import AVFoundation
import SwiftUI

struct TestView: View {
    @ObservedObject var controller: PlayerController
    let onFullscreen: () -> Void

    @State private var recorder: AVAudioRecorder?
    @State private var recordingURL: URL?
    @State private var isRecording = false
    @State private var isAssessing = false
    @State private var testStatus = "请先在训练模块选择一个云端课程"
    @State private var scoreSummary = "尚未评测"
    @State private var scoreDetail = ""

    var body: some View {
        ScrollView(showsIndicators: false) {
            VStack(spacing: 0) {
                PlayerSectionView(
                    controller: controller,
                    showsContinuousToggle: false,
                    continuousPlayback: .constant(true),
                    onFullscreen: onFullscreen
                )
                VStack(alignment: .leading, spacing: 10) {
                Text("朗读评测（测试）")
                    .font(.system(size: 16, weight: .bold))
                    .foregroundColor(Theme.textDark)
                Text(testStatus)
                    .font(.system(size: 13))
                    .foregroundColor(Theme.accentDeep)
                    .fixedSize(horizontal: false, vertical: true)
                HStack(spacing: 8) {
                    sentenceButton("上一句") {
                        controller.seekToPreviousSentence()
                    }
                    sentenceButton("播放原句") {
                        controller.playCurrentSentenceAndStop()
                        controller.showTransientMessage("正在播放当前句子，播放完自动停止")
                    }
                    sentenceButton("下一句") {
                        controller.seekToNextSentence()
                    }
                }
                Button(action: toggleRecording) {
                    Text(isRecording ? "停止并评测" : "开始录音")
                        .font(.system(size: 14, weight: .bold))
                        .foregroundColor(.white)
                        .frame(maxWidth: .infinity)
                        .frame(height: 44)
                        .background(isRecording ? Theme.buttonBlue : Theme.accent)
                        .clipShape(RoundedRectangle(cornerRadius: 8))
                }
                .buttonStyle(.plain)
                .disabled(isAssessing)
                Text(scoreSummary)
                    .font(.system(size: 22, weight: .bold))
                    .foregroundColor(Theme.textDark)
                Text(scoreDetail)
                    .font(.system(size: 13))
                    .foregroundColor(Theme.textSubtle)
                    .lineSpacing(4)
                    .frame(maxWidth: .infinity, alignment: .leading)
            }
            .padding(18)
            .background(Color.white)
            .clipShape(RoundedRectangle(cornerRadius: 8))
            .overlay(
                RoundedRectangle(cornerRadius: 8)
                    .stroke(Theme.lightBorder, lineWidth: 1)
            )
                .padding(16)
            }
        }
        .onReceive(controller.$currentItem) { _ in
            refreshTestUI()
        }
        .onReceive(controller.$currentSentence) { _ in
            refreshTestUI()
        }
    }

    private func sentenceButton(_ label: String, action: @escaping () -> Void) -> some View {
        Button(action: action) {
            Text(label)
                .font(.system(size: 13, weight: .bold))
                .foregroundColor(.white)
                .frame(maxWidth: .infinity)
                .frame(height: 40)
                .background(Theme.buttonBlue)
                .clipShape(RoundedRectangle(cornerRadius: 8))
        }
        .buttonStyle(.plain)
    }

    // MARK: - 录音

    private func toggleRecording() {
        if isRecording {
            stopRecordingAndAssess()
        } else {
            startRecording()
        }
    }

    private func startRecording() {
        controller.pause()
        requestMicrophonePermission { granted in
            guard granted else {
                testStatus = "需要麦克风权限才能进行录音评测"
                return
            }
            beginRecording()
        }
    }

    private func requestMicrophonePermission(completion: @escaping (Bool) -> Void) {
        if #available(iOS 17.0, *) {
            AVAudioApplication.requestRecordPermission { granted in
                DispatchQueue.main.async {
                    completion(granted)
                }
            }
        } else {
            AVAudioSession.sharedInstance().requestRecordPermission { granted in
                DispatchQueue.main.async {
                    completion(granted)
                }
            }
        }
    }

    private func beginRecording() {
        let fileURL = FileManager.default.temporaryDirectory
            .appendingPathComponent("attempt-\(Int(Date().timeIntervalSince1970 * 1000)).m4a")
        let settings: [String: Any] = [
            AVFormatIDKey: Int(kAudioFormatMPEG4AAC),
            AVSampleRateKey: 16_000,
            AVNumberOfChannelsKey: 1,
            AVEncoderBitRateKey: 96_000,
            AVEncoderAudioQualityKey: AVAudioQuality.medium.rawValue,
        ]
        do {
            let session = AVAudioSession.sharedInstance()
            try session.setCategory(.playAndRecord, mode: .default, options: [.defaultToSpeaker])
            try session.setActive(true)
            let newRecorder = try AVAudioRecorder(url: fileURL, settings: settings)
            guard newRecorder.record() else {
                testStatus = "录音启动失败：无法开始录制"
                return
            }
            recorder = newRecorder
            recordingURL = fileURL
            isRecording = true
            testStatus = "正在录音…读完当前句子后点击“停止并评测”"
        } catch {
            testStatus = "录音启动失败：\(error.localizedDescription)"
        }
    }

    private func stopRecordingAndAssess() {
        guard let currentRecorder = recorder else {
            return
        }
        let duration = currentRecorder.currentTime
        currentRecorder.stop()
        restorePlaybackAudioSession()
        recorder = nil
        isRecording = false
        guard let url = recordingURL else {
            return
        }
        recordingURL = nil
        if duration < 1.0 {
            testStatus = "录音太短或无法保存"
            try? FileManager.default.removeItem(at: url)
            return
        }
        submitAssessment(recordingURL: url)
    }

    private func restorePlaybackAudioSession() {
        let session = AVAudioSession.sharedInstance()
        try? session.setCategory(.playback, mode: .moviePlayback)
        try? session.setActive(true)
    }

    // MARK: - 评测

    private func submitAssessment(recordingURL url: URL) {
        guard let item = controller.currentItem, let sentence = controller.currentSentence else {
            testStatus = "没有正在学习的句子，无法评测"
            return
        }
        guard item.id.range(of: AppConfig.sha256Pattern, options: .regularExpression) != nil else {
            testStatus = "仅云端课程支持朗读评测（本地视频请先上传到服务器）"
            return
        }
        guard !AppConfig.assessmentAPIKey.isEmpty,
              !AppConfig.assessmentAPIKey.hasPrefix("replace-") else {
            testStatus = "未配置评分密钥：请在 Config.swift 填入服务器 .env 的 CLIENT_API_KEY"
            return
        }
        testStatus = "正在评测第 \(sentence.index + 1) 句，请稍候…"
        scoreSummary = "评测中…"
        scoreDetail = ""
        isAssessing = true
        let request = ImitationAssessmentRequest(
            mediaId: item.id,
            sentence: sentence,
            recordingURL: url,
            locale: sentence.language?.isEmpty == false ? sentence.language : nil
        )
        Task {
            do {
                let result = try await ImitationAssessor.assess(request: request)
                applyAssessmentResult(result)
            } catch {
                testStatus = "评测失败：\(error.localizedDescription)"
                scoreSummary = "评测失败"
            }
            isAssessing = false
            try? FileManager.default.removeItem(at: url)
        }
    }

    private func applyAssessmentResult(_ result: ImitationAssessmentResult) {
        testStatus = result.passed == true ? "已通过" : "未通过"
        scoreSummary = String(format: "总分 %.1f", result.overallScore)
        var lines: [String] = []
        if let value = result.contentScore {
            lines.append(String(format: "内容分 %.1f", value))
        }
        if let value = result.fluencyScore {
            lines.append(String(format: "流畅度 %.1f", value))
        }
        if let value = result.durationScore {
            lines.append(String(format: "时长分 %.1f", value))
        }
        if let value = result.pauseScore {
            lines.append(String(format: "停顿分 %.1f", value))
        }
        if let value = result.speechRateScore {
            lines.append(String(format: "语速分 %.1f", value))
        }
        if let text = result.referenceText, !text.isEmpty {
            lines.append("参考：\(text)")
        }
        if let text = result.recognizedText, !text.isEmpty {
            lines.append("识别：\(text)")
        }
        if !result.missingTokens.isEmpty {
            lines.append("漏读：\(result.missingTokens.joined(separator: "、"))")
        }
        if !result.extraTokens.isEmpty {
            lines.append("多读：\(result.extraTokens.joined(separator: "、"))")
        }
        if let feedback = result.feedback, !feedback.isEmpty {
            lines.append(feedback)
        }
        scoreDetail = lines.joined(separator: "\n")
    }

    private func refreshTestUI() {
        guard !isRecording, !isAssessing else {
            return
        }
        guard let item = controller.currentItem, let sentence = controller.currentSentence else {
            testStatus = "请先在训练模块选择一个云端课程"
            return
        }
        testStatus = "评测对象：第 \(sentence.index + 1) 句（共 \(item.sentences.count) 句）"
    }
}
