import SwiftUI

/// 模型推理自检:加载 LLM 跑一段固定 prompt,流式显示输出 + tok/s。
/// 模型就绪后从「我的 · 模型管理」进入,用于现场快速验证本地推理是否正常。
struct ModelSelfTestView: View {
    @State private var output = ""
    @State private var phase: Phase = .idle
    @State private var rate: Double = 0

    private enum Phase: Equatable {
        case idle, loading, running, done, failed(String)

        var label: String {
            switch self {
            case .idle:            return String(appLoc: "未开始")
            case .loading:         return String(appLoc: "加载模型…")
            case .running:         return String(appLoc: "推理中…")
            case .done:            return String(appLoc: "完成 ✓")
            case .failed(let m):   return String(appLoc: "失败:\(m)")
            }
        }
    }

    private let prompt = "用中文一句话介绍肝功能里 ALT 这个指标。"

    private var isBusy: Bool { phase == .loading || phase == .running }

    private var statusColor: Color {
        switch phase {
        case .failed: return Tj.Palette.brick
        case .done:   return Tj.Palette.leaf
        default:      return Tj.Palette.text2
        }
    }

    var body: some View {
        VStack(alignment: .leading, spacing: 16) {
            VStack(alignment: .leading, spacing: 6) {
                Text("测试 PROMPT")
                    .font(.system(size: 11, weight: .semibold))
                    .tracking(0.5)
                    .foregroundStyle(Tj.Palette.text3)
                Text(prompt)
                    .font(.system(size: 14))
                    .foregroundStyle(Tj.Palette.text)
            }
            .padding(14)
            .frame(maxWidth: .infinity, alignment: .leading)
            .tjCard()

            HStack {
                Text(phase.label)
                    .font(.system(size: 13, weight: .medium))
                    .foregroundStyle(statusColor)
                    .lineLimit(1)
                Spacer()
                if rate > 0 {
                    Text(String(format: "%.1f tok/s", rate))
                        .font(.system(size: 12, design: .monospaced))
                        .foregroundStyle(Tj.Palette.text3)
                }
            }

            Button {
                Task { await run() }
            } label: {
                Text(isBusy ? "运行中…" : "运行推理自检").frame(maxWidth: .infinity)
            }
            .buttonStyle(TjPrimaryButton())
            .disabled(isBusy)

            ScrollView {
                Text(output.isEmpty ? "(暂无输出)" : output)
                    .font(.system(.footnote, design: .monospaced))
                    .foregroundStyle(Tj.Palette.text)
                    .frame(maxWidth: .infinity, alignment: .leading)
                    .textSelection(.enabled)
                    .padding(12)
            }
            .frame(maxHeight: 280)
            .background(
                RoundedRectangle(cornerRadius: Tj.Radius.md, style: .continuous)
                    .fill(Tj.Palette.paper)
            )
            .overlay(
                RoundedRectangle(cornerRadius: Tj.Radius.md, style: .continuous)
                    .strokeBorder(Tj.Palette.lineSoft, lineWidth: 1)
            )

            Spacer()
        }
        .padding(16)
        .background(Tj.Palette.sand.ignoresSafeArea())
        .navigationTitle("推理自检")
        .navigationBarTitleDisplayMode(.inline)
    }

    @MainActor
    private func run() async {
        output = ""
        rate = 0
        phase = .loading
        do {
            try await AIRuntime.shared.prepare()
            phase = .running
            for try await chunk in await AIRuntime.shared.generate(prompt: prompt, maxTokens: 200) {
                output += chunk.text
                rate = chunk.decodeRate
            }
            phase = .done
        } catch {
            phase = .failed(error.localizedDescription)
        }
    }
}

#Preview {
    NavigationStack { ModelSelfTestView() }
}
