import Testing
import SwiftData
import Foundation
@testable import 康康

@MainActor
struct UserProfileTests {

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

    @Test func freshProfileHasNilDemographics() {
        let p = UserProfile()
        #expect(p.birthYear == nil)
        #expect(p.heightCM == nil)
        #expect(p.weightKG == nil)
        #expect(p.biologicalSexRaw == "")
        #expect(p.bloodTypeRaw == "")
        #expect(p.allergies.isEmpty)
        #expect(p.chronicConditions.isEmpty)
        #expect(p.currentMedications.isEmpty)
        #expect(p.familyHistory.isEmpty)
        #expect(p.age == nil)
        #expect(p.sex == .undisclosed)
        #expect(p.bmi == nil)
        #expect(p.hasAnyBasics == false)
        #expect(p.summaryLine == "")
    }

    @Test func ageComputedFromBirthYear() {
        let p = UserProfile(birthYear: 1985)
        let currentYear = Calendar.current.component(.year, from: .now)
        #expect(p.age == currentYear - 1985)
    }

    @Test func sexEnumRoundtripsThroughRaw() {
        let p = UserProfile(biologicalSexRaw: "male")
        #expect(p.sex == .male)
        p.sex = .female
        #expect(p.biologicalSexRaw == "female")
        p.sex = .undisclosed
        #expect(p.biologicalSexRaw == "")
    }

    @Test func summaryLineSkipsEmptyFields() {
        let p = UserProfile(birthYear: 1990, biologicalSexRaw: "female", heightCM: 162)
        let line = p.summaryLine
        #expect(line.contains("岁"))
        #expect(line.contains("女"))
        #expect(line.contains("162cm"))
        #expect(!line.contains("kg"))    // 体重空,不出现
        #expect(!line.contains("型"))    // 血型空,不出现
    }

    @Test func summaryLineIncludesWeightWhenSet() {
        let p = UserProfile(heightCM: 175, weightKG: 68.5)
        #expect(p.summaryLine.contains("175cm"))
        #expect(p.summaryLine.contains("68.5kg"))
    }

    @Test func summaryLineFormatsIntegerWeightWithoutDecimal() {
        let p = UserProfile(weightKG: 70)
        #expect(p.summaryLine == "70kg")
    }

    @Test func bmiNilWithoutBothHeightAndWeight() {
        #expect(UserProfile(heightCM: 175).bmi == nil)
        #expect(UserProfile(weightKG: 68).bmi == nil)
        #expect(UserProfile().bmi == nil)
    }

    @Test func bmiComputedFromHeightAndWeight() throws {
        let p = UserProfile(heightCM: 175, weightKG: 70)
        let bmi = try #require(p.bmi)
        // 70 / (1.75 * 1.75) = 22.857
        #expect(abs(bmi - 22.857) < 0.01)
    }

    @Test func loadOrCreateReturnsExistingSingleton() throws {
        let ctx = try makeContext()
        let first = UserProfileStore.loadOrCreate(in: ctx)
        first.birthYear = 1990
        try ctx.save()

        let second = UserProfileStore.loadOrCreate(in: ctx)
        #expect(second.birthYear == 1990)

        let all = try ctx.fetch(FetchDescriptor<UserProfile>())
        #expect(all.count == 1)
    }

    @Test func arrayFieldsRoundtripThroughSwiftData() throws {
        let ctx = try makeContext()
        let p = UserProfile(
            chronicConditions: ["高血压", "糖尿病"],
            currentMedications: ["缬沙坦 80mg qd", "二甲双胍 500mg bid"]
        )
        ctx.insert(p)
        try ctx.save()

        let fetched = try #require(try ctx.fetch(FetchDescriptor<UserProfile>()).first)
        #expect(fetched.chronicConditions == ["高血压", "糖尿病"])
        #expect(fetched.currentMedications.count == 2)
        #expect(fetched.currentMedications.first == "缬沙坦 80mg qd")
    }
}
