import Foundation
import SwiftData

/// 报告大白话摘要预生成(§3.1:流程经本服务碰 AIRuntime,UI 不直接调)。
/// 时机:归档保存后立即后台跑(用户继续操作时完成);详情页打开时兜底重试。
/// 写回策略:只在 summary 为空时生成 —— 绝不覆盖 VL 已给出或用户编辑过的摘要。
@MainActor
final class ReportInsightService {
    static let shared = ReportInsightService()
    private init() {}

    /// 进行中的报告 ID,防止「保存后台任务」与「详情页兜底」重复触发。
    private var inFlight: Set<String> = []

    func pregenerateIfNeeded(report: Report, in ctx: ModelContext) async {
        guard (report.summary ?? "").isEmpty, !report.indicators.isEmpty else { return }
        let key = String(describing: report.persistentModelID)
        guard !inFlight.contains(key) else { return }
        inFlight.insert(key)
        defer { inFlight.remove(key) }

        do {
            try await AIRuntime.shared.prepare()
        } catch {
            return   // 模型未就绪:静默放弃,详情页下次打开再试
        }

        let prompt = InsightPrompts.reportPlainSummary(
            title: report.title,
            typeLabel: report.type.label,
            indicatorLines: Self.indicatorLines(for: report.indicators)
        )
        var collected = ""
        do {
            let stream = await AIRuntime.shared.generate(
                prompt: prompt, maxTokens: 200, priority: .background)
            for try await chunk in stream { collected += chunk.text }
        } catch {
            return   // 被前台任务抢占(CancellationError)或推理失败:放弃,兜底路径再试
        }
        let text = HealthExportService.stripThinkBlocks(collected)
            .trimmingCharacters(in: .whitespacesAndNewlines)
        guard !text.isEmpty, (report.summary ?? "").isEmpty else { return }
        report.summary = text
        try? ctx.save()
    }

    /// 「名 值 单位(参考 range)status」每指标一行;异常项排前,上限 15 行控 prompt 体积。
    static func indicatorLines(for indicators: [Indicator]) -> String {
        let sorted = indicators.sorted {
            ($0.status == .normal ? 1 : 0) < ($1.status == .normal ? 1 : 0)
        }
        return sorted.prefix(15).map { i in
            var line = "\(i.name) \(i.value)"
            if !i.unit.isEmpty { line += " \(i.unit)" }
            if !i.range.isEmpty { line += "(参考 \(i.range))" }
            line += " \(i.status.rawValue)"
            return line
        }.joined(separator: "\n")
    }
}
