//
//  HistoryView.swift
//  Andromida
//
//  A scrollable calendar history view showing daily habit completion.
//

import SwiftUI
import Bedrock

/// Main history view with scrollable months and ritual filtering.
/// Wrapper struct to make Date identifiable for sheet presentation
struct IdentifiableDate: Identifiable {
    let id = UUID()
    let date: Date
}

struct HistoryView: View {
    @Bindable var store: RitualStore
    @Environment(\.horizontalSizeClass) private var horizontalSizeClass
    @State private var selectedRitual: Ritual?
    @State private var selectedDateItem: IdentifiableDate?
    @State private var monthsToShow = 2
    @State private var refreshToken = UUID()
    @State private var cachedProgressByDate: [Date: Double] = [:]
    
    private let calendar = Calendar.current
    private let baseMonthsToShow = 2
    private let monthChunkSize = 6
    
    /// Whether to use wide layout (2 columns) on iPad/landscape
    private var useWideLayout: Bool {
        horizontalSizeClass == .regular
    }
    
    /// Grid columns for month cards - 2 columns on regular width, 1 on compact
    private var monthColumns: [GridItem] {
        AdaptiveColumns.columns(
            compactCount: 1,
            regularCount: 2,
            spacing: Design.Spacing.large,
            horizontalSizeClass: horizontalSizeClass
        )
    }
    
    /// Generate months based on expanded state
    /// - Collapsed: Last month + current month (2 months)
    /// - Expanded: Up to 12 months of history
    /// Months are ordered oldest first, newest last (chronological order)
    private var months: [Date] {
        let today = Date()
        let currentMonth = calendar.date(from: calendar.dateComponents([.year, .month], from: today)) ?? today
        
        // Determine how far back to go
        let totalAvailableMonths = totalMonthsAvailable(from: currentMonth)
        let effectiveMonthsToShow = min(monthsToShow, totalAvailableMonths)
        let monthsBack = max(0, effectiveMonthsToShow - 1)
        guard let startMonth = calendar.date(byAdding: .month, value: -monthsBack, to: currentMonth) else {
            return [currentMonth]
        }
        
        // Build list of months in chronological order (oldest first)
        var result: [Date] = []
        var current = startMonth
        
        while current <= currentMonth {
            result.append(current)
            current = calendar.date(byAdding: .month, value: 1, to: current) ?? current
        }
        
        return result
    }
    
    /// Check if there's more history available beyond what's shown
    private var hasMoreHistory: Bool {
        guard let earliestActivity = store.earliestActivityDate() else { return false }
        guard let oldestVisibleMonth = months.first else { return false }
        let oldestVisibleStart = calendar.startOfDay(for: oldestVisibleMonth)
        let earliestStart = calendar.startOfDay(for: earliestActivity)
        return earliestStart < oldestVisibleStart
    }
    
    var body: some View {
        ScrollView(.vertical, showsIndicators: false) {
            VStack(alignment: .leading, spacing: Design.Spacing.large) {
                // Header with Show More/Less button
                headerSection
                
                // Ritual filter picker
                ritualPicker
                
                // Month calendars - 2-column grid on iPad/landscape
                LazyVGrid(columns: monthColumns, alignment: .top, spacing: Design.Spacing.large) {
                    ForEach(months, id: \.self) { month in
                        HistoryMonthView(
                            month: month,
                            selectedRitual: selectedRitual,
                            completionRate: { date, ritual in
                                let day = calendar.startOfDay(for: date)
                                return cachedProgressByDate[day] ?? store.completionRate(for: day, ritual: ritual)
                            },
                            onDayTapped: { date in
                                selectedDateItem = IdentifiableDate(date: date)
                            }
                        )
                    }
                }
                .id(refreshToken)
            }
            .padding(Design.Spacing.large)
        }
        .background(LinearGradient(
            colors: [AppSurface.primary, AppSurface.secondary],
            startPoint: .topLeading,
            endPoint: .bottomTrailing
        ))
        .onChange(of: store.rituals) { _, newRituals in
            if let selectedRitual {
                self.selectedRitual = newRituals.first { $0.id == selectedRitual.id }
            }
            refreshProgressCache()
            refreshToken = UUID()
        }
        .onChange(of: selectedRitual) { _, _ in
            refreshProgressCache()
            refreshToken = UUID()
        }
        .onChange(of: monthsToShow) { _, _ in
            refreshProgressCache()
            refreshToken = UUID()
        }
        .onAppear {
            refreshProgressCache()
        }
        .sheet(item: $selectedDateItem) { item in
            HistoryDayDetailSheet(
                date: item.date,
                completions: store.habitCompletions(for: item.date, ritual: selectedRitual),
                store: store
            )
        }
    }
    
    private var headerSection: some View {
        HStack(alignment: .top) {
            SectionHeaderView(
                title: String(localized: "History"),
                subtitle: String(localized: "Your journey over time")
            )
            
            Spacer()
            
            if hasMoreHistory || monthsToShow > baseMonthsToShow {
                Button {
                    withAnimation(.easeInOut(duration: Design.Animation.standard)) {
                        if monthsToShow > baseMonthsToShow {
                            monthsToShow = baseMonthsToShow
                        } else {
                            let totalAvailableMonths = totalMonthsAvailable(from: Date())
                            monthsToShow = min(monthsToShow + monthChunkSize, totalAvailableMonths)
                        }
                    }
                } label: {
                    HStack(spacing: Design.Spacing.xSmall) {
                        Text(monthsToShow > baseMonthsToShow ? String(localized: "Show less") : String(localized: "Show more"))
                            .font(.subheadline)
                        Image(systemName: monthsToShow > baseMonthsToShow ? "chevron.up" : "chevron.down")
                            .font(.caption)
                    }
                    .foregroundStyle(AppAccent.primary)
                }
                .buttonStyle(.plain)
            }
        }
    }
    
    private var ritualPicker: some View {
        ScrollView(.horizontal, showsIndicators: false) {
            HStack(spacing: Design.Spacing.small) {
                // "All" option
                filterChip(
                    title: String(localized: "All"),
                    isSelected: selectedRitual == nil,
                    action: { selectedRitual = nil }
                )
                
                // Individual rituals
                ForEach(store.rituals) { ritual in
                    filterChip(
                        title: ritual.title,
                        isSelected: selectedRitual?.id == ritual.id,
                        action: { selectedRitual = ritual }
                    )
                }
            }
        }
    }
    
    private func filterChip(title: String, isSelected: Bool, action: @escaping () -> Void) -> some View {
        Button(action: action) {
            Text(title)
                .font(.subheadline)
                .fontWeight(isSelected ? .semibold : .regular)
                .foregroundStyle(isSelected ? AppTextColors.inverse : AppTextColors.primary)
                .padding(.horizontal, Design.Spacing.medium)
                .padding(.vertical, Design.Spacing.small)
                .background(isSelected ? AppAccent.primary : AppSurface.card)
                .clipShape(.capsule)
        }
        .buttonStyle(.plain)
        .accessibilityAddTraits(isSelected ? .isSelected : [])
    }

    private func refreshProgressCache() {
        Task { @MainActor in
            await Task.yield()
            let snapshotMonths = months
            let selected = selectedRitual
            var result: [Date: Double] = [:]
            let today = calendar.startOfDay(for: Date())

            for month in snapshotMonths {
                guard let firstOfMonth = calendar.date(from: calendar.dateComponents([.year, .month], from: month)),
                      let range = calendar.range(of: .day, in: .month, for: firstOfMonth) else {
                    continue
                }

                for day in range {
                    guard let date = calendar.date(byAdding: .day, value: day - 1, to: firstOfMonth) else { continue }
                    let normalizedDate = calendar.startOfDay(for: date)
                    guard normalizedDate <= today else { continue }
                    result[normalizedDate] = store.completionRate(for: normalizedDate, ritual: selected)
                }
            }
            let cache = result
            cachedProgressByDate = cache
        }
    }

    private func totalMonthsAvailable(from currentMonth: Date) -> Int {
        guard let earliestActivity = store.earliestActivityDate() else { return baseMonthsToShow }
        let earliestMonth = calendar.date(from: calendar.dateComponents([.year, .month], from: earliestActivity)) ?? currentMonth
        let comps = calendar.dateComponents([.month], from: earliestMonth, to: currentMonth)
        let months = (comps.month ?? 0) + 1
        return max(baseMonthsToShow, months)
    }
}

#Preview {
    HistoryView(store: RitualStore.preview)
}
