import SwiftUI
import SwiftData
import UIKit

/// 指标速记 · 统一流程。
/// 整幅单拍(真机)/ 相册(模拟器)→ 静态图手动框选 → 框内 OCR+LLM 抽指标 → 核对 → 存独立 Indicator。
///
/// 状态机:
/// ```
/// idle(相机/相册) → adjust(静态图框选,可反复识别) → confirm(核对) → save → dismiss
///                                                     confirm → 重拍 → idle
/// ```
/// 识别失败/超时不卡死:停在 adjust 提示挪框重试,或直接进 confirm 手动补(§3.2 失败回退红线)。
struct QuickRegionCaptureFlow: View {
    @Environment(\.modelContext) private var ctx
    let onClose: () -> Void

    @State private var phase: Phase = .idle

    enum Phase {
        case idle
        case adjust(image: UIImage)
        case confirm(image: UIImage?, items: [QuickRegionItem], warning: String?)
    }

    var body: some View {
        content
            .background(Tj.Palette.sand.ignoresSafeArea())
    }

    @ViewBuilder
    private var content: some View {
        switch phase {
        case .idle:
            // 不再整体 ignoresSafeArea:相机/框选内部已各自做全屏黑底,
            // 这里再忽略安全区会把「取消」顶进灵动岛,几乎点不到。
            captureEntry

        case .adjust(let image):
            RegionAdjustView(
                image: image,
                recognize: { await recognizeRegion($0) },
                onProceed: { items in
                    phase = .confirm(image: image, items: items, warning: nil)
                },
                onRetake: { phase = .idle },
                onCancel: { onClose() }
            )

        case .confirm(let image, let items, let warning):
            NavigationStack {
                QuickRegionConfirmView(
                    image: image,
                    items: items,
                    warning: warning,
                    onSave: { finalItems, capturedAt in save(items: finalItems, capturedAt: capturedAt) },
                    onCancel: { onClose() },
                    onRetake: { phase = .idle }
                )
                .navigationTitle(String(appLoc: "核对指标"))
                .navigationBarTitleDisplayMode(.inline)
                .toolbar {
                    ToolbarItem(placement: .topBarLeading) {
                        Button("取消") { onClose() }
                            .foregroundStyle(Tj.Palette.text)
                    }
                }
            }
        }
    }

    // MARK: - 入口:整幅单拍(真机)/ 相册(模拟器或无相机)

    @ViewBuilder
    private var captureEntry: some View {
        #if targetEnvironment(simulator)
        PhotoPickerSheet(
            onFinish: { handlePicked($0) },
            onCancel: onClose
        )
        #else
        SingleShotCameraView(
            onCapture: { phase = .adjust(image: $0) },
            onCancel: onClose
        )
        #endif
    }

    /// 拍/选回来:取首张进框选;无图则关闭(「只能拍一张」=只用第一张)。
    private func handlePicked(_ images: [UIImage]) {
        if let first = images.first {
            phase = .adjust(image: first)
        } else {
            onClose()
        }
    }

    // MARK: - 识别(框内子图 → Vision OCR → Qwen3 整理)

    /// 对已裁好的框内子图跑识别。失败/超时返回提示文案,绝不抛出(由 RegionAdjustView 展示)。
    /// 固定链路:Vision 端侧 OCR 出文字 → Qwen3 跑一次结构化整理抽指标。
    /// (旧的「大模型直读」VL 路径已移除:端侧看图慢且易卡,OCR→整理又快又准。)
    private func recognizeRegion(_ image: UIImage) async -> (items: [QuickRegionItem], warning: String?) {
        do {
            let text = try await OCRService.recognizeText(in: image)
            if Task.isCancelled { return ([], nil) }   // 超时:文案由调用方给
            let trimmed = text.trimmingCharacters(in: .whitespacesAndNewlines)
            #if DEBUG
            NSLog("KKDBG-OCR region text:\n%@\n--- end OCR ---", trimmed)
            #endif
            if trimmed.isEmpty {
                return ([], String(appLoc: "没识别到文字,挪一下框再试"))
            }
            let parsed = try await CaptureService.shared.recognizeIndicators(fromOCRText: trimmed)
            if Task.isCancelled { return ([], nil) }
            let items = Self.buildItems(from: parsed)
            return (items, items.isEmpty ? String(appLoc: "没读出指标,挪一下框再试") : nil)
        } catch CaptureError.modelNotReady {
            return ([], String(appLoc: "AI 模型未就绪,手动补充"))
        } catch CaptureError.parseFailed {
            // 已回退手动录入,给用户友好提示;技术细节留在 CaptureService 的 DEBUG 日志。
            return ([], String(appLoc: "没自动认出指标,挪一下框再试,或手动填写"))
        } catch CaptureError.inferenceFailed {
            return ([], Task.isCancelled ? nil : String(appLoc: "识别没成功,挪一下框再试,或手动填写"))
        } catch {
            return ([], Task.isCancelled ? nil : String(appLoc: "识别没成功,请手动填写"))
        }
    }

    /// LLM 结果 → 可编辑行,异常项(high/low)置顶、默认勾选。
    private static func buildItems(from parsed: [ParsedReport.ParsedIndicator]) -> [QuickRegionItem] {
        let mapped = parsed.map {
            QuickRegionItem(name: $0.name, value: $0.value, unit: $0.unit,
                            range: $0.range, status: $0.status, include: true)
        }
        return mapped.enumerated().sorted { a, b in
            let aAbn = a.element.status != .normal
            let bAbn = b.element.status != .normal
            if aAbn != bAbn { return aAbn && !bAbn }
            return a.offset < b.offset
        }.map { $0.element }
    }

    // MARK: - 保存

    /// 勾选项各存一条独立 Indicator(与「记录指标」自由输入一致):无 Report、无 Asset、无 seriesKey。
    private func save(items: [QuickRegionItem], capturedAt: Date) {
        let selected = items.filter {
            $0.include
            && !$0.name.trimmingCharacters(in: .whitespaces).isEmpty
            && !$0.value.trimmingCharacters(in: .whitespaces).isEmpty
        }
        for item in selected {
            let indicator = Indicator(
                name: item.name.trimmingCharacters(in: .whitespaces),
                value: item.value.trimmingCharacters(in: .whitespaces),
                unit: item.unit.trimmingCharacters(in: .whitespaces),
                range: item.range.trimmingCharacters(in: .whitespaces),
                status: item.status,
                capturedAt: capturedAt,
                source: .quickCapture
            )
            ctx.insert(indicator)
        }
        try? ctx.save()
        onClose()
    }
}
