import Testing
import Foundation
@testable import 康康

struct CaptureServiceJSONTests {

    @Test func parsesCleanJSON() throws {
        let raw = """
        {"title":"春检","type":"checkup","report_date":"2026-04-12","institution":"协和","page_count":2,"summary":"血脂偏高","indicators":[{"name":"LDL-C","value":"3.84","unit":"mmol/L","range":"< 3.40","status":"high"}]}
        """
        let parsed = try CaptureService.parseReportJSON(raw)
        #expect(parsed.title == "春检")
        #expect(parsed.typeRaw == ReportType.checkup.rawValue)
        #expect(parsed.institution == "协和")
        #expect(parsed.pageCount == 2)
        #expect(parsed.indicators.count == 1)
        #expect(parsed.indicators.first?.status == .high)
    }

    @Test func stripsMarkdownCodeFence() throws {
        let raw = """
        ```json
        {"title":"x","type":"lab","report_date":"2026-05-01","institution":"","page_count":1,"summary":"","indicators":[]}
        ```
        """
        let parsed = try CaptureService.parseReportJSON(raw)
        #expect(parsed.title == "x")
        #expect(parsed.typeRaw == ReportType.lab.rawValue)
        #expect(parsed.indicators.isEmpty)
    }

    @Test func extractsObjectAfterLeadingText() throws {
        let raw = """
        好的,识别结果如下:
        {"title":"y","type":"lab","report_date":"2026-05-01","institution":"","page_count":1,"summary":"","indicators":[]}
        以上。
        """
        let parsed = try CaptureService.parseReportJSON(raw)
        #expect(parsed.title == "y")
    }

    @Test func handlesNestedBraces() throws {
        let raw = """
        {"title":"y","type":"lab","report_date":"2026-05-01","institution":"","page_count":1,"summary":"含嵌套{x}对象","indicators":[]}
        """
        let parsed = try CaptureService.parseReportJSON(raw)
        #expect(parsed.summary == "含嵌套{x}对象")
    }

    @Test func handlesEscapedQuotesInStrings() throws {
        let raw = #"{"title":"y \"内嵌\" 引号","type":"lab","report_date":"2026-05-01","institution":"","page_count":1,"summary":"","indicators":[]}"#
        let parsed = try CaptureService.parseReportJSON(raw)
        #expect(parsed.title == #"y "内嵌" 引号"#)
    }

    @Test func fillsDefaultsForMissingFields() throws {
        // 缺 title / type / report_date / institution / summary / page_count
        let raw = """
        {"indicators":[{"name":"X","value":"1","unit":"","range":"","status":"normal"}]}
        """
        let parsed = try CaptureService.parseReportJSON(raw)
        #expect(parsed.title == "拍摄识别")  // 默认值
        #expect(parsed.typeRaw == ReportType.other.rawValue)
        #expect(parsed.indicators.count == 1)
    }

    @Test func skipsIndicatorsWithEmptyName() throws {
        let raw = """
        {"title":"t","type":"lab","report_date":"2026-05-01","institution":"","page_count":1,"summary":"","indicators":[
          {"name":"","value":"1","unit":"","range":"","status":"normal"},
          {"name":"  ","value":"1","unit":"","range":"","status":"normal"},
          {"name":"OK","value":"1","unit":"","range":"","status":"normal"}
        ]}
        """
        let parsed = try CaptureService.parseReportJSON(raw)
        #expect(parsed.indicators.count == 1)
        #expect(parsed.indicators.first?.name == "OK")
    }

    @Test func malformedJSONThrows() {
        let raw = "完全不是 JSON"
        #expect(throws: CaptureError.self) {
            _ = try CaptureService.parseReportJSON(raw)
        }
    }

    @Test func valueAsNumberStillParses() throws {
        let raw = """
        {"title":"t","type":"lab","report_date":"2026-05-01","institution":"","page_count":1,"summary":"","indicators":[{"name":"X","value":3.84,"unit":"","range":"","status":"high"}]}
        """
        let parsed = try CaptureService.parseReportJSON(raw)
        #expect(parsed.indicators.first?.value == "3.84")
    }

    @Test func unknownStatusFallsBackToNormal() throws {
        let raw = """
        {"title":"t","type":"lab","report_date":"2026-05-01","institution":"","page_count":1,"summary":"","indicators":[{"name":"X","value":"1","unit":"","range":"","status":"abnormal"}]}
        """
        let parsed = try CaptureService.parseReportJSON(raw)
        #expect(parsed.indicators.first?.status == .normal)
    }

    @Test func parsesRegionJSONWithChineseKeysAndArrowStatus() throws {
        let raw = """
        {"指标":[{"项目":"尿酸","结果":"486","单位":"μmol/L","参考范围":"208 - 428","异常":"↑"}]}
        """
        let indicators = try CaptureService.parseIndicatorsJSON(raw)
        #expect(indicators.count == 1)
        #expect(indicators.first?.name == "尿酸")
        #expect(indicators.first?.value == "486")
        #expect(indicators.first?.unit == "μmol/L")
        #expect(indicators.first?.range == "208 - 428")
        #expect(indicators.first?.status == .high)
    }

    @Test func parsesReportJSONWithChineseIndicatorArrayKey() throws {
        let raw = """
        {"title":"t","type":"lab","report_date":"2026-05-01","指标":[{"项目":"尿酸","结果":"486","单位":"μmol/L","参考范围":"208 - 428","异常":"偏高"}]}
        """
        let parsed = try CaptureService.parseReportJSON(raw)
        #expect(parsed.indicators.count == 1)
        #expect(parsed.indicators.first?.name == "尿酸")
        #expect(parsed.indicators.first?.status == .high)
    }

    @Test func parsesIndicatorEvidenceLocation() throws {
        let raw = """
        {"title":"t","type":"lab","report_date":"2026-05-01","page_count":2,"indicators":[{"name":"尿酸","value":"486","unit":"μmol/L","range":"208 - 428","status":"high","source_page":2,"source_box":[0.18,0.42,0.68,0.49]}]}
        """
        let parsed = try CaptureService.parseReportJSON(raw, pageCount: 2)
        let indicator = try #require(parsed.indicators.first)
        #expect(indicator.sourcePageIndex == 1)
        #expect(indicator.sourceBoxX == 0.18)
        #expect(indicator.sourceBoxY == 0.42)
        #expect(indicator.sourceBoxWidth == 0.68)
        #expect(indicator.sourceBoxHeight == 0.49)
    }

    @Test func ignoresInvalidIndicatorEvidenceLocation() throws {
        let raw = """
        {"indicators":[{"name":"尿酸","value":"486","unit":"μmol/L","range":"208 - 428","status":"high","source_page":0,"source_box":[-1,0.42,0.68,1.5]}]}
        """
        let parsed = try CaptureService.parseReportJSON(raw)
        let indicator = try #require(parsed.indicators.first)
        #expect(indicator.sourcePageIndex == nil)
        #expect(indicator.sourceBoxX == nil)
        #expect(indicator.sourceBoxY == nil)
        #expect(indicator.sourceBoxWidth == nil)
        #expect(indicator.sourceBoxHeight == nil)
    }

    @Test func infersStatusFromValueAndReferenceRangeWhenStatusMissing() throws {
        let raw = """
        {"indicators":[
          {"name":"低密度脂蛋白","value":"3.84","unit":"mmol/L","range":"< 3.40"},
          {"name":"白细胞","value":"2.8","unit":"10^9/L","range":"3.5 - 9.5"}
        ]}
        """
        let indicators = try CaptureService.parseIndicatorsJSON(raw)
        #expect(indicators.count == 2)
        #expect(indicators[0].status == .high)
        #expect(indicators[1].status == .low)
    }

    @Test func badReportDateFallsBackToNow() throws {
        let raw = """
        {"title":"t","type":"lab","report_date":"昨天","institution":"","page_count":1,"summary":"","indicators":[]}
        """
        let parsed = try CaptureService.parseReportJSON(raw)
        let now = Date()
        let diff = abs(parsed.reportDate.timeIntervalSince(now))
        #expect(diff < 5)  // 5 秒内算 .now
    }

    /// VL 多项时偶尔直接吐裸数组 [{...},{...}],旧实现(只认 {})会只截第一项静默丢其余。
    @Test func parsesTopLevelArrayAsIndicators() throws {
        let raw = """
        [{"name":"A","value":"1","unit":"","range":"","status":"high"},
         {"name":"B","value":"2","unit":"","range":"","status":"low"}]
        """
        let parsed = try CaptureService.parseReportJSON(raw)
        #expect(parsed.indicators.count == 2)
        #expect(parsed.indicators.first?.name == "A")
        #expect(parsed.indicators.last?.status == .low)
    }

    /// VL 不同来源会吐 yyyy/MM/dd 等格式,不应回退到「今天」导致归档年份错位。
    @Test func parsesSlashAndCJKDateFormats() throws {
        for ds in ["2026/04/12", "2026.04.12", "2026年04月12日"] {
            let raw = """
            {"title":"t","type":"lab","report_date":"\(ds)","institution":"","page_count":1,"summary":"","indicators":[]}
            """
            let parsed = try CaptureService.parseReportJSON(raw)
            let c = Calendar(identifier: .gregorian).dateComponents([.year, .month, .day], from: parsed.reportDate)
            #expect(c.year == 2026 && c.month == 4 && c.day == 12, "格式 \(ds) 解析失败")
        }
    }
}
