//
//  FilterView.swift
//  Reflect
//
//  Created by Trey Tartt on 1/12/22.
//

import SwiftUI

struct YearView: View {
    let months = [(0, "J"), (1, "F"), (2,"M"), (3,"A"), (4,"M"), (5, "J"), (6,"J"), (7,"A"), (8,"S"), (9,"O"), (10, "N"), (11,"D")]

    @State private var toggle = true

    @AppStorage(UserDefaultsStore.Keys.theme.rawValue, store: GroupUserDefaults.groupDefaults) private var theme: Theme = .system
    @AppStorage(UserDefaultsStore.Keys.moodTint.rawValue, store: GroupUserDefaults.groupDefaults) private var moodTint: MoodTints = .Default
    @AppStorage(UserDefaultsStore.Keys.moodImages.rawValue, store: GroupUserDefaults.groupDefaults) private var imagePack: MoodImages = .FontAwesome

    @EnvironmentObject var iapManager: IAPManager
    @StateObject public var viewModel: YearViewModel
    @StateObject private var filteredDays = DaysFilterClass.shared
    @StateObject private var shareImage = ShareImageStateViewModel()
    @State private var trialWarningHidden = false
    @State private var showSubscriptionStore = false
    @State private var sharePickerData: SharePickerData? = nil

    /// Cached sorted year keys to avoid re-sorting in ForEach on every render
    @State private var cachedSortedYearKeys: [Int] = []
    @State private var cachedDemoYearData: [Int: [Int: [DayChartView]]] = [:]

    // MARK: - Demo Animation
    @StateObject private var demoManager = DemoAnimationManager.shared

    // Heatmap-style grid: 12 columns for months
    private let heatmapColumns = Array(repeating: GridItem(.flexible(), spacing: 2), count: 12)

    /// Generate demo year data for the past 3 years (full 12 months each)
    private func computeDemoYearData() -> [Int: [Int: [DayChartView]]] {
        var result: [Int: [Int: [DayChartView]]] = [:]
        let calendar = Calendar.current
        let currentYear = calendar.component(.year, from: Date())

        for yearOffset in 0..<3 {
            let year = currentYear - yearOffset
            var yearDict: [Int: [DayChartView]] = [:]

            // Generate all 12 months for demo (including future months)
            for month in 1...12 {
                var components = DateComponents()
                components.year = year
                components.month = month
                components.day = 1
                guard let firstOfMonth = calendar.date(from: components),
                      let range = calendar.range(of: .day, in: .month, for: firstOfMonth) else { continue }

                var monthDays: [DayChartView] = []
                for day in 1...range.count {
                    components.day = day
                    if let date = calendar.date(from: components) {
                        let weekDay = calendar.component(.weekday, from: date)
                        // Use average mood color as placeholder (demo cell will assign random colors)
                        let dayView = DayChartView(
                            color: moodTint.color(forMood: .average),
                            weekDay: weekDay,
                            shape: .circle
                        )
                        monthDays.append(dayView)
                    }
                }
                yearDict[month] = monthDays
            }
            result[year] = yearDict
        }
        return result
    }

    /// Generate demo entries for metrics calculation (all 12 months)
    private func demoEntriesForYear(_ year: Int) -> [MoodEntryModel] {
        var entries: [MoodEntryModel] = []
        let calendar = Calendar.current

        // Generate all 12 months for demo
        for month in 1...12 {
            var components = DateComponents()
            components.year = year
            components.month = month
            components.day = 1
            guard let firstOfMonth = calendar.date(from: components),
                  let range = calendar.range(of: .day, in: .month, for: firstOfMonth) else { continue }

            for day in 1...range.count {
                components.day = day
                if let date = calendar.date(from: components) {
                    let entry = MoodEntryModel(
                        forDate: date,
                        mood: DemoAnimationManager.randomPositiveMood(),
                        entryType: .listView,
                        canEdit: false,
                        canDelete: false
                    )
                    entries.append(entry)
                }
            }
        }
        return entries
    }

    /// Year keys to display - demo data or real data
    private var displayYearKeys: [Int] {
        if demoManager.isDemoMode {
            return Array(cachedDemoYearData.keys.sorted(by: >))
        }
        return cachedSortedYearKeys
    }

    /// Year data for a specific year - demo or real
    private func yearDataFor(_ year: Int) -> [Int: [DayChartView]] {
        if demoManager.isDemoMode {
            return cachedDemoYearData[year] ?? [:]
        }
        return viewModel.data[year] ?? [:]
    }

    /// Entries for a specific year - demo or real
    private func entriesFor(_ year: Int) -> [MoodEntryModel] {
        if demoManager.isDemoMode {
            return demoEntriesForYear(year)
        }
        return viewModel.entriesByYear[year] ?? []
    }

    var body: some View {
        ZStack {
            if self.viewModel.data.keys.isEmpty && !demoManager.isDemoMode {
                EmptyHomeView(showVote: false, viewModel: nil)
                    .padding()
            } else {
                ScrollView {
                    VStack(spacing: 16) {
                        ForEach(Array(displayYearKeys.enumerated()), id: \.element) { yearIndex, yearKey in
                            YearCard(
                                year: yearKey,
                                yearData: yearDataFor(yearKey),
                                yearEntries: entriesFor(yearKey),
                                moodTint: moodTint,
                                imagePack: imagePack,
                                theme: theme,
                                filteredDays: filteredDays.currentFilters,
                                yearIndex: yearIndex,
                                demoManager: demoManager,
                                onShare: { metrics, entries, year in
                                    let totalCount = entries.filter { ![.missing, .placeholder].contains($0.mood) }.count
                                    sharePickerData = SharePickerData(
                                        title: String(year),
                                        designs: [
                                            SharingDesign(
                                                name: "Gradient",
                                                shareView: AnyView(AllMoodsV2(metrics: metrics, totalCount: totalCount)),
                                                image: { AllMoodsV2(metrics: metrics, totalCount: totalCount).image }
                                            ),
                                            SharingDesign(
                                                name: "Color Block",
                                                shareView: AnyView(AllMoodsV5(metrics: metrics, totalCount: totalCount)),
                                                image: { AllMoodsV5(metrics: metrics, totalCount: totalCount).image }
                                            ),
                                        ]
                                    )
                                }
                            )
                        }
                    }
                    .padding(.horizontal)
                    .padding(.bottom, 100)
                    .id(moodTint) // Force complete refresh when mood tint changes
                    .background(
                        GeometryReader { proxy in
                            let offset = proxy.frame(in: .named("scroll")).minY
                            Color.clear.preference(key: ViewOffsetKey.self, value: offset)
                        }
                    )
                }
                .scrollDisabled(iapManager.shouldShowPaywall && !demoManager.isDemoMode)
                .mask(
                    // Fade effect when paywall should show: 100% at top, 0% halfway down (disabled in demo mode)
                    (iapManager.shouldShowPaywall && !demoManager.isDemoMode) ?
                    AnyView(
                        LinearGradient(
                            gradient: Gradient(stops: [
                                .init(color: .black, location: 0),
                                .init(color: .black, location: 0.3),
                                .init(color: .clear, location: 0.5)
                            ]),
                            startPoint: .top,
                            endPoint: .bottom
                        )
                    ) : AnyView(Color.black)
                )
            }

            if iapManager.shouldShowPaywall && !demoManager.isDemoMode {
                // Premium year overview prompt - bottom half (hidden in demo mode)
                VStack(spacing: 20) {
                    // Icon
                    ZStack {
                        Circle()
                            .fill(
                                LinearGradient(
                                    colors: [.orange.opacity(0.2), .pink.opacity(0.2)],
                                    startPoint: .topLeading,
                                    endPoint: .bottomTrailing
                                )
                            )
                            .frame(width: 80, height: 80)

                        Image(systemName: "chart.bar.xaxis")
                            .font(.title)
                            .foregroundStyle(
                                LinearGradient(
                                    colors: [.orange, .pink],
                                    startPoint: .topLeading,
                                    endPoint: .bottomTrailing
                                )
                            )
                    }

                    // Text
                    VStack(spacing: 10) {
                        Text("See Your Year at a Glance")
                            .font(.title3.weight(.bold))
                            .foregroundColor(theme.currentTheme.labelColor)
                            .multilineTextAlignment(.center)

                        Text("Discover your emotional rhythm across the year. Spot trends and celebrate how far you've come.")
                            .font(.subheadline)
                            .foregroundColor(theme.currentTheme.labelColor.opacity(0.7))
                            .multilineTextAlignment(.center)
                            .padding(.horizontal, 24)
                    }

                    // Subscribe button
                    Button {
                        showSubscriptionStore = true
                    } label: {
                        HStack {
                            Image(systemName: "chart.bar.fill")
                            Text("Unlock Year Overview")
                        }
                        .font(.headline.weight(.bold))
                        .foregroundColor(.white)
                        .frame(maxWidth: .infinity)
                        .padding(.vertical, 14)
                        .background(
                            LinearGradient(
                                colors: [.orange, .pink],
                                startPoint: .leading,
                                endPoint: .trailing
                            )
                        )
                        .clipShape(RoundedRectangle(cornerRadius: 14))
                    }
                    .padding(.horizontal, 24)
                }
                .padding(.vertical, 24)
                .frame(maxWidth: .infinity)
                .background(theme.currentTheme.bg)
                .frame(maxHeight: .infinity, alignment: .bottom)
                .accessibilityIdentifier(AccessibilityID.Paywall.yearOverlay)
            } else if iapManager.shouldShowTrialWarning && !demoManager.isDemoMode {
                VStack {
                    Spacer()
                    if !trialWarningHidden {
                        IAPWarningView(iapManager: iapManager)
                    }
                }
            }
        }
        .sheet(isPresented: $showSubscriptionStore) {
            ReflectSubscriptionStoreView(source: "year_gate")
        }
        .sheet(item: $sharePickerData) { data in
            SharingStylePickerView(title: data.title, designs: data.designs)
        }
        .onAppear(perform: {
            self.viewModel.filterEntries(startDate: Date(timeIntervalSince1970: 0), endDate: Date())
            cachedSortedYearKeys = Array(viewModel.data.keys.sorted(by: >))
            cachedDemoYearData = computeDemoYearData()
        })
        .onChange(of: viewModel.data.keys.count) { _, _ in
            cachedSortedYearKeys = Array(viewModel.data.keys.sorted(by: >))
        }
        .onChange(of: moodTint) { _, _ in
            // Rebuild chart data when mood tint changes to update colors
            self.viewModel.filterEntries(startDate: Date(timeIntervalSince1970: 0), endDate: Date())
            cachedSortedYearKeys = Array(viewModel.data.keys.sorted(by: >))
        }
        .background(
            theme.currentTheme.bg
                .edgesIgnoringSafeArea(.all)
        )
        .onPreferenceChange(ViewOffsetKey.self) { value in
            withAnimation {
                trialWarningHidden = value < 0
            }
        }
        .padding([.top])
        .preferredColorScheme(theme.preferredColorScheme)
        #if DEBUG
        // Triple-tap to toggle demo mode for video recording
        .onTapGesture(count: 3) {
            if demoManager.isDemoMode {
                demoManager.stopDemoMode()
            } else {
                demoManager.startDemoMode()
            }
        }
        #endif
    }
}

// MARK: - Year Card Component
struct YearCard: View, Equatable {
    let year: Int
    let yearData: [Int: [DayChartView]]
    let yearEntries: [MoodEntryModel]
    let moodTint: MoodTints
    let imagePack: MoodImages
    let theme: Theme
    let filteredDays: [Int]
    let yearIndex: Int  // Which year this is (0 = most recent)
    @ObservedObject var demoManager: DemoAnimationManager
    let onShare: ([MoodMetrics], [MoodEntryModel], Int) -> Void

    private var textColor: Color { theme.currentTheme.labelColor }

    // Equatable conformance to prevent unnecessary re-renders
    static func == (lhs: YearCard, rhs: YearCard) -> Bool {
        lhs.year == rhs.year &&
        lhs.yearEntries.count == rhs.yearEntries.count &&
        lhs.moodTint == rhs.moodTint &&
        lhs.imagePack == rhs.imagePack &&
        lhs.filteredDays == rhs.filteredDays &&
        lhs.theme == rhs.theme &&
        lhs.yearIndex == rhs.yearIndex
    }

    @State private var showStats = true
    @State private var cachedMetrics: [MoodMetrics] = []

    private let months = ["J", "F", "M", "A", "M", "J", "J", "A", "S", "O", "N", "D"]
    private let heatmapColumns = Array(repeating: GridItem(.flexible(), spacing: 2), count: 12)

    // Animated metrics for demo mode - scales based on visible percentage
    private var animatedMetrics: [MoodMetrics] {
        guard demoManager.isDemoMode else { return cachedMetrics }

        let totalCells = yearEntries.filter { $0.mood != .placeholder && $0.mood != .missing }.count
        let visiblePercentage = demoManager.visiblePercentageForYear(totalCells: totalCells, yearIndex: yearIndex)

        // Scale metrics by visible percentage
        return cachedMetrics.map { metric in
            let animatedTotal = Int(Double(metric.total) * visiblePercentage)
            let animatedPercent = metric.percent * Float(visiblePercentage)
            return MoodMetrics(mood: metric.mood, total: animatedTotal, percent: animatedPercent)
        }
    }

    // Cached filtered/sorted metrics to avoid recalculating in ForEach
    private var displayMetrics: [MoodMetrics] {
        animatedMetrics.filter { $0.total > 0 }.sorted { $0.mood.rawValue > $1.mood.rawValue }
    }

    // All 5 moods for share view (shows 0% for moods with no entries)
    private var allMoodMetrics: [MoodMetrics] {
        animatedMetrics.sorted { $0.mood.rawValue > $1.mood.rawValue }
    }

    // Animated total entries for demo mode
    private var animatedTotalEntries: Int {
        let total = yearEntries.filter { ![Mood.missing, Mood.placeholder].contains($0.mood) }.count
        guard demoManager.isDemoMode else { return total }
        let visiblePercentage = demoManager.visiblePercentageForYear(totalCells: total, yearIndex: yearIndex)
        return Int(Double(total) * visiblePercentage)
    }

    private var totalEntries: Int {
        animatedTotalEntries
    }

    private var topMood: Mood? {
        displayMetrics.max(by: { $0.total < $1.total })?.mood
    }

    private var shareableView: some View {
        VStack(spacing: 0) {
            // Header with year
            Text(String(year))
                .font(.largeTitle.weight(.heavy))
                .foregroundColor(textColor)
                .padding(.top, 40)
                .padding(.bottom, 8)

            Text("Year in Review")
                .font(.headline.weight(.medium))
                .foregroundColor(textColor.opacity(0.6))
                .padding(.bottom, 30)

            // Top mood highlight
            if let topMood = topMood {
                VStack(spacing: 12) {
                    Circle()
                        .fill(moodTint.color(forMood: topMood))
                        .frame(width: 120, height: 120)
                        .overlay(
                            imagePack.icon(forMood: topMood)
                                .resizable()
                                .aspectRatio(contentMode: .fit)
                                .foregroundColor(.white)
                                .padding(28)
                                .accessibilityLabel(topMood.strValue)
                        )
                        .shadow(color: moodTint.color(forMood: topMood).opacity(0.5), radius: 25, x: 0, y: 12)

                    Text("Top Mood")
                        .font(.subheadline.weight(.medium))
                        .foregroundColor(textColor.opacity(0.5))

                    Text(topMood.strValue.uppercased())
                        .font(.title2.weight(.bold))
                        .foregroundColor(moodTint.color(forMood: topMood))
                }
                .padding(.bottom, 30)
            }

            // Stats row
            HStack(spacing: 0) {
                VStack(spacing: 4) {
                    Text("\(totalEntries)")
                        .font(.largeTitle.weight(.bold))
                        .foregroundColor(textColor)
                    Text("Days Tracked")
                        .font(.caption.weight(.medium))
                        .foregroundColor(textColor.opacity(0.5))
                }
                .frame(maxWidth: .infinity)
            }
            .padding(.bottom, 30)

            // Mood breakdown with bars
            VStack(spacing: 14) {
                ForEach(allMoodMetrics) { metric in
                    HStack(spacing: 14) {
                        Circle()
                            .fill(moodTint.color(forMood: metric.mood))
                            .frame(width: 36, height: 36)
                            .overlay(
                                imagePack.icon(forMood: metric.mood)
                                    .resizable()
                                    .aspectRatio(contentMode: .fit)
                                    .foregroundColor(.white)
                                    .padding(8)
                                    .accessibilityLabel(metric.mood.strValue)
                            )

                        GeometryReader { geo in
                            ZStack(alignment: .leading) {
                                RoundedRectangle(cornerRadius: 8)
                                    .fill(Color.gray.opacity(0.2))

                                if metric.percent > 0 {
                                    RoundedRectangle(cornerRadius: 8)
                                        .fill(moodTint.color(forMood: metric.mood))
                                        .frame(width: max(8, geo.size.width * CGFloat(metric.percent / 100)))
                                }
                            }
                        }
                        .frame(height: 16)

                        Text("\(Int(metric.percent))%")
                            .font(.body.weight(.semibold))
                            .foregroundColor(textColor)
                            .frame(width: 45, alignment: .trailing)
                    }
                }
            }
            .padding(.horizontal, 32)
            .padding(.bottom, 40)

            // App branding
            Text("ifeel")
                .font(.subheadline.weight(.medium))
                .foregroundColor(textColor.opacity(0.3))
                .padding(.bottom, 20)
        }
        .frame(width: 400)
        .background(theme.currentTheme.secondaryBGColor)
    }

    var body: some View {
        VStack(spacing: 0) {
            // Year Header
            HStack {
                Button(action: {
                if UIAccessibility.isReduceMotionEnabled {
                    showStats.toggle()
                } else {
                    withAnimation(.easeInOut(duration: 0.2)) { showStats.toggle() }
                }
            }) {
                    HStack {
                        Text(String(year))
                            .font(.title2.bold())
                            .foregroundColor(textColor)

                        Text("\(totalEntries) days")
                            .font(.subheadline)
                            .foregroundColor(textColor.opacity(0.6))

                        Image(systemName: showStats ? "chevron.up" : "chevron.down")
                            .font(.caption.weight(.semibold))
                            .foregroundColor(textColor.opacity(0.5))
                            .padding(.leading, 4)
                    }
                }
                .buttonStyle(.plain)
                .accessibilityIdentifier(AccessibilityID.YearView.cardHeader(year: year))

                Spacer()

                Button(action: {
                    onShare(cachedMetrics, yearEntries, year)
                }) {
                    Image(systemName: "square.and.arrow.up")
                        .font(.subheadline.weight(.medium))
                        .foregroundColor(textColor.opacity(0.6))
                }
                .buttonStyle(.plain)
                .accessibilityIdentifier(AccessibilityID.YearView.shareButton)
            }
            .padding(.horizontal, 16)
            .padding(.vertical, 12)

            // Stats Section (collapsible)
            if showStats {
                HStack(spacing: 16) {
                    // Donut Chart
                    MoodDonutChart(metrics: animatedMetrics, moodTint: moodTint)
                        .frame(width: 100, height: 100)
                        .accessibilityIdentifier(AccessibilityID.YearView.donutChart)

                    // Bar Chart
                    VStack(spacing: 6) {
                        ForEach(displayMetrics) { metric in
                            HStack(spacing: 8) {
                                imagePack.icon(forMood: metric.mood)
                                    .resizable()
                                    .aspectRatio(contentMode: .fit)
                                    .frame(width: 16, height: 16)
                                    .foregroundColor(moodTint.color(forMood: metric.mood))
                                    .accessibilityLabel(metric.mood.strValue)

                                GeometryReader { geo in
                                    ZStack(alignment: .leading) {
                                        RoundedRectangle(cornerRadius: 3)
                                            .fill(Color.gray.opacity(0.15))
                                        RoundedRectangle(cornerRadius: 3)
                                            .fill(moodTint.color(forMood: metric.mood))
                                            .frame(width: max(4, geo.size.width * CGFloat(metric.percent / 100)))
                                    }
                                }
                                .frame(height: 8)

                                Text("\(Int(metric.percent))%")
                                    .font(.caption2.weight(.medium))
                                    .foregroundColor(textColor.opacity(0.7))
                                    .frame(width: 32, alignment: .trailing)
                            }
                        }
                    }
                    .frame(maxWidth: .infinity)
                    .accessibilityIdentifier(AccessibilityID.YearView.barChart)
                }
                .padding(.horizontal, 16)
                .padding(.bottom, 12)
                .transition(.opacity.combined(with: .move(edge: .top)))
                .accessibilityIdentifier(AccessibilityID.YearView.statsSection)
            }

            Divider()
                .padding(.horizontal, 16)

            // Month Labels
            HStack(spacing: 2) {
                ForEach(months.indices, id: \.self) { index in
                    Text(months[index])
                        .font(.caption2.weight(.medium))
                        .foregroundColor(textColor.opacity(0.5))
                        .frame(maxWidth: .infinity)
                }
            }
            .padding(.horizontal, 16)
            .padding(.top, 10)
            .padding(.bottom, 4)

            // Heatmap Grid
            YearHeatmapGrid(
                yearData: yearData,
                moodTint: moodTint,
                filteredDays: filteredDays,
                yearIndex: yearIndex,
                demoManager: demoManager
            )
            .accessibilityIdentifier(AccessibilityID.YearView.heatmap)
            .padding(.horizontal, 16)
            .padding(.bottom, 16)
        }
        .background(
            RoundedRectangle(cornerRadius: 16)
                .fill(theme.currentTheme.secondaryBGColor)
        )
        .onAppear {
            // Cache metrics calculation on first appearance
            if cachedMetrics.isEmpty {
                cachedMetrics = Random.createTotalPerc(fromEntries: yearEntries)
            }
        }
    }
}

// MARK: - Year Heatmap Grid
struct YearHeatmapGrid: View {
    let yearData: [Int: [DayChartView]]
    let moodTint: MoodTints
    let filteredDays: [Int]
    let yearIndex: Int  // Which year this grid belongs to (0 = most recent)
    @ObservedObject var demoManager: DemoAnimationManager

    private let heatmapColumns = Array(repeating: GridItem(.flexible(), spacing: 2), count: 12)

    /// Pre-sorted month keys to avoid sorting in ForEach on every render
    private var sortedMonthKeys: [Int] {
        // This is computed once per yearData change, not on every body access
        // since yearData is a let constant passed from parent
        Array(yearData.keys.sorted(by: <))
    }

    /// Total days across all months for animation positioning
    private var totalDays: Int {
        yearData.values.reduce(0) { $0 + $1.count }
    }

    var body: some View {
        LazyVGrid(columns: heatmapColumns, spacing: 2) {
            ForEach(Array(sortedMonthKeys.enumerated()), id: \.element) { monthIndex, monthKey in
                if let monthData = yearData[monthKey] {
                    DemoMonthColumn(
                        monthData: monthData,
                        moodTint: moodTint,
                        filteredDays: filteredDays,
                        monthIndex: monthIndex,
                        totalMonths: 12,
                        yearIndex: yearIndex,
                        demoManager: demoManager
                    )
                }
            }
        }
    }
}

// MARK: - Month Column (Vertical stack of days)
struct MonthColumn: View {
    let monthData: [DayChartView]
    let moodTint: MoodTints
    let filteredDays: [Int]

    var body: some View {
        VStack(spacing: 2) {
            ForEach(monthData, id: \.self) { dayView in
                YearHeatmapCell(
                    color: dayView.color,
                    weekDay: dayView.weekDay,
                    isFiltered: filteredDays.contains(dayView.weekDay)
                )
            }
        }
    }
}

// MARK: - Demo Month Column (with animation support)
struct DemoMonthColumn: View {
    let monthData: [DayChartView]
    let moodTint: MoodTints
    let filteredDays: [Int]
    let monthIndex: Int
    let totalMonths: Int
    let yearIndex: Int  // Which year this column belongs to
    @ObservedObject var demoManager: DemoAnimationManager

    var body: some View {
        VStack(spacing: 2) {
            ForEach(Array(monthData.enumerated()), id: \.element) { dayIndex, dayView in
                DemoYearHeatmapCell(
                    color: dayView.color,
                    weekDay: dayView.weekDay,
                    isFiltered: filteredDays.contains(dayView.weekDay),
                    row: dayIndex,
                    column: monthIndex,
                    totalRows: monthData.count,
                    totalColumns: totalMonths,
                    moodTint: moodTint,
                    yearIndex: yearIndex,
                    demoManager: demoManager
                )
            }
        }
    }
}

// MARK: - Year Heatmap Cell
struct YearHeatmapCell: View {
    let color: Color
    let weekDay: Int
    let isFiltered: Bool

    var body: some View {
        RoundedRectangle(cornerRadius: 2)
            .fill(cellColor)
            .aspectRatio(1, contentMode: .fit)
            .accessibilityLabel(accessibilityDescription)
    }

    private var accessibilityDescription: String {
        if !isFiltered {
            return "Filtered out"
        } else if color == Mood.placeholder.color {
            return "Empty"
        } else if color == Mood.missing.color {
            return "No mood logged"
        } else {
            return "Mood entry"
        }
    }

    private var cellColor: Color {
        if !isFiltered {
            return Color.gray.opacity(0.1)
        } else if color == Mood.placeholder.color || color == Mood.missing.color {
            return Color.gray.opacity(0.2)
        } else {
            return color
        }
    }
}

// MARK: - Demo Year Heatmap Cell (with animation support)
struct DemoYearHeatmapCell: View {
    let color: Color
    let weekDay: Int
    let isFiltered: Bool
    let row: Int
    let column: Int
    let totalRows: Int
    let totalColumns: Int
    let moodTint: MoodTints
    let yearIndex: Int  // Which year this is (0 = most recent)
    @ObservedObject var demoManager: DemoAnimationManager

    /// Random mood for this cell (computed once and cached)
    @State private var randomMood: Mood = .great

    var body: some View {
        ZStack {
            // Background: Gray grid cell always visible at 1x scale
            RoundedRectangle(cornerRadius: 2)
                .fill(Color.gray.opacity(0.3))
                .aspectRatio(1, contentMode: .fit)

            // Foreground: Animated mood color that scales 2x -> 1x
            if demoManager.isDemoMode {
                RoundedRectangle(cornerRadius: 2)
                    .fill(moodTint.color(forMood: randomMood))
                    .aspectRatio(1, contentMode: .fit)
                    .scaleEffect(isAnimated ? 1.0 : 2.0)
                    .opacity(isAnimated ? 1.0 : 0.0)
                    .animation(.spring(response: 0.3, dampingFraction: 0.7), value: isAnimated)
            } else {
                // Normal mode - just show the actual color
                RoundedRectangle(cornerRadius: 2)
                    .fill(normalCellColor)
                    .aspectRatio(1, contentMode: .fit)
            }
        }
        .onAppear {
            // Generate random mood once when cell appears
            randomMood = DemoAnimationManager.randomPositiveMood()
        }
        .accessibilityLabel(accessibilityDescription)
    }

    private var accessibilityDescription: String {
        if !isFiltered {
            return "Filtered out"
        } else if color == Mood.placeholder.color {
            return "Empty"
        } else if color == Mood.missing.color {
            return "No mood logged"
        } else {
            return "Mood entry"
        }
    }

    /// Whether this cell has been animated (filled with color)
    private var isAnimated: Bool {
        if !demoManager.isDemoMode {
            return true // Normal mode - always show
        }
        if !demoManager.animationStarted {
            return false // Demo mode but animation hasn't started
        }

        return demoManager.isCellVisibleForYear(
            row: row,
            column: column,
            totalRows: totalRows,
            totalColumns: totalColumns,
            yearIndex: yearIndex
        )
    }

    /// Color for normal (non-demo) mode
    private var normalCellColor: Color {
        if !isFiltered {
            return Color.gray.opacity(0.1)
        } else if color == Mood.placeholder.color || color == Mood.missing.color {
            return Color.gray.opacity(0.2)
        } else {
            return color
        }
    }
}

// MARK: - Donut Chart
struct MoodDonutChart: View {
    let metrics: [MoodMetrics]
    let moodTint: MoodTints

    private var filteredMetrics: [MoodMetrics] {
        metrics.filter { $0.total > 0 }
    }

    private var total: Int {
        metrics.reduce(0) { $0 + $1.total }
    }

    var body: some View {
        GeometryReader { geo in
            let size = min(geo.size.width, geo.size.height)
            let lineWidth = size * 0.2

            ZStack {
                // Background ring
                Circle()
                    .stroke(Color.gray.opacity(0.15), lineWidth: lineWidth)

                // Mood segments
                ForEach(Array(filteredMetrics.enumerated()), id: \.element.id) { index, metric in
                    Circle()
                        .trim(from: startAngle(for: index), to: endAngle(for: index))
                        .stroke(moodTint.color(forMood: metric.mood), style: StrokeStyle(lineWidth: lineWidth, lineCap: .butt))
                        .rotationEffect(.degrees(-90))
                }

                // Center text
                VStack(spacing: 0) {
                    Text("\(total)")
                        .font(.system(size: size * 0.22, weight: .bold, design: .rounded))
                    Text("days")
                        .font(.system(size: size * 0.12, weight: .medium))
                        .foregroundColor(.secondary)
                }
            }
            .frame(width: size, height: size)
        }
    }

    private func startAngle(for index: Int) -> CGFloat {
        let precedingTotal = filteredMetrics.prefix(index).reduce(0) { $0 + $1.total }
        return CGFloat(precedingTotal) / CGFloat(max(1, total))
    }

    private func endAngle(for index: Int) -> CGFloat {
        let includingCurrent = filteredMetrics.prefix(index + 1).reduce(0) { $0 + $1.total }
        return CGFloat(includingCurrent) / CGFloat(max(1, total))
    }
}

struct YearView_Previews: PreviewProvider {
    static var previews: some View {
        Group {
            YearView(viewModel: YearViewModel())

            YearView(viewModel: YearViewModel())
                .preferredColorScheme(.dark)
        }
    }
}
