//
//  TripOptionsView.swift
//  SportsTime
//
//  Displays trip options for user selection after planning completes.
//

import SwiftUI

// MARK: - Sort Options

enum TripSortOption: String, CaseIterable, Identifiable {
    case recommended = "Recommended"
    case mostCities = "Most Cities"
    case mostGames = "Most Games"
    case leastGames = "Least Games"
    case mostMiles = "Most Miles"
    case leastMiles = "Least Miles"
    case bestEfficiency = "Best Efficiency"

    var id: String { rawValue }

    var icon: String {
        switch self {
        case .recommended: return "star.fill"
        case .mostCities: return "mappin.and.ellipse"
        case .mostGames, .leastGames: return "sportscourt"
        case .mostMiles, .leastMiles: return "road.lanes"
        case .bestEfficiency: return "gauge.with.dots.needle.33percent"
        }
    }
}

// MARK: - Pace Filter

enum TripPaceFilter: String, CaseIterable, Identifiable {
    case all = "All"
    case packed = "Packed"
    case moderate = "Moderate"
    case relaxed = "Relaxed"

    var id: String { rawValue }

    var icon: String {
        switch self {
        case .all: return "rectangle.stack"
        case .packed: return "flame"
        case .moderate: return "equal.circle"
        case .relaxed: return "leaf"
        }
    }
}

// MARK: - Cities Filter

enum CitiesFilter: Int, CaseIterable, Identifiable {
    case noLimit = 100
    case fifteen = 15
    case ten = 10
    case five = 5
    case four = 4
    case three = 3
    case two = 2

    var id: Int { rawValue }

    var displayName: String {
        switch self {
        case .noLimit: return "No Limit"
        case .fifteen: return "15"
        case .ten: return "10"
        case .five: return "5"
        case .four: return "4"
        case .three: return "3"
        case .two: return "2"
        }
    }
}

// MARK: - Trip Options Grouper

enum TripOptionsGrouper {
    typealias GroupedOptions = (header: String, options: [ItineraryOption])

    static func groupByCityCount(_ options: [ItineraryOption], ascending: Bool) -> [GroupedOptions] {
        let grouped = Dictionary(grouping: options) { option in
            Set(option.stops.map { $0.city }).count
        }
        let sorted = ascending ? grouped.sorted { $0.key < $1.key } : grouped.sorted { $0.key > $1.key }
        return sorted.map { count, opts in
            ("\(count) \(count == 1 ? "city" : "cities")", opts)
        }
    }

    static func groupByGameCount(_ options: [ItineraryOption], ascending: Bool) -> [GroupedOptions] {
        let grouped = Dictionary(grouping: options) { $0.totalGames }
        let sorted = ascending ? grouped.sorted { $0.key < $1.key } : grouped.sorted { $0.key > $1.key }
        return sorted.map { count, opts in
            ("\(count) \(count == 1 ? "game" : "games")", opts)
        }
    }

    static func groupByMileageRange(_ options: [ItineraryOption], ascending: Bool) -> [GroupedOptions] {
        let ranges: [(min: Int, max: Int, label: String)] = [
            (0, 500, "0-500 mi"),
            (500, 1000, "500-1000 mi"),
            (1000, 1500, "1000-1500 mi"),
            (1500, 2000, "1500-2000 mi"),
            (2000, Int.max, "2000+ mi")
        ]

        var groupedDict: [String: [ItineraryOption]] = [:]
        for option in options {
            let miles = Int(option.totalDistanceMiles)
            for range in ranges {
                if miles >= range.min && miles < range.max {
                    groupedDict[range.label, default: []].append(option)
                    break
                }
            }
        }

        // Sort by range order
        let rangeOrder = ascending ? ranges : ranges.reversed()
        return rangeOrder.compactMap { range in
            guard let opts = groupedDict[range.label], !opts.isEmpty else { return nil }
            return (range.label, opts)
        }
    }
}

// MARK: - Trip Options View

struct TripOptionsView: View {
    let options: [ItineraryOption]
    let games: [String: RichGame]
    let preferences: TripPreferences?
    let convertToTrip: (ItineraryOption) -> Trip

    @State private var selectedTrip: Trip?
    @State private var showTripDetail = false
    @State private var sortOption: TripSortOption = .recommended
    @State private var citiesFilter: CitiesFilter = .noLimit
    @State private var paceFilter: TripPaceFilter = .all
    @Environment(\.colorScheme) private var colorScheme

    // MARK: - Computed Properties

    private func uniqueCityCount(for option: ItineraryOption) -> Int {
        Set(option.stops.map { $0.city }).count
    }

    private var filteredAndSortedOptions: [ItineraryOption] {
        // Apply filters first
        let filtered = options.filter { option in
            let cityCount = uniqueCityCount(for: option)

            // City filter
            guard cityCount <= citiesFilter.rawValue else { return false }

            // Pace filter based on games per day ratio
            switch paceFilter {
            case .all:
                return true
            case .packed:
                // High game density: > 0.8 games per day
                return gamesPerDay(for: option) >= 0.8
            case .moderate:
                // Medium density: 0.4-0.8 games per day
                let gpd = gamesPerDay(for: option)
                return gpd >= 0.4 && gpd < 0.8
            case .relaxed:
                // Low density: < 0.4 games per day
                return gamesPerDay(for: option) < 0.4
            }
        }

        // Then apply sorting
        switch sortOption {
        case .recommended:
            return filtered
        case .mostCities:
            return filtered.sorted { $0.stops.count > $1.stops.count }
        case .mostGames:
            return filtered.sorted { $0.totalGames > $1.totalGames }
        case .leastGames:
            return filtered.sorted { $0.totalGames < $1.totalGames }
        case .mostMiles:
            return filtered.sorted { $0.totalDistanceMiles > $1.totalDistanceMiles }
        case .leastMiles:
            return filtered.sorted { $0.totalDistanceMiles < $1.totalDistanceMiles }
        case .bestEfficiency:
            return filtered.sorted {
                let effA = $0.totalDrivingHours > 0 ? Double($0.totalGames) / $0.totalDrivingHours : 0
                let effB = $1.totalDrivingHours > 0 ? Double($1.totalGames) / $1.totalDrivingHours : 0
                return effA > effB
            }
        }
    }

    private func gamesPerDay(for option: ItineraryOption) -> Double {
        guard let first = option.stops.first,
              let last = option.stops.last else { return 0 }
        let days = max(1, Calendar.current.dateComponents([.day], from: first.arrivalDate, to: last.departureDate).day ?? 1)
        return Double(option.totalGames) / Double(days)
    }

    private var groupedOptions: [TripOptionsGrouper.GroupedOptions] {
        switch sortOption {
        case .recommended, .bestEfficiency:
            // Flat list, no grouping
            return [("", filteredAndSortedOptions)]

        case .mostCities:
            return TripOptionsGrouper.groupByCityCount(filteredAndSortedOptions, ascending: false)

        case .mostGames:
            return TripOptionsGrouper.groupByGameCount(filteredAndSortedOptions, ascending: false)

        case .leastGames:
            return TripOptionsGrouper.groupByGameCount(filteredAndSortedOptions, ascending: true)

        case .mostMiles:
            return TripOptionsGrouper.groupByMileageRange(filteredAndSortedOptions, ascending: false)

        case .leastMiles:
            return TripOptionsGrouper.groupByMileageRange(filteredAndSortedOptions, ascending: true)
        }
    }

    var body: some View {
        ScrollView {
            LazyVStack(spacing: 16) {
                // Hero header
                VStack(spacing: 8) {
                    Image(systemName: "point.topright.arrow.triangle.backward.to.point.bottomleft.scurvepath.fill")
                        .font(.largeTitle)
                        .foregroundStyle(Theme.warmOrange)

                    Text("\(filteredAndSortedOptions.count) of \(options.count) Routes")
                        .font(.title2)
                        .foregroundStyle(Theme.textPrimary(colorScheme))
                }
                .padding(.top, Theme.Spacing.lg)

                // Filters section
                filtersSection
                    .padding(.horizontal, Theme.Spacing.md)

                // Options list (grouped when applicable)
                if filteredAndSortedOptions.isEmpty {
                    emptyFilterState
                        .padding(.top, Theme.Spacing.xl)
                } else {
                    ForEach(Array(groupedOptions.enumerated()), id: \.offset) { _, group in
                        VStack(alignment: .leading, spacing: Theme.Spacing.sm) {
                            // Section header (only if non-empty)
                            if !group.header.isEmpty {
                                HStack {
                                    Text(group.header)
                                        .font(.headline)
                                        .foregroundStyle(Theme.textPrimary(colorScheme))

                                    Spacer()

                                    Text("\(group.options.count)")
                                        .font(.subheadline)
                                        .foregroundStyle(Theme.textMuted(colorScheme))
                                }
                                .padding(.horizontal, Theme.Spacing.md)
                                .padding(.top, Theme.Spacing.md)
                            }

                            // Options in this group
                            ForEach(group.options) { option in
                                TripOptionCard(
                                    option: option,
                                    games: games,
                                    onSelect: {
                                        selectedTrip = convertToTrip(option)
                                        showTripDetail = true
                                    }
                                )
                                .padding(.horizontal, Theme.Spacing.md)
                            }
                        }
                    }
                }
            }
            .padding(.bottom, Theme.Spacing.xxl)
        }
        .themedBackground()
        .navigationDestination(isPresented: $showTripDetail) {
            if let trip = selectedTrip {
                TripDetailView(trip: trip)
            }
        }
        .onChange(of: showTripDetail) { _, isShowing in
            if !isShowing {
                selectedTrip = nil
            }
        }
    }

    private var sortPicker: some View {
        Menu {
            ForEach(TripSortOption.allCases) { option in
                Button {
                    withAnimation(.easeInOut(duration: 0.2)) {
                        sortOption = option
                    }
                } label: {
                    Label(option.rawValue, systemImage: option.icon)
                }
            }
        } label: {
            HStack(spacing: 8) {
                Image(systemName: sortOption.icon)
                    .font(.subheadline)
                Text(sortOption.rawValue)
                    .font(.subheadline)
                Image(systemName: "chevron.down")
                    .font(.caption)
            }
            .foregroundStyle(Theme.textPrimary(colorScheme))
            .padding(.horizontal, 16)
            .padding(.vertical, 10)
            .background(Theme.cardBackground(colorScheme))
            .clipShape(Capsule())
            .overlay(
                Capsule()
                    .strokeBorder(Theme.textMuted(colorScheme).opacity(0.2), lineWidth: 1)
            )
        }
    }

    // MARK: - Filters Section

    private var filtersSection: some View {
        VStack(spacing: Theme.Spacing.md) {
            // Sort and Pace row
            HStack(spacing: Theme.Spacing.sm) {
                sortPicker
                Spacer()
                pacePicker
            }

            // Cities picker
            citiesPicker
        }
        .padding(Theme.Spacing.md)
        .background(Theme.cardBackground(colorScheme))
        .clipShape(RoundedRectangle(cornerRadius: Theme.CornerRadius.medium))
    }

    private var pacePicker: some View {
        Menu {
            ForEach(TripPaceFilter.allCases) { pace in
                Button {
                    paceFilter = pace
                } label: {
                    Label(pace.rawValue, systemImage: pace.icon)
                }
            }
        } label: {
            HStack(spacing: 6) {
                Image(systemName: paceFilter.icon)
                    .font(.caption)
                    .contentTransition(.identity)
                Text(paceFilter.rawValue)
                    .font(.subheadline)
                    .contentTransition(.identity)
                Image(systemName: "chevron.down")
                    .font(.caption2)
            }
            .foregroundStyle(paceFilter == .all ? Theme.textPrimary(colorScheme) : Theme.warmOrange)
            .padding(.horizontal, 12)
            .padding(.vertical, 8)
            .background(paceFilter == .all ? Theme.cardBackground(colorScheme) : Theme.warmOrange.opacity(0.15))
            .clipShape(Capsule())
            .overlay(
                Capsule()
                    .strokeBorder(paceFilter == .all ? Theme.textMuted(colorScheme).opacity(0.2) : Theme.warmOrange.opacity(0.3), lineWidth: 1)
            )
        }
    }

    private var citiesPicker: some View {
        VStack(alignment: .leading, spacing: Theme.Spacing.xs) {
            Label("Max Cities", systemImage: "mappin.circle")
                .font(.subheadline)
                .foregroundStyle(Theme.textSecondary(colorScheme))

            ScrollView(.horizontal, showsIndicators: false) {
                HStack(spacing: 8) {
                    ForEach(CitiesFilter.allCases) { filter in
                        Button {
                            withAnimation(.easeInOut(duration: 0.2)) {
                                citiesFilter = filter
                            }
                        } label: {
                            Text(filter.displayName)
                                .font(.system(size: 13, weight: citiesFilter == filter ? .semibold : .medium))
                                .foregroundStyle(citiesFilter == filter ? .white : Theme.textPrimary(colorScheme))
                                .padding(.horizontal, 12)
                                .padding(.vertical, 6)
                                .background(citiesFilter == filter ? Theme.warmOrange : Theme.cardBackground(colorScheme))
                                .clipShape(Capsule())
                                .overlay(
                                    Capsule()
                                        .strokeBorder(citiesFilter == filter ? Color.clear : Theme.textMuted(colorScheme).opacity(0.2), lineWidth: 1)
                                )
                        }
                        .buttonStyle(.plain)
                    }
                }
            }
        }
    }

    private var emptyFilterState: some View {
        VStack(spacing: Theme.Spacing.md) {
            Image(systemName: "line.3.horizontal.decrease.circle")
                .font(.system(size: 48))
                .foregroundStyle(Theme.textMuted(colorScheme))

            Text("No routes match your filters")
                .font(.body)
                .foregroundStyle(Theme.textSecondary(colorScheme))

            Button {
                withAnimation {
                    citiesFilter = .noLimit
                    paceFilter = .all
                }
            } label: {
                Text("Reset Filters")
                    .font(.subheadline)
                    .foregroundStyle(Theme.warmOrange)
            }
        }
        .frame(maxWidth: .infinity)
        .padding(.vertical, Theme.Spacing.xxl)
    }
}

// MARK: - Trip Option Card

struct TripOptionCard: View {
    let option: ItineraryOption
    let games: [String: RichGame]
    let onSelect: () -> Void
    @Environment(\.colorScheme) private var colorScheme

    @State private var aiDescription: String?
    @State private var isLoadingDescription = false

    private var uniqueCities: [String] {
        option.stops.map { $0.city }.removingDuplicates()
    }

    private var totalGames: Int {
        option.stops.flatMap { $0.games }.count
    }

    private var uniqueSports: [Sport] {
        let gameIds = option.stops.flatMap { $0.games }
        let sports = gameIds.compactMap { games[$0]?.game.sport }
        return Array(Set(sports)).sorted { $0.rawValue < $1.rawValue }
    }

    private var gamesPerSport: [(sport: Sport, count: Int)] {
        let gameIds = option.stops.flatMap { $0.games }
        var countsBySport: [Sport: Int] = [:]
        for gameId in gameIds {
            if let sport = games[gameId]?.game.sport {
                countsBySport[sport, default: 0] += 1
            }
        }
        return countsBySport.sorted { $0.key.rawValue < $1.key.rawValue }
            .map { (sport: $0.key, count: $0.value) }
    }

    var body: some View {
        Button(action: onSelect) {
            HStack(spacing: Theme.Spacing.md) {
                // Route info
                VStack(alignment: .leading, spacing: 6) {
                    // Vertical route display
                    VStack(alignment: .leading, spacing: 0) {
                        Text(uniqueCities.first ?? "")
                            .font(.subheadline)
                            .foregroundStyle(Theme.textPrimary(colorScheme))

                        VStack(spacing: 0) {
                            Text("|")
                                .font(.caption2)
                            Image(systemName: "chevron.down")
                                .font(.caption2)
                        }
                        .foregroundStyle(Theme.warmOrange)

                        Text(uniqueCities.last ?? "")
                            .font(.subheadline)
                            .foregroundStyle(Theme.textPrimary(colorScheme))
                    }

                    // Top stats row: cities and miles
                    HStack(spacing: 12) {
                        Label("\(uniqueCities.count) cities", systemImage: "mappin")
                        if option.totalDistanceMiles > 0 {
                            Label("\(Int(option.totalDistanceMiles)) mi", systemImage: "car")
                        }
                    }
                    .font(.caption)
                    .foregroundStyle(Theme.textSecondary(colorScheme))

                    // Bottom row: sports with game counts
                    HStack(spacing: 6) {
                        ForEach(gamesPerSport, id: \.sport) { item in
                            HStack(spacing: 3) {
                                Image(systemName: item.sport.iconName)
                                    .font(.caption2)
                                Text("\(item.sport.rawValue.uppercased()) \(item.count)")
                                    .font(.caption2)
                            }
                            .padding(.horizontal, 6)
                            .padding(.vertical, 3)
                            .background(item.sport.themeColor.opacity(0.15))
                            .foregroundStyle(item.sport.themeColor)
                            .clipShape(Capsule())
                        }
                    }

                    // AI-generated description (after stats)
                    if let description = aiDescription {
                        Text(description)
                            .font(.system(size: 13, weight: .regular))
                            .foregroundStyle(Theme.textMuted(colorScheme))
                            .fixedSize(horizontal: false, vertical: true)
                            .transition(.opacity)
                    } else if isLoadingDescription {
                        HStack(spacing: 4) {
                            LoadingSpinner(size: .small)
                            Text("Generating...")
                                .font(.caption2)
                                .foregroundStyle(Theme.textMuted(colorScheme))
                        }
                    }
                }

                Spacer()

                // Right: Chevron
                Image(systemName: "chevron.right")
                    .font(.system(size: 14, weight: .semibold))
                    .foregroundStyle(Theme.textMuted(colorScheme))
            }
            .padding(Theme.Spacing.md)
            .background(Theme.cardBackground(colorScheme))
            .clipShape(RoundedRectangle(cornerRadius: Theme.CornerRadius.medium))
            .overlay {
                RoundedRectangle(cornerRadius: Theme.CornerRadius.medium)
                    .stroke(Theme.surfaceGlow(colorScheme), lineWidth: 1)
            }
        }
        .buttonStyle(.plain)
        .task(id: option.id) {
            // Reset state when option changes
            aiDescription = nil
            isLoadingDescription = false
            await generateDescription()
        }
    }

    private func generateDescription() async {
        guard RouteDescriptionGenerator.shared.isAvailable else { return }

        isLoadingDescription = true

        // Build input from THIS specific option
        let input = RouteDescriptionInput(from: option, games: games)

        if let description = await RouteDescriptionGenerator.shared.generateDescription(for: input) {
            withAnimation(.easeInOut(duration: 0.3)) {
                aiDescription = description
            }
        }
        isLoadingDescription = false
    }
}

// MARK: - Array Extension for Removing Duplicates

extension Array where Element: Hashable {
    func removingDuplicates() -> [Element] {
        var seen = Set<Element>()
        return filter { seen.insert($0).inserted }
    }
}
