import SwiftUI
import SwiftData

enum CalendarMode: String, CaseIterable, Identifiable {
    case month, year
    var id: String { rawValue }
    var label: String {
        switch self {
        case .month: return String(appLoc: "月")
        case .year:  return String(appLoc: "年")
        }
    }
}

/// 健康日历总览页。从主页 HomeCalendarCard 进入。
/// 月/年切换 + 上下导航 + 图例 + 月视图下方当日详情。日历组件复用 CalendarMonthGrid / CalendarYearGrid。
struct CalendarOverviewView: View {
    /// 进入时定位到的日期(从主页某天点入);nil → 今天。
    var initialDate: Date = .now
    /// fullScreenCover 形态下的关闭回调。
    var onClose: (() -> Void)?

    @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]

    @State private var mode: CalendarMode = .month
    @State private var anchor: Date = .now
    @State private var selectedDate: Date = .now

    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
        )
    }

    var body: some View {
        NavigationStack {
            ScrollView(showsIndicators: false) {
                VStack(alignment: .leading, spacing: 18) {
                    modeSwitch.padding(.top, 4)
                    anchorBar
                    calendarBody
                    legend
                    if mode == .month {
                        dayDetailInline
                    }
                }
                .padding(.horizontal, 20)
                .padding(.bottom, 24)
            }
            .frame(maxWidth: .infinity, maxHeight: .infinity, alignment: .topLeading)
            .background(Tj.Palette.sand.ignoresSafeArea())
            .navigationTitle(String(appLoc: "健康日历"))
            .navigationBarTitleDisplayMode(.inline)
            .toolbar {
                ToolbarItem(placement: .topBarLeading) {
                    Button {
                        withAnimation(.snappy(duration: 0.2)) {
                            anchor = .now
                            selectedDate = .now
                            mode = .month
                        }
                    } label: {
                        Text("回到今天")
                            .font(.tjScaled( 13))
                            .foregroundStyle(Tj.Palette.text3)
                    }
                }
                ToolbarItem(placement: .topBarTrailing) {
                    if let onClose {
                        Button(action: onClose) {
                            Text("完成")
                                .font(.tjScaled( 15, weight: .semibold))
                                .foregroundStyle(Tj.Palette.text)
                        }
                    }
                }
            }
        }
        .onAppear {
            anchor = initialDate
            selectedDate = initialDate
        }
    }

    private var dayDetailInline: some View {
        VStack(alignment: .leading, spacing: 0) {
            DayDetailContent(
                date: selectedDate,
                indicators: indicators,
                reports: reports,
                diaries: diaries,
                symptoms: symptoms,
                showHeader: true
            )
            .padding(14)
        }
        .frame(maxWidth: .infinity, alignment: .leading)
        .background(
            RoundedRectangle(cornerRadius: Tj.Radius.md, style: .continuous)
                .fill(Tj.Palette.paper)
        )
        .overlay(
            RoundedRectangle(cornerRadius: Tj.Radius.md, style: .continuous)
                .strokeBorder(Tj.Palette.lineSoft, lineWidth: 1)
        )
        .animation(.snappy(duration: 0.2), value: selectedDate)
    }

    private var modeSwitch: some View {
        HStack(spacing: 0) {
            ForEach(CalendarMode.allCases) { m in
                Button {
                    withAnimation(.spring(response: 0.3, dampingFraction: 0.8)) {
                        mode = m
                    }
                } label: {
                    Text(m.label)
                        .font(.tjScaled( 13, weight: mode == m ? .semibold : .regular))
                        .foregroundStyle(mode == m ? Tj.Palette.paper : Tj.Palette.text)
                        .frame(maxWidth: .infinity)
                        .padding(.vertical, 9)
                        .background(
                            Capsule().fill(mode == m ? Tj.Palette.ink : Color.clear)
                        )
                }
                .buttonStyle(.plain)
            }
        }
        .padding(3)
        .background(Capsule().fill(Tj.Palette.paper))
        .overlay(Capsule().strokeBorder(Tj.Palette.line, lineWidth: 1))
        .frame(maxWidth: 220)
    }

    private var anchorBar: some View {
        HStack {
            Button { shiftAnchor(-1) } label: {
                Image(systemName: "chevron.left")
                    .font(.tjScaled( 16, weight: .semibold))
                    .foregroundStyle(Tj.Palette.text)
                    .frame(width: 36, height: 36)
                    .background(Circle().fill(Tj.Palette.paper))
                    .overlay(Circle().strokeBorder(Tj.Palette.line, lineWidth: 1))
            }
            .buttonStyle(.plain)

            Spacer()

            Text(anchorTitle)
                .font(.tjH2())
                .foregroundStyle(Tj.Palette.text)
                .contentTransition(.numericText())
                .animation(.snappy, value: anchor)

            Spacer()

            Button { shiftAnchor(1) } label: {
                Image(systemName: "chevron.right")
                    .font(.tjScaled( 16, weight: .semibold))
                    .foregroundStyle(Tj.Palette.text)
                    .frame(width: 36, height: 36)
                    .background(Circle().fill(Tj.Palette.paper))
                    .overlay(Circle().strokeBorder(Tj.Palette.line, lineWidth: 1))
            }
            .buttonStyle(.plain)
            .disabled(isAnchorAtFuture)
            .opacity(isAnchorAtFuture ? 0.4 : 1)
        }
    }

    private var anchorTitle: String {
        let style: Date.FormatStyle = mode == .month
            ? .dateTime.year().month()
            : .dateTime.year()
        return anchor.formatted(style)
    }

    @ViewBuilder
    private var calendarBody: some View {
        switch mode {
        case .month:
            CalendarMonthGrid(monthAnchor: anchor, data: data, selectedDate: selectedDate) { day in
                withAnimation(.snappy(duration: 0.2)) {
                    selectedDate = day
                }
            }
                .padding(14)
                .background(
                    RoundedRectangle(cornerRadius: Tj.Radius.md, style: .continuous)
                        .fill(Tj.Palette.paper)
                )
                .overlay(
                    RoundedRectangle(cornerRadius: Tj.Radius.md, style: .continuous)
                        .strokeBorder(Tj.Palette.lineSoft, lineWidth: 1)
                )
        case .year:
            CalendarYearGrid(
                year: calendar.component(.year, from: anchor),
                data: data
            ) { tappedMonth in
                anchor = tappedMonth
                withAnimation(.spring(response: 0.3, dampingFraction: 0.8)) {
                    mode = .month
                }
            }
        }
    }

    private var legend: some View {
        VStack(alignment: .leading, spacing: 8) {
            Text("图例")
                .font(.tjScaled( 11, weight: .semibold))
                .tracking(0.5)
                .foregroundStyle(Tj.Palette.text3)
            HStack(spacing: 14) {
                legendItem(color: Tj.Palette.brick, label: String(appLoc: "指标异常"))
                legendItem(color: Tj.Palette.amber, label: String(appLoc: "症状持续中"))
                legendItem(color: Tj.Palette.ink2, label: String(appLoc: "报告归档"))
                legendItem(color: Tj.Palette.leaf, label: String(appLoc: "正常"))
            }
        }
        .padding(.top, 4)
    }

    private func legendItem(color: Color, label: String) -> some View {
        HStack(spacing: 5) {
            RoundedRectangle(cornerRadius: 2, style: .continuous)
                .fill(color)
                .frame(width: 14, height: 6)
            Text(label)
                .font(.tjScaled( 11))
                .foregroundStyle(Tj.Palette.text2)
        }
    }

    private var isAnchorAtFuture: Bool {
        switch mode {
        case .month:
            return calendar.isDate(anchor, equalTo: .now, toGranularity: .month) ||
                   anchor > .now
        case .year:
            let nowYear = calendar.component(.year, from: .now)
            let anchorYear = calendar.component(.year, from: anchor)
            return anchorYear >= nowYear
        }
    }

    private func shiftAnchor(_ delta: Int) {
        let component: Calendar.Component = (mode == .month) ? .month : .year
        if let next = calendar.date(byAdding: component, value: delta, to: anchor) {
            withAnimation(.snappy) {
                anchor = next
                if mode == .month {
                    if calendar.isDate(next, equalTo: .now, toGranularity: .month) {
                        selectedDate = .now
                    } else if let first = calendar.dateInterval(of: .month, for: next)?.start {
                        selectedDate = first
                    }
                }
            }
        }
    }
}

#Preview {
    CalendarOverviewView(onClose: {})
        .modelContainer(for: [
            Indicator.self, Report.self, DiaryEntry.self, Symptom.self, Asset.self
        ], inMemory: true)
}
