import SwiftUI

/// 性能自检:跑固定 prompt,展示当前后端(MNN·SME2 / MNN·NEON / MLX·GPU)的
/// prefill / decode 实测速度,并按后端存档对比 —— 挑战赛考核点的可见证据(§12 卖点 2/6)。
struct ModelSelfTestView: View {
    @State private var output = ""
    @State private var phase: Phase = .idle
    @State private var rate: Double = 0
    @State private var lastResult: BenchmarkResult?
    @State private var history: [String: BenchmarkResult] = [:]

    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 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 {
        ScrollView {
            VStack(alignment: .leading, spacing: 16) {
                promptCard

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

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

                if isBusy { AIFlowBar() }

                if let r = lastResult { statsCard(r) }

                outputCard

                if !history.isEmpty { historyCard }
            }
            .padding(16)
        }
        .background(Tj.Palette.sand.ignoresSafeArea())
        .navigationTitle("性能自检")
        .navigationBarTitleDisplayMode(.inline)
        .onAppear { history = BenchmarkService.load() }
    }

    private var promptCard: some View {
        VStack(alignment: .leading, spacing: 6) {
            Text("测试 PROMPT")
                .font(.tjScaled( 11, weight: .semibold))
                .tracking(0.5)
                .foregroundStyle(Tj.Palette.text3)
            Text(BenchmarkService.fixedPrompt)
                .font(.tjScaled( 14))
                .foregroundStyle(Tj.Palette.text)
        }
        .padding(14)
        .frame(maxWidth: .infinity, alignment: .leading)
        .tjCard()
    }

    private func statsCard(_ r: BenchmarkResult) -> some View {
        VStack(alignment: .leading, spacing: 10) {
            HStack {
                Text("本次结果")
                    .font(.tjScaled( 12, weight: .semibold))
                    .foregroundStyle(Tj.Palette.text2)
                Spacer()
                TjBadge(text: r.backendLabel, style: .leaf)
            }
            HStack(spacing: 0) {
                metric(String(appLoc: "读入"), r.prefillTokensPerSecond > 0
                       ? String(format: "%.0f tok/s", r.prefillTokensPerSecond) : "—")
                metric(String(appLoc: "生成"), String(format: "%.1f tok/s", r.decodeTokensPerSecond))
                metric(String(appLoc: "总耗时"), String(format: "%.1fs", r.totalSeconds))
            }
            Text(String(appLoc: "prompt \(r.promptTokens) tok · 生成 \(r.genTokens) tok · 100% 本地"))
                .font(.tjScaled( 10, design: .monospaced))
                .foregroundStyle(Tj.Palette.text3)
        }
        .padding(14)
        .frame(maxWidth: .infinity, alignment: .leading)
        .tjCard()
    }

    private func metric(_ label: String, _ value: String) -> some View {
        VStack(spacing: 3) {
            Text(value)
                .font(.tjScaled( 15, weight: .semibold, design: .monospaced))
                .foregroundStyle(Tj.Palette.text)
            Text(label)
                .font(.tjScaled( 10))
                .foregroundStyle(Tj.Palette.text3)
        }
        .frame(maxWidth: .infinity)
    }

    private var outputCard: some View {
        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: 220)
        .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)
        )
    }

    private var historyCard: some View {
        VStack(alignment: .leading, spacing: 10) {
            Text("各引擎实测对比")
                .font(.tjScaled( 12, weight: .semibold))
                .foregroundStyle(Tj.Palette.text2)
            ForEach(history.keys.sorted(), id: \.self) { key in
                if let r = history[key] {
                    HStack {
                        Text(key)
                            .font(.tjScaled( 12, weight: .medium))
                            .foregroundStyle(Tj.Palette.text)
                        Spacer()
                        Text(String(format: String(appLoc: "生成 %.1f tok/s"), r.decodeTokensPerSecond))
                            .font(.tjScaled( 12, design: .monospaced))
                            .foregroundStyle(Tj.Palette.leaf)
                        Text(r.date.formatted(.dateTime.month().day()))
                            .font(.tjScaled( 10))
                            .foregroundStyle(Tj.Palette.text3)
                    }
                }
            }
            Text("在「我的 · 推理引擎」切换引擎后再跑一次,即可对比 SME2 与 GPU。")
                .font(.tjScaled( 10))
                .foregroundStyle(Tj.Palette.text3)
        }
        .padding(14)
        .frame(maxWidth: .infinity, alignment: .leading)
        .tjCard()
    }

    @MainActor
    private func run() async {
        output = ""
        rate = 0
        lastResult = nil
        phase = .loading
        do {
            let result = try await BenchmarkService.shared.run { piece, r in
                output += piece
                if r > 0 { rate = r }
                if phase == .loading { phase = .running }
            }
            lastResult = result
            history = BenchmarkService.load()
            phase = .done
        } catch {
            phase = .failed(error.localizedDescription)
        }
    }
}

#Preview {
    NavigationStack { ModelSelfTestView() }
}
