//
//  AppServerAllocateView.swift
//  aoqdemo
//
//  AppServer /api/v1/allocate 接口的可复用 UI 组件。
//  在音频设备API、视频设备API、链接API、AI通话等页面中均可嵌入。
//

import SwiftUI
import Foundation
import AoqClientSdk

// MARK: - Allocate Response Model

struct AllocateExtraInfo: Codable {
    let workspaceIdHash: String?
}

/* relay 接入点元素，与服务器返回的 clientRelayEndpoints 数组元素对齐。 */
struct ClientRelayEndpoint: Codable {
    let endpoint: String
    let port: Int
}

struct AllocateResponse: Codable {
    let sid: String
    let aoqTokenForClient: String
    let aoqTokenForServer: String?
    /* 服务器返回的 relay 接入点数组 */
    let clientRelayEndpoints: [ClientRelayEndpoint]
    let clientRelayCertFingerprint: String
    let serverRelayEndpoint: String?
    let serverRelayPort: Int?
    let serverRelayCertFingerprint: String?
    let sidExpiresInSecs: Int?
    let extraInfo: AllocateExtraInfo?
}

// MARK: - AppServer Service

enum AppServerService {

    /// POST {baseURL}{AppServerConfig.allocatePath}  body: {"model": model}
    static func allocate(baseURL: String, model: String) async throws -> AllocateResponse {
        let fullURL = AppServerConfig.allocateURL(from: baseURL)
        guard let url = URL(string: fullURL) else {
            throw URLError(.badURL)
        }

        var request = URLRequest(url: url)
        request.httpMethod = "POST"
        request.setValue("application/json", forHTTPHeaderField: "Content-Type")
        request.httpBody = try JSONSerialization.data(withJSONObject: ["model": model])

        let (data, response) = try await URLSession.shared.data(for: request)

        if let httpResp = response as? HTTPURLResponse, !(200..<300).contains(httpResp.statusCode) {
            let bodyStr = String(data: data, encoding: .utf8) ?? ""
            throw NSError(domain: "AppServer", code: httpResp.statusCode,
                          userInfo: [NSLocalizedDescriptionKey: "HTTP \(httpResp.statusCode): \(bodyStr)"])
        }
        return try JSONDecoder().decode(AllocateResponse.self, from: data)
    }
}

// MARK: - Reusable Allocate Section (CardSection style for iOS)

/// 可嵌入各页面的 AppServer 配置获取组件。
/// 获取成功后自动填充绑定的 token / sid / certificate / relayEndpointsJSON / workspaceIdHash。
struct AppServerAllocateSection: View {
    @Binding var token: String
    @Binding var sid: String
    @Binding var certificate: String
    /* relay 接入点列表的 JSON 表示，格式如 [{"endpoint":"ip","port":8443}] */
    @Binding var relayEndpointsJSON: String
    @Binding var workspaceIdHash: String

    @State private var model: String = "qwen3.5-omni-plus-realtime"
    @State private var isLoading: Bool = false
    @State private var statusMessage: String = ""
    @State private var isError: Bool = false

    var body: some View {
        CardSection(title: "AppServer 配置获取") {
            HStack {
                Text("URL")
                    .font(.caption)
                    .foregroundStyle(.secondary)
                Text(AppServerConfig.currentAllocateURL)
                    .font(.caption)
                    .foregroundStyle(.secondary)
                    .lineLimit(1)
                    .truncationMode(.middle)
                    .textSelection(.enabled)
            }

            LabeledInput(label: "Model", text: $model, placeholder: "模型名称")

            HStack(spacing: 8) {
                Button("获取配置") {
                    Task { await allocate() }
                }
                .buttonStyle(.borderedProminent)
                .disabled(isLoading || model.isEmpty)

                if isLoading {
                    ProgressView()
                        .controlSize(.small)
                }

                if !statusMessage.isEmpty {
                    Text(statusMessage)
                        .font(.caption)
                        .foregroundStyle(isError ? .red : .green)
                        .lineLimit(2)
                        .truncationMode(.tail)
                }
            }
        }
    }

    // MARK: Private

    private func allocate() async {
        isLoading = true
        statusMessage = ""
        isError = false

        do {
            let resp = try await AppServerService.allocate(
                baseURL: AppServerConfig.currentBaseURL,
                model: model
            )
            token = resp.aoqTokenForClient
            sid = resp.sid
            certificate = resp.clientRelayCertFingerprint
            relayEndpointsJSON = Self.prettyJSON(for: resp.clientRelayEndpoints)
            workspaceIdHash = resp.extraInfo?.workspaceIdHash ?? ""
            statusMessage = "配置获取成功"
        } catch {
            statusMessage = error.localizedDescription
            isError = true
        }
        isLoading = false
    }

    /* 将 relay 接入点数组序列化为可读的 pretty JSON，供 UI 展示与用户编辑。 */
    private static func prettyJSON(for endpoints: [ClientRelayEndpoint]) -> String {
        let encoder = JSONEncoder()
        encoder.outputFormatting = [.prettyPrinted]
        if let data = try? encoder.encode(endpoints),
           let str = String(data: data, encoding: .utf8) {
            return str
        }
        return "[]"
    }
}

/* 将用户输入的 JSON 文本解析为 SDK 所需的 AoqRelayEndpoint 数组。
   解析失败返回空数组，由调用方自行处理。 */
func parseRelayEndpoints(json: String) -> [AoqRelayEndpoint] {
    guard let data = json.data(using: .utf8) else { return [] }
    let parsed = (try? JSONDecoder().decode([ClientRelayEndpoint].self, from: data)) ?? []
    return parsed.map { item in
        let ep = AoqRelayEndpoint()
        ep.endpoint = item.endpoint
        ep.port = item.port
        return ep
    }
}
