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: "年")
        }
    }
}

struct TrendsView: 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]

    @Query private var profiles: [UserProfile]

    @Query private var customMetrics: [CustomMonitorMetric]

    @State private var mode: CalendarMode = .month
    @State private var anchor: Date = .now
    /// 选中的当天 — 默认选今天,日历下方 inline 显示该日详情
    @State private var selectedDate: Date = .now

    private var profile: UserProfile? { profiles.first }

    private var seriesBuckets: [SeriesBucket] {
        SeriesBucket.build(from: indicators,
                           profile: profile,
                           customMetrics: customMetrics)
    }

    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 {
        ScrollView(showsIndicators: false) {
            VStack(alignment: .leading, spacing: 18) {
                header.padding(.top, 4)
                modeSwitch
                anchorBar
                calendarBody
                legend
                if mode == .month {
                    dayDetailInline
                }
                seriesSection
            }
            .padding(.horizontal, 20)
            .padding(.bottom, 24)
        }
        .frame(maxWidth: .infinity, maxHeight: .infinity, alignment: .topLeading)
        .background(Tj.Palette.sand.ignoresSafeArea())
    }

    /// 日历下方 inline 显示选中天的详情(symptoms / indicators / reports / diaries)
    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 header: some View {
        HStack(alignment: .lastTextBaseline) {
            Text("趋势")
                .font(.tjTitle(26))
                .foregroundStyle(Tj.Palette.text)
            Spacer()
            Button {
                withAnimation(.snappy(duration: 0.2)) {
                    anchor = .now
                    selectedDate = .now
                }
            } label: {
                Text("回到今天")
                    .font(.system(size: 12))
                    .foregroundStyle(Tj.Palette.text3)
            }
            .buttonStyle(.plain)
        }
    }

    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(.system(size: 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(.system(size: 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(.system(size: 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
                }
            }
        }
    }

    @ViewBuilder
    private var seriesSection: some View {
        let buckets = seriesBuckets
        if !buckets.isEmpty {
            VStack(alignment: .leading, spacing: 12) {
                HStack(alignment: .lastTextBaseline) {
                    Text("长期监测")
                        .font(.tjH2())
                        .foregroundStyle(Tj.Palette.text)
                    Text("\(buckets.count) 项")
                        .font(.system(size: 12))
                        .foregroundStyle(Tj.Palette.text3)
                    Spacer()
                }
                .padding(.top, 8)

                VStack(spacing: 12) {
                    ForEach(buckets) { bucket in
                        SeriesChartCard(bucket: bucket)
                    }
                }
            }
        }
    }

    private var legend: some View {
        VStack(alignment: .leading, spacing: 8) {
            Text("图例")
                .font(.system(size: 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(.system(size: 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
                // 翻月时把 selection 跟着走:同月内停在今天(如果是当前月)或 1 号
                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 {
    TrendsView()
        .modelContainer(for: [
            Indicator.self, Report.self, DiaryEntry.self, Symptom.self, Asset.self
        ], inMemory: true)
}
