import SwiftUI
import SwiftData

/// 主页「健康日历」卡:当前一周横条 + 本月记录摘要。
/// 点整卡或某一天 → 打开 CalendarOverviewView 看月/年总览。自包含 @Query(对齐 TodayRemindersCard)。
struct HomeCalendarCard: View {
    @Query(sort: \Indicator.capturedAt, order: .reverse)
    private var indicators: [Indicator]

    @Query(sort: \Report.reportDate, order: .reverse)
    private var reports: [Report]

    @Query(sort: \DiaryEntry.createdAt, order: .reverse)
    private var diaries: [DiaryEntry]

    @Query(sort: \Symptom.startedAt, order: .reverse)
    private var symptoms: [Symptom]

    /// 打开总览时定位的日期(nil = 不展示)。
    @State private var openDay: SelectedDay?

    private let calendar: Calendar = {
        var c = Calendar(identifier: .gregorian)
        c.firstWeekday = 2
        c.locale = Locale.current
        return c
    }()

    @MainActor
    private var data: CalendarData {
        CalendarData.build(
            indicators: indicators,
            reports: reports,
            diaries: diaries,
            symptoms: symptoms
        )
    }

    /// 本周一 → 本周日。
    private var weekDays: [Date] {
        let today = calendar.startOfDay(for: .now)
        let weekdayIndex = (calendar.component(.weekday, from: today) - calendar.firstWeekday + 7) % 7
        guard let monday = calendar.date(byAdding: .day, value: -weekdayIndex, to: today) else {
            return []
        }
        return (0..<7).compactMap { calendar.date(byAdding: .day, value: $0, to: monday) }
    }

    /// 本月有记录的天数(指标/报告/日记/症状任一)。传入已构建好的 data,避免逐天重建。
    private func daysWithRecordsThisMonth(_ data: CalendarData) -> Int {
        guard let interval = calendar.dateInterval(of: .month, for: .now) else { return 0 }
        let count = calendar.range(of: .day, in: .month, for: .now)?.count ?? 30
        var n = 0
        for i in 0..<count {
            guard let d = calendar.date(byAdding: .day, value: i, to: interval.start) else { continue }
            if data.marks(for: d, calendar: calendar).hasAnyEvent ||
               !data.ranges(touching: d, calendar: calendar).isEmpty {
                n += 1
            }
        }
        return n
    }

    var body: some View {
        // CalendarData 一次性构建,供周条 + 本月摘要复用 —— 杜绝逐格(7)+ 逐天(~30)反复全表重建。
        let calData = data
        return VStack(alignment: .leading, spacing: 12) {
            header(calData)
            weekStrip(calData)
        }
        .padding(14)
        .frame(maxWidth: .infinity, alignment: .leading)
        .tjCard(bordered: true)
        .padding(.bottom, 18)
        .contentShape(Rectangle())
        .onTapGesture { openDay = SelectedDay(date: .now) }
        .fullScreenCover(item: $openDay) { day in
            CalendarOverviewView(initialDate: day.date, onClose: { openDay = nil })
        }
    }

    private func header(_ data: CalendarData) -> some View {
        HStack(alignment: .firstTextBaseline) {
            Text("健康日历")
                .font(.tjH2())
                .foregroundStyle(Tj.Palette.text)
            Spacer()
            HStack(spacing: 3) {
                Text(summaryLine(data))
                    .font(.tjScaled( 12))
                    .foregroundStyle(Tj.Palette.text3)
                Image(systemName: "chevron.right")
                    .font(.tjScaled( 11, weight: .semibold))
                    .foregroundStyle(Tj.Palette.text3)
            }
        }
    }

    private func summaryLine(_ data: CalendarData) -> String {
        let n = daysWithRecordsThisMonth(data)
        return n > 0 ? String(appLoc: "本月 \(n) 天有记录") : String(appLoc: "本月暂无记录")
    }

    private func weekStrip(_ data: CalendarData) -> some View {
        HStack(spacing: 6) {
            ForEach(weekDays, id: \.self) { day in
                dayCell(day, data)
            }
        }
    }

    private func dayCell(_ day: Date, _ data: CalendarData) -> some View {
        let marks = data.marks(for: day, calendar: calendar)
        let ranges = data.ranges(touching: day, calendar: calendar)
        let isToday = calendar.isDateInToday(day)
        let hasSymptom = !ranges.isEmpty

        return Button {
            openDay = SelectedDay(date: day)
        } label: {
            VStack(spacing: 5) {
                Text(weekdayLabel(day))
                    .font(.tjScaled( 10, weight: .medium))
                    .foregroundStyle(Tj.Palette.text3)
                ZStack {
                    RoundedRectangle(cornerRadius: 9, style: .continuous)
                        .fill(cellFill(isToday: isToday, hasSymptom: hasSymptom))
                    if isToday {
                        RoundedRectangle(cornerRadius: 9, style: .continuous)
                            .strokeBorder(Tj.Palette.ink, lineWidth: 1.2)
                    }
                    Text("\(calendar.component(.day, from: day))")
                        .font(.tjScaled( 14, weight: isToday ? .bold : .regular))
                        .foregroundStyle(isToday ? Tj.Palette.ink : Tj.Palette.text)
                }
                .frame(height: 38)
                marksDots(marks)
                    .frame(height: 5)
            }
            .frame(maxWidth: .infinity)
            .contentShape(Rectangle())
        }
        .buttonStyle(.plain)
    }

    @ViewBuilder
    private func marksDots(_ marks: DayMarks) -> some View {
        HStack(spacing: 2) {
            if marks.abnormalCount > 0 {
                dot(Tj.Palette.brick)
            } else if marks.normalCount > 0 {
                dot(Tj.Palette.leaf)
            }
            if marks.reportCount > 0 { dot(Tj.Palette.ink2) }
            if marks.diaryCount > 0 { dot(Tj.Palette.text3.opacity(0.7)) }
        }
    }

    private func dot(_ color: Color) -> some View {
        Circle().fill(color).frame(width: 4, height: 4)
    }

    private func cellFill(isToday: Bool, hasSymptom: Bool) -> Color {
        if hasSymptom { return Tj.Palette.amber.opacity(0.18) }
        if isToday { return Tj.Palette.sand2 }
        return Tj.Palette.sand2.opacity(0.5)
    }

    private func weekdayLabel(_ day: Date) -> String {
        let labels = [
            String(appLoc: "一"), String(appLoc: "二"), String(appLoc: "三"),
            String(appLoc: "四"), String(appLoc: "五"), String(appLoc: "六"),
            String(appLoc: "日")
        ]
        let idx = (calendar.component(.weekday, from: day) - calendar.firstWeekday + 7) % 7
        return labels[idx]
    }
}
