//
//  DateRangePicker.swift
//  SportsTime
//
//  Extracted from TripCreationView - reusable date range picker component.
//

import SwiftUI

struct DateRangePicker: View {
    @Binding var startDate: Date
    @Binding var endDate: Date
    @Environment(\.colorScheme) private var colorScheme

    @State private var displayedMonth: Date = Date()
    @State private var selectionState: SelectionState = .none

    enum SelectionState {
        case none
        case startSelected
        case complete
    }

    private let calendar = Calendar.current
    private let daysOfWeek = ["S", "M", "T", "W", "T", "F", "S"]

    private var monthYearString: String {
        let formatter = DateFormatter()
        formatter.dateFormat = "MMMM yyyy"
        return formatter.string(from: displayedMonth)
    }

    private var daysInMonth: [Date?] {
        guard let monthInterval = calendar.dateInterval(of: .month, for: displayedMonth),
              let monthFirstWeek = calendar.dateInterval(of: .weekOfMonth, for: monthInterval.start) else {
            return []
        }

        var days: [Date?] = []
        let startOfMonth = monthInterval.start
        let endOfMonth = calendar.date(byAdding: .day, value: -1, to: monthInterval.end)!

        // Get the first day of the week containing the first day of the month
        var currentDate = monthFirstWeek.start

        // Add days until we've covered the month
        while currentDate <= endOfMonth || days.count % 7 != 0 {
            if currentDate >= startOfMonth && currentDate <= endOfMonth {
                days.append(currentDate)
            } else if currentDate < startOfMonth {
                days.append(nil) // Placeholder for days before month starts
            } else if days.count % 7 != 0 {
                days.append(nil) // Placeholder to complete the last week
            } else {
                break
            }
            currentDate = calendar.date(byAdding: .day, value: 1, to: currentDate)!
        }

        return days
    }

    private var tripDuration: Int {
        let components = calendar.dateComponents([.day], from: startDate, to: endDate)
        return (components.day ?? 0) + 1
    }

    var body: some View {
        VStack(spacing: Theme.Spacing.md) {
            // Selected range summary
            selectedRangeSummary

            // Month navigation
            monthNavigation

            // Days of week header
            daysOfWeekHeader

            // Calendar grid
            calendarGrid

            // Trip duration
            tripDurationBadge
        }
        .onAppear {
            // Initialize displayed month to show the start date's month
            displayedMonth = calendar.startOfDay(for: startDate)
            // If dates are already selected (endDate > startDate), show complete state
            if endDate > startDate {
                selectionState = .complete
            }
        }
    }

    private var selectedRangeSummary: some View {
        HStack(spacing: Theme.Spacing.md) {
            // Start date
            VStack(alignment: .leading, spacing: 4) {
                Text("START")
                    .font(.caption2)
                    .foregroundStyle(Theme.textMuted(colorScheme))
                Text(startDate.formatted(.dateTime.month(.abbreviated).day().year()))
                    .font(.body)
                    .foregroundStyle(Theme.warmOrange)
            }
            .frame(maxWidth: .infinity, alignment: .leading)

            // Arrow
            Image(systemName: "arrow.right")
                .font(.subheadline)
                .foregroundStyle(Theme.textMuted(colorScheme))

            // End date
            VStack(alignment: .trailing, spacing: 4) {
                Text("END")
                    .font(.caption2)
                    .foregroundStyle(Theme.textMuted(colorScheme))
                Text(endDate.formatted(.dateTime.month(.abbreviated).day().year()))
                    .font(.body)
                    .foregroundStyle(Theme.warmOrange)
            }
            .frame(maxWidth: .infinity, alignment: .trailing)
        }
        .padding(Theme.Spacing.md)
        .background(Theme.cardBackgroundElevated(colorScheme))
        .clipShape(RoundedRectangle(cornerRadius: Theme.CornerRadius.medium))
    }

    private var monthNavigation: some View {
        HStack {
            Button {
                withAnimation(.easeInOut(duration: 0.2)) {
                    displayedMonth = calendar.date(byAdding: .month, value: -1, to: displayedMonth) ?? displayedMonth
                }
            } label: {
                Image(systemName: "chevron.left")
                    .font(.body)
                    .foregroundStyle(Theme.warmOrange)
                    .frame(width: 36, height: 36)
                    .background(Theme.warmOrange.opacity(0.15))
                    .clipShape(Circle())
            }

            Spacer()

            Text(monthYearString)
                .font(.headline)
                .foregroundStyle(Theme.textPrimary(colorScheme))

            Spacer()

            Button {
                withAnimation(.easeInOut(duration: 0.2)) {
                    displayedMonth = calendar.date(byAdding: .month, value: 1, to: displayedMonth) ?? displayedMonth
                }
            } label: {
                Image(systemName: "chevron.right")
                    .font(.body)
                    .foregroundStyle(Theme.warmOrange)
                    .frame(width: 36, height: 36)
                    .background(Theme.warmOrange.opacity(0.15))
                    .clipShape(Circle())
            }
        }
    }

    private var daysOfWeekHeader: some View {
        HStack(spacing: 0) {
            ForEach(Array(daysOfWeek.enumerated()), id: \.offset) { _, day in
                Text(day)
                    .font(.caption)
                    .foregroundStyle(Theme.textMuted(colorScheme))
                    .frame(maxWidth: .infinity)
            }
        }
    }

    private var calendarGrid: some View {
        let columns = Array(repeating: GridItem(.flexible(), spacing: 4), count: 7)

        return LazyVGrid(columns: columns, spacing: 4) {
            ForEach(Array(daysInMonth.enumerated()), id: \.offset) { _, date in
                if let date = date {
                    DayCell(
                        date: date,
                        isStart: calendar.isDate(date, inSameDayAs: startDate),
                        isEnd: calendar.isDate(date, inSameDayAs: endDate),
                        isInRange: isDateInRange(date),
                        isToday: calendar.isDateInToday(date),
                        onTap: { handleDateTap(date) }
                    )
                } else {
                    Color.clear
                        .frame(height: 40)
                }
            }
        }
    }

    private var tripDurationBadge: some View {
        HStack(spacing: Theme.Spacing.xs) {
            Image(systemName: "calendar.badge.clock")
                .foregroundStyle(Theme.warmOrange)
            Text("\(tripDuration) day\(tripDuration == 1 ? "" : "s")")
                .font(.subheadline)
                .foregroundStyle(Theme.textSecondary(colorScheme))
        }
        .frame(maxWidth: .infinity, alignment: .center)
        .padding(.top, Theme.Spacing.xs)
    }

    private func isDateInRange(_ date: Date) -> Bool {
        let start = calendar.startOfDay(for: startDate)
        let end = calendar.startOfDay(for: endDate)
        let current = calendar.startOfDay(for: date)
        return current > start && current < end
    }

    private func handleDateTap(_ date: Date) {
        let today = calendar.startOfDay(for: Date())
        let tappedDate = calendar.startOfDay(for: date)

        // Don't allow selecting dates in the past
        if tappedDate < today {
            return
        }

        switch selectionState {
        case .none, .complete:
            // First tap: set start date, reset end to same day
            startDate = date
            endDate = date
            selectionState = .startSelected

        case .startSelected:
            // Second tap: set end date (if after start)
            if date >= startDate {
                endDate = date
            } else {
                // If tapped date is before start, make it the new start
                endDate = startDate
                startDate = date
            }
            selectionState = .complete
        }
    }
}

// MARK: - Day Cell

struct DayCell: View {
    let date: Date
    let isStart: Bool
    let isEnd: Bool
    let isInRange: Bool
    let isToday: Bool
    let onTap: () -> Void

    @Environment(\.colorScheme) private var colorScheme

    private let calendar = Calendar.current

    private var dayNumber: String {
        "\(calendar.component(.day, from: date))"
    }

    private var isPast: Bool {
        calendar.startOfDay(for: date) < calendar.startOfDay(for: Date())
    }

    var body: some View {
        Button(action: onTap) {
            ZStack {
                // Range highlight background (stretches edge to edge)
                if isInRange || isStart || isEnd {
                    HStack(spacing: 0) {
                        Rectangle()
                            .fill(Theme.warmOrange.opacity(0.15))
                            .frame(maxWidth: .infinity)
                            .opacity(isStart && !isEnd ? 0 : 1)
                            .offset(x: isStart ? 20 : 0)

                        Rectangle()
                            .fill(Theme.warmOrange.opacity(0.15))
                            .frame(maxWidth: .infinity)
                            .opacity(isEnd && !isStart ? 0 : 1)
                            .offset(x: isEnd ? -20 : 0)
                    }
                    .opacity(isStart && isEnd ? 0 : 1) // Hide when start == end
                }

                // Day circle
                ZStack {
                    if isStart || isEnd {
                        Circle()
                            .fill(Theme.warmOrange)
                    } else if isToday {
                        Circle()
                            .stroke(Theme.warmOrange, lineWidth: 2)
                    }

                    Text(dayNumber)
                        .font(.system(size: 14, weight: (isStart || isEnd) ? .bold : .medium))
                        .foregroundStyle(
                            isPast ? Theme.textMuted(colorScheme).opacity(0.5) :
                            (isStart || isEnd) ? .white :
                            isToday ? Theme.warmOrange :
                            Theme.textPrimary(colorScheme)
                        )
                }
                .frame(width: 36, height: 36)
            }
        }
        .buttonStyle(.plain)
        .disabled(isPast)
        .frame(height: 40)
    }
}

// MARK: - Preview

#Preview {
    DateRangePicker(
        startDate: .constant(Date()),
        endDate: .constant(Date().addingTimeInterval(86400 * 7))
    )
    .padding()
}
