import SwiftUI

struct CalendarYearGrid: View {
    let year: Int
    let data: CalendarData
    let onTapMonth: (Date) -> Void

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

    private var monthAnchors: [Date] {
        (1...12).compactMap { m in
            var comps = DateComponents()
            comps.year = year; comps.month = m; comps.day = 1
            return calendar.date(from: comps)
        }
    }

    private let columns = Array(repeating: GridItem(.flexible(), spacing: 14), count: 3)

    var body: some View {
        LazyVGrid(columns: columns, spacing: 18) {
            ForEach(monthAnchors, id: \.self) { anchor in
                Button {
                    onTapMonth(anchor)
                } label: {
                    MiniMonth(anchor: anchor, data: data, calendar: calendar)
                }
                .buttonStyle(.plain)
            }
        }
    }
}

private struct MiniMonth: View {
    let anchor: Date
    let data: CalendarData
    let calendar: Calendar

    private var monthLabel: String {
        anchor.formatted(.dateTime.month())
    }

    private var days: [Date] {
        guard let interval = calendar.dateInterval(of: .month, for: anchor) else { return [] }
        // 用 range(of:.day,in:.month) 求当月天数,避免按秒差折算在 DST 切换月份偏 1 天。
        let count = calendar.range(of: .day, in: .month, for: anchor)?.count ?? 30
        return (0..<count).compactMap { calendar.date(byAdding: .day, value: $0, to: interval.start) }
    }

    private var leadingPadding: Int {
        guard let first = days.first else { return 0 }
        return (calendar.component(.weekday, from: first) - calendar.firstWeekday + 7) % 7
    }

    private let microColumns = Array(repeating: GridItem(.flexible(), spacing: 2), count: 7)

    var body: some View {
        VStack(alignment: .leading, spacing: 6) {
            Text(monthLabel)
                .font(.tjScaled( 12, weight: .semibold))
                .foregroundStyle(Tj.Palette.text)

            LazyVGrid(columns: microColumns, spacing: 2) {
                ForEach(0..<leadingPadding, id: \.self) { _ in
                    Color.clear.frame(height: 8)
                }
                ForEach(days, id: \.self) { d in
                    dot(for: d)
                }
            }
        }
        .padding(8)
        .background(
            RoundedRectangle(cornerRadius: Tj.Radius.sm, style: .continuous)
                .fill(Tj.Palette.paper)
        )
        .overlay(
            RoundedRectangle(cornerRadius: Tj.Radius.sm, style: .continuous)
                .strokeBorder(Tj.Palette.lineSoft, lineWidth: 1)
        )
    }

    private func dot(for date: Date) -> some View {
        let marks = data.marks(for: date, calendar: calendar)
        let ranges = data.ranges(touching: date, calendar: calendar)
        let color: Color = {
            if marks.abnormalCount > 0 { return Tj.Palette.brick }
            if let topSeverity = ranges.map(\.severity).max() {
                switch topSeverity {
                case 1, 2: return Tj.Palette.leaf
                case 3:    return Tj.Palette.amber
                default:   return Tj.Palette.brick
                }
            }
            if marks.hasAnyEvent { return Tj.Palette.text3.opacity(0.6) }
            return Tj.Palette.lineSoft
        }()
        let isToday = calendar.isDateInToday(date)
        return RoundedRectangle(cornerRadius: 2, style: .continuous)
            .fill(color)
            .frame(height: 8)
            .overlay(
                RoundedRectangle(cornerRadius: 2, style: .continuous)
                    .strokeBorder(Tj.Palette.ink, lineWidth: isToday ? 1 : 0)
            )
    }
}
