import Foundation
import AIFabric
import DSKit

/// S3-owned concrete `DSAskClient` (the HTTP seam S2's `RemoteDSProvider` calls). Hits DS
/// `GET /search/ask?q=&backend=` and decodes **AIFabric.AskResponse** (a decode-only type that
/// RemoteDSProvider maps to AICompletionResponse). This is the piece S2's plan assigns to S3
/// ("구체 DSAskClient(HTTP) = S3 소유"). FU-A: exercised only when the real router is wired.
public struct LiveDSAskClient: DSAskClient {
    private let base: DSBaseURL
    private let session: URLSession
    private let decoder: JSONDecoder
    private let token: @Sendable () async -> String?

    public init(
        base: DSBaseURL = .publicTLS,
        session: URLSession = .shared,
        token: @escaping @Sendable () async -> String? = { nil }
    ) {
        self.base = base
        self.session = session
        self.decoder = DSDecoder.make()
        self.token = token
    }

    public func ask(query: String, backend: String) async throws -> AIFabric.AskResponse {
        let raw = base.url.absoluteString + "/search/ask"
        guard var comps = URLComponents(string: raw) else {
            throw DSError.transport(underlying: "bad ask URL")
        }
        comps.queryItems = [
            URLQueryItem(name: "q", value: query),
            URLQueryItem(name: "backend", value: backend),
        ]
        guard let url = comps.url else { throw DSError.transport(underlying: "bad ask URL components") }

        var request = URLRequest(url: url)
        if let token = await token() {
            request.setValue("Bearer \(token)", forHTTPHeaderField: "Authorization")
        }
        let (data, response) = try await session.data(for: request)
        guard let http = response as? HTTPURLResponse else {
            throw DSError.transport(underlying: "no HTTP response")
        }
        guard (200..<300).contains(http.statusCode) else {
            throw DSError.from(status: http.statusCode, data: data)
        }
        return try decoder.decode(AIFabric.AskResponse.self, from: data)
    }
}
