import Testing
import SwiftData
import Foundation
@testable import 康康

@MainActor
struct TimelineEntryBPMergeTests {

    private func makeContext() throws -> ModelContext {
        let schema = Schema([Indicator.self])
        let config = ModelConfiguration(schema: schema, isStoredInMemoryOnly: true)
        return ModelContext(try ModelContainer(for: schema, configurations: [config]))
    }

    private func bp(sys: Int, dia: Int, at: Date, in ctx: ModelContext) -> (Indicator, Indicator) {
        let s = Indicator(name: "收缩压", value: "\(sys)", unit: "mmHg",
                          range: "90-140", status: .normal,
                          capturedAt: at, pinned: true, seriesKey: "bp.systolic")
        let d = Indicator(name: "舒张压", value: "\(dia)", unit: "mmHg",
                          range: "60-90", status: .normal,
                          capturedAt: at, pinned: true, seriesKey: "bp.diastolic")
        ctx.insert(s); ctx.insert(d)
        return (s, d)
    }

    @Test func bpPairAtSameTimeMergesIntoSingleEntry() throws {
        let ctx = try makeContext()
        let now = Date(timeIntervalSince1970: 1_716_000_000)
        _ = bp(sys: 120, dia: 80, at: now, in: ctx)
        try ctx.save()

        let all = try ctx.fetch(FetchDescriptor<Indicator>())
        let entries = TimelineEntry.from(indicators: all)

        #expect(entries.count == 1)
        let e = try #require(entries.first)
        #expect(e.title == "血压")
        #expect(e.trailing?.contains("120/80") == true)
        #expect(e.trailingIsAlert == false)
    }

    @Test func bpPairWithAbnormalSystolicMarksAlert() throws {
        let ctx = try makeContext()
        let now = Date()
        let (s, _) = bp(sys: 150, dia: 80, at: now, in: ctx)
        s.statusRaw = IndicatorStatus.high.rawValue
        try ctx.save()

        let all = try ctx.fetch(FetchDescriptor<Indicator>())
        let entries = TimelineEntry.from(indicators: all)
        #expect(entries.count == 1)
        #expect(entries.first?.trailingIsAlert == true)
        #expect(entries.first?.trailing?.contains("↑") == true)
    }

    @Test func nonBPSeriesStayAsSeparateEntries() throws {
        let ctx = try makeContext()
        let now = Date()
        let glu = Indicator(name: "空腹血糖", value: "5.4", unit: "mmol/L",
                            range: "3.9-6.1", status: .normal,
                            capturedAt: now, pinned: true, seriesKey: "glucose.fasting")
        let weight = Indicator(name: "体重", value: "68", unit: "kg",
                               range: "", status: .normal,
                               capturedAt: now, pinned: true, seriesKey: "weight")
        ctx.insert(glu); ctx.insert(weight)
        try ctx.save()

        let all = try ctx.fetch(FetchDescriptor<Indicator>())
        let entries = TimelineEntry.from(indicators: all)
        #expect(entries.count == 2)
        #expect(entries.contains { $0.title == "空腹血糖" })
        #expect(entries.contains { $0.title == "体重" })
    }

    @Test func bpAtDifferentTimesDoNotMerge() throws {
        let ctx = try makeContext()
        let t1 = Date(timeIntervalSince1970: 1_716_000_000)
        let t2 = t1.addingTimeInterval(3600)  // 1 小时后
        _ = bp(sys: 120, dia: 80, at: t1, in: ctx)
        _ = bp(sys: 130, dia: 85, at: t2, in: ctx)
        try ctx.save()

        let all = try ctx.fetch(FetchDescriptor<Indicator>())
        let entries = TimelineEntry.from(indicators: all)
        #expect(entries.count == 2)
    }

    @Test func unpairedSystolicFallsBackToSingleEntry() throws {
        let ctx = try makeContext()
        let s = Indicator(name: "收缩压", value: "120", unit: "mmHg",
                          range: "90-140", status: .normal,
                          capturedAt: .now, pinned: true, seriesKey: "bp.systolic")
        ctx.insert(s)
        try ctx.save()

        let all = try ctx.fetch(FetchDescriptor<Indicator>())
        let entries = TimelineEntry.from(indicators: all)
        // 没找到 diastolic 配对,落到单 from(indicator:),显示 "收缩压"
        #expect(entries.count == 1)
        #expect(entries.first?.title == "收缩压")
    }

    @Test func freeformIndicatorWithoutSeriesKeyShowsAsItself() throws {
        let ctx = try makeContext()
        let i = Indicator(name: "ALT", value: "32", unit: "U/L",
                          range: "9-50", status: .normal,
                          capturedAt: .now)
        ctx.insert(i)
        try ctx.save()

        let all = try ctx.fetch(FetchDescriptor<Indicator>())
        let entries = TimelineEntry.from(indicators: all)
        #expect(entries.count == 1)
        #expect(entries.first?.title == "ALT")
    }
}
