import Testing
import SwiftData
import Foundation
@testable import 康康

struct ModelsSchemaTests {

    private func makeContainer() throws -> ModelContainer {
        let schema = Schema([
            Indicator.self,
            Report.self,
            DiaryEntry.self,
            Asset.self,
            ChatTurn.self,
            Symptom.self,
            UserProfile.self,
            MetricReminder.self,
            CustomMonitorMetric.self,
        ])
        let config = ModelConfiguration(schema: schema, isStoredInMemoryOnly: true)
        return try ModelContainer(for: schema, configurations: [config])
    }

    @Test func insertIndicatorWithReportRelationship() throws {
        let container = try makeContainer()
        let ctx = ModelContext(container)

        let report = Report(title: "春检", type: .checkup, reportDate: .now)
        let indicator = Indicator(
            name: "ALT",
            value: "32",
            unit: "U/L",
            range: "9-50",
            status: .normal,
            report: report
        )
        ctx.insert(report)
        ctx.insert(indicator)
        try ctx.save()

        #expect(report.indicators.count == 1)
        #expect(indicator.report?.title == "春检")
    }

    @Test func cascadeDeleteReportRemovesIndicators() throws {
        let container = try makeContainer()
        let ctx = ModelContext(container)

        let report = Report(title: "春检", type: .checkup, reportDate: .now)
        let indicator = Indicator(
            name: "ALT", value: "32", unit: "U/L", range: "9-50",
            status: .normal, report: report
        )
        ctx.insert(report)
        ctx.insert(indicator)
        try ctx.save()

        ctx.delete(report)
        try ctx.save()

        let remaining = try ctx.fetch(FetchDescriptor<Indicator>())
        #expect(remaining.isEmpty)
    }

    @Test func ongoingSymptomQueryFiltersByEndedAt() throws {
        let container = try makeContainer()
        let ctx = ModelContext(container)

        let active = Symptom(name: "头痛", startedAt: .now.addingTimeInterval(-3600))
        let ended = Symptom(
            name: "咳嗽",
            startedAt: .now.addingTimeInterval(-7200),
            endedAt: .now.addingTimeInterval(-1800)
        )
        ctx.insert(active)
        ctx.insert(ended)
        try ctx.save()

        let predicate = #Predicate<Symptom> { $0.endedAt == nil }
        let ongoing = try ctx.fetch(FetchDescriptor<Symptom>(predicate: predicate))

        #expect(ongoing.count == 1)
        #expect(ongoing.first?.name == "头痛")
        #expect(active.isOngoing)
        #expect(!ended.isOngoing)
        #expect(active.duration >= 3600)
    }

    @Test func symptomSeverityClampedToRange() throws {
        let high = Symptom(name: "腹痛", severity: 99)
        let low = Symptom(name: "失眠", severity: -3)
        #expect(high.severity == 5)
        #expect(low.severity == 1)
    }

    @Test func chatTurnPersistsReferencedIDs() throws {
        let container = try makeContainer()
        let ctx = ModelContext(container)

        let turn = ChatTurn(
            question: "我的 LDL 怎么样?",
            answer: "近 3 个月 LDL 偏高 [1]",
            referencedIndicatorIDs: ["abc"],
            referencedReportIDs: [],
            decodeRate: 24.3
        )
        ctx.insert(turn)
        try ctx.save()

        let all = try ctx.fetch(FetchDescriptor<ChatTurn>())
        #expect(all.count == 1)
        #expect(all.first?.referencedIndicatorIDs == ["abc"])
    }

    @Test func indicatorSeriesKeyRoundtrip() throws {
        let container = try makeContainer()
        let ctx = ModelContext(container)

        let bp = Indicator(
            name: "收缩压",
            value: "125",
            unit: "mmHg",
            range: "90-140",
            status: .normal,
            pinned: true,
            seriesKey: "bp.systolic"
        )
        ctx.insert(bp)
        try ctx.save()

        let fetched = try #require(try ctx.fetch(FetchDescriptor<Indicator>()).first)
        #expect(fetched.seriesKey == "bp.systolic")
        #expect(fetched.pinned == true)
    }

    @Test func indicatorSeriesKeyDefaultsToNil() {
        let i = Indicator(name: "ALT", value: "32", unit: "U/L", range: "9-50", status: .normal)
        #expect(i.seriesKey == nil)
    }

    @Test func userProfileSchemaPersistsAcrossSave() throws {
        let container = try makeContainer()
        let ctx = ModelContext(container)

        let p = UserProfile(
            birthYear: 1985,
            biologicalSexRaw: "male",
            heightCM: 175,
            bloodTypeRaw: "A",
            chronicConditions: ["高血压"]
        )
        ctx.insert(p)
        try ctx.save()

        let fetched = try #require(try ctx.fetch(FetchDescriptor<UserProfile>()).first)
        #expect(fetched.birthYear == 1985)
        #expect(fetched.sex == .male)
        #expect(fetched.heightCM == 175)
        #expect(fetched.bloodTypeRaw == "A")
        #expect(fetched.chronicConditions == ["高血压"])
    }
}
