//
//  TripCreationView.swift
//  SportsTime
//

import SwiftUI

struct TripCreationView: View {
    @Environment(\.dismiss) private var dismiss
    @Environment(\.colorScheme) private var colorScheme

    @Bindable var viewModel: TripCreationViewModel
    let initialSport: Sport?

    init(viewModel: TripCreationViewModel, initialSport: Sport? = nil) {
        self.viewModel = viewModel
        self.initialSport = initialSport
    }
    @State private var showGamePicker = false
    @State private var showCityInput = false
    @State private var cityInputType: CityInputType = .mustStop
    @State private var showLocationBanner = true
    @State private var showTripDetail = false
    @State private var showTripOptions = false
    @State private var completedTrip: Trip?
    @State private var tripOptions: [ItineraryOption] = []

    // Location search state
    @State private var startLocationSuggestions: [LocationSearchResult] = []
    @State private var endLocationSuggestions: [LocationSearchResult] = []
    @State private var startSearchTask: Task<Void, Never>?
    @State private var endSearchTask: Task<Void, Never>?
    @State private var isSearchingStart = false
    @State private var isSearchingEnd = false

    private let locationService = LocationService.shared

    enum CityInputType {
        case mustStop
        case preferred
    }

    var body: some View {
        NavigationStack {
            ScrollView {
                VStack(spacing: Theme.Spacing.lg) {
                    // Hero header
                    heroHeader

                    // Planning Mode Selector
                    planningModeSection

                    // Location Permission Banner (only for locations mode)
                    if viewModel.planningMode == .locations && showLocationBanner {
                        LocationPermissionBanner(isPresented: $showLocationBanner)
                    }

                    // Mode-specific sections
                    switch viewModel.planningMode {
                    case .dateRange:
                        // Sports + Dates
                        sportsSection
                        datesSection

                    case .gameFirst:
                        // Sports + Game Picker
                        sportsSection
                        gameBrowserSection

                    case .locations:
                        // Locations + Sports + optional games
                        locationSection
                        sportsSection
                        datesSection
                        gamesSection
                    }

                    // Common sections
                    travelSection
                    optionalSection

                    // Validation message
                    if let message = viewModel.formValidationMessage {
                        validationBanner(message: message)
                    }

                    // Plan button
                    planButton
                }
                .padding(Theme.Spacing.md)
            }
            .themedBackground()
                        .toolbar {
                ToolbarItem(placement: .cancellationAction) {
                    Button("Cancel") {
                        dismiss()
                    }
                }
            }
            .overlay {
                if case .planning = viewModel.viewState {
                    planningOverlay
                }
            }
            .sheet(isPresented: $showGamePicker) {
                GamePickerSheet(
                    games: viewModel.availableGames,
                    selectedIds: $viewModel.mustSeeGameIds
                )
            }
            .sheet(isPresented: $showCityInput) {
                LocationSearchSheet(inputType: cityInputType) { location in
                    switch cityInputType {
                    case .mustStop:
                        viewModel.addMustStopLocation(location)
                    case .preferred:
                        viewModel.addPreferredCity(location.name)
                    }
                }
            }
            .alert("Error", isPresented: Binding(
                get: { viewModel.viewState.isError },
                set: { if !$0 { viewModel.viewState = .editing } }
            )) {
                Button("OK") {
                    viewModel.viewState = .editing
                }
            } message: {
                if case .error(let message) = viewModel.viewState {
                    Text(message)
                }
            }
            .navigationDestination(isPresented: $showTripOptions) {
                TripOptionsView(
                    options: tripOptions,
                    games: buildGamesDictionary(),
                    preferences: viewModel.currentPreferences,
                    convertToTrip: { option in
                        viewModel.convertOptionToTrip(option)
                    }
                )
            }
            .navigationDestination(isPresented: $showTripDetail) {
                if let trip = completedTrip {
                    TripDetailView(trip: trip, games: buildGamesDictionary())
                }
            }
            .onChange(of: viewModel.viewState) { _, newState in
                switch newState {
                case .selectingOption(let options):
                    tripOptions = options
                    showTripOptions = true
                case .completed(let trip):
                    completedTrip = trip
                    showTripDetail = true
                default:
                    break
                }
            }
            .onChange(of: showTripOptions) { _, isShowing in
                if !isShowing {
                    // User navigated back from options to editing
                    viewModel.viewState = .editing
                    tripOptions = []
                }
            }
            .onChange(of: showTripDetail) { _, isShowing in
                if !isShowing {
                    // User navigated back from single-option detail to editing
                    completedTrip = nil
                    viewModel.viewState = .editing
                }
            }
            .task {
                await viewModel.loadScheduleData()
            }
            .onAppear {
                if let sport = initialSport {
                    viewModel.selectedSports = [sport]
                }
            }
        }
    }

    // MARK: - Hero Header

    private var heroHeader: some View {
        VStack(spacing: Theme.Spacing.sm) {
            Image(systemName: "map.fill")
                .font(.system(size: 40))
                .foregroundStyle(Theme.warmOrange)

            Text("Plan Your Adventure")
                .font(.system(size: Theme.FontSize.sectionTitle, weight: .bold, design: .rounded))
                .foregroundStyle(Theme.textPrimary(colorScheme))

            Text("Select your games, set your route, and hit the road")
                .font(.system(size: Theme.FontSize.caption))
                .foregroundStyle(Theme.textSecondary(colorScheme))
                .multilineTextAlignment(.center)
        }
        .padding(.vertical, Theme.Spacing.md)
    }

    // MARK: - Sections

    private var planningModeSection: some View {
        ThemedSection(title: "How do you want to plan?") {
            Picker("Planning Mode", selection: $viewModel.planningMode) {
                ForEach(PlanningMode.allCases) { mode in
                    Text(mode.displayName).tag(mode)
                }
            }
            .pickerStyle(.segmented)

            Text(viewModel.planningMode.description)
                .font(.system(size: Theme.FontSize.caption))
                .foregroundStyle(Theme.textSecondary(colorScheme))
                .padding(.top, Theme.Spacing.xs)
        }
    }

    private var locationSection: some View {
        ThemedSection(title: "Locations") {
            // Start Location with suggestions
            VStack(alignment: .leading, spacing: 0) {
                ThemedTextField(
                    label: "Start Location",
                    placeholder: "Where are you starting from?",
                    text: $viewModel.startLocationText,
                    icon: "location.circle.fill"
                )
                .onChange(of: viewModel.startLocationText) { _, newValue in
                    searchLocation(query: newValue, isStart: true)
                }

                // Suggestions for start location
                if !startLocationSuggestions.isEmpty {
                    locationSuggestionsList(
                        suggestions: startLocationSuggestions,
                        isLoading: isSearchingStart
                    ) { result in
                        viewModel.startLocationText = result.name
                        viewModel.startLocation = result.toLocationInput()
                        startLocationSuggestions = []
                    }
                } else if isSearchingStart {
                    HStack {
                        ThemedSpinnerCompact(size: 14)
                        Text("Searching...")
                            .font(.system(size: Theme.FontSize.caption))
                            .foregroundStyle(Theme.textMuted(colorScheme))
                    }
                    .padding(.top, Theme.Spacing.xs)
                }
            }

            // End Location with suggestions
            VStack(alignment: .leading, spacing: 0) {
                ThemedTextField(
                    label: "End Location",
                    placeholder: "Where do you want to end up?",
                    text: $viewModel.endLocationText,
                    icon: "mappin.circle.fill"
                )
                .onChange(of: viewModel.endLocationText) { _, newValue in
                    searchLocation(query: newValue, isStart: false)
                }

                // Suggestions for end location
                if !endLocationSuggestions.isEmpty {
                    locationSuggestionsList(
                        suggestions: endLocationSuggestions,
                        isLoading: isSearchingEnd
                    ) { result in
                        viewModel.endLocationText = result.name
                        viewModel.endLocation = result.toLocationInput()
                        endLocationSuggestions = []
                    }
                } else if isSearchingEnd {
                    HStack {
                        ThemedSpinnerCompact(size: 14)
                        Text("Searching...")
                            .font(.system(size: Theme.FontSize.caption))
                            .foregroundStyle(Theme.textMuted(colorScheme))
                    }
                    .padding(.top, Theme.Spacing.xs)
                }
            }
        }
    }

    private func searchLocation(query: String, isStart: Bool) {
        // Cancel previous search
        if isStart {
            startSearchTask?.cancel()
        } else {
            endSearchTask?.cancel()
        }

        guard query.count >= 2 else {
            if isStart {
                startLocationSuggestions = []
                isSearchingStart = false
            } else {
                endLocationSuggestions = []
                isSearchingEnd = false
            }
            return
        }

        let task = Task {
            // Debounce
            try? await Task.sleep(for: .milliseconds(300))
            guard !Task.isCancelled else { return }

            if isStart {
                isSearchingStart = true
            } else {
                isSearchingEnd = true
            }

            do {
                let results = try await locationService.searchLocations(query)
                guard !Task.isCancelled else { return }

                if isStart {
                    startLocationSuggestions = Array(results.prefix(5))
                    isSearchingStart = false
                } else {
                    endLocationSuggestions = Array(results.prefix(5))
                    isSearchingEnd = false
                }
            } catch {
                if isStart {
                    startLocationSuggestions = []
                    isSearchingStart = false
                } else {
                    endLocationSuggestions = []
                    isSearchingEnd = false
                }
            }
        }

        if isStart {
            startSearchTask = task
        } else {
            endSearchTask = task
        }
    }

    @ViewBuilder
    private func locationSuggestionsList(
        suggestions: [LocationSearchResult],
        isLoading: Bool,
        onSelect: @escaping (LocationSearchResult) -> Void
    ) -> some View {
        VStack(alignment: .leading, spacing: 0) {
            ForEach(suggestions) { result in
                Button {
                    onSelect(result)
                } label: {
                    HStack(spacing: Theme.Spacing.sm) {
                        Image(systemName: "mappin.circle.fill")
                            .foregroundStyle(Theme.warmOrange)
                            .font(.system(size: 14))

                        VStack(alignment: .leading, spacing: 2) {
                            Text(result.name)
                                .font(.system(size: Theme.FontSize.caption, weight: .medium))
                                .foregroundStyle(Theme.textPrimary(colorScheme))

                            if !result.address.isEmpty {
                                Text(result.address)
                                    .font(.system(size: Theme.FontSize.micro))
                                    .foregroundStyle(Theme.textMuted(colorScheme))
                            }
                        }

                        Spacer()
                    }
                    .padding(.vertical, Theme.Spacing.sm)
                    .padding(.horizontal, Theme.Spacing.xs)
                }
                .buttonStyle(.plain)

                if result.id != suggestions.last?.id {
                    Divider()
                        .overlay(Theme.surfaceGlow(colorScheme))
                }
            }
        }
        .padding(.top, Theme.Spacing.xs)
        .background(Theme.cardBackgroundElevated(colorScheme))
        .clipShape(RoundedRectangle(cornerRadius: Theme.CornerRadius.small))
    }

    private var gameBrowserSection: some View {
        ThemedSection(title: "Select Games") {
            if viewModel.isLoadingGames || viewModel.availableGames.isEmpty {
                HStack(spacing: Theme.Spacing.sm) {
                    ThemedSpinnerCompact(size: 20)
                    Text("Loading games...")
                        .font(.system(size: Theme.FontSize.body))
                        .foregroundStyle(Theme.textSecondary(colorScheme))
                }
                .frame(maxWidth: .infinity, alignment: .center)
                .padding(.vertical, Theme.Spacing.md)
                .task(id: viewModel.selectedSports) {
                    // Always load 90-day browsing window for gameFirst mode
                    await viewModel.loadGamesForBrowsing()
                }
            } else {
                Button {
                    showGamePicker = true
                } label: {
                    HStack(spacing: Theme.Spacing.md) {
                        ZStack {
                            Circle()
                                .fill(Theme.warmOrange.opacity(0.15))
                                .frame(width: 44, height: 44)
                            Image(systemName: "sportscourt.fill")
                                .foregroundStyle(Theme.warmOrange)
                        }

                        VStack(alignment: .leading, spacing: 4) {
                            Text("Browse Teams & Games")
                                .font(.system(size: Theme.FontSize.body, weight: .semibold))
                                .foregroundStyle(Theme.textPrimary(colorScheme))
                            Text("\(viewModel.availableGames.count) games available")
                                .font(.system(size: Theme.FontSize.caption))
                                .foregroundStyle(Theme.textSecondary(colorScheme))
                        }

                        Spacer()

                        Image(systemName: "chevron.right")
                            .foregroundStyle(Theme.textMuted(colorScheme))
                    }
                    .padding(Theme.Spacing.md)
                    .background(Theme.cardBackgroundElevated(colorScheme))
                    .clipShape(RoundedRectangle(cornerRadius: Theme.CornerRadius.medium))
                }
                .buttonStyle(.plain)
            }

            // Show selected games summary
            if !viewModel.mustSeeGameIds.isEmpty {
                VStack(alignment: .leading, spacing: Theme.Spacing.sm) {
                    HStack {
                        Image(systemName: "checkmark.circle.fill")
                            .foregroundStyle(.green)
                        Text("\(viewModel.mustSeeGameIds.count) game(s) selected")
                            .font(.system(size: Theme.FontSize.body, weight: .medium))
                            .foregroundStyle(Theme.textPrimary(colorScheme))

                        Spacer()

                        Button {
                            viewModel.deselectAllGames()
                        } label: {
                            Text("Deselect All")
                                .font(.system(size: Theme.FontSize.caption, weight: .medium))
                                .foregroundStyle(.red)
                        }
                    }

                    // Show selected games preview
                    ForEach(viewModel.selectedGames.prefix(3)) { game in
                        HStack(spacing: Theme.Spacing.sm) {
                            SportColorBar(sport: game.game.sport)
                            Text("\(game.awayTeam.abbreviation) @ \(game.homeTeam.abbreviation)")
                                .font(.system(size: Theme.FontSize.caption))
                                .foregroundStyle(Theme.textPrimary(colorScheme))
                            Spacer()
                            Text(game.game.formattedDate)
                                .font(.system(size: Theme.FontSize.micro))
                                .foregroundStyle(Theme.textMuted(colorScheme))
                        }
                    }

                    if viewModel.selectedGames.count > 3 {
                        Text("+ \(viewModel.selectedGames.count - 3) more")
                            .font(.system(size: Theme.FontSize.caption))
                            .foregroundStyle(Theme.textSecondary(colorScheme))
                    }
                }
                .padding(Theme.Spacing.md)
                .background(Theme.cardBackgroundElevated(colorScheme))
                .clipShape(RoundedRectangle(cornerRadius: Theme.CornerRadius.medium))
            }
        }
    }

    private var sportsSection: some View {
        let sports = Sport.supported
        let rows = sports.chunked(into: 4)

        return ThemedSection(title: "Sports") {
            VStack(spacing: Theme.Spacing.sm) {
                ForEach(Array(rows.enumerated()), id: \.offset) { _, row in
                    HStack(spacing: Theme.Spacing.sm) {
                        ForEach(row) { sport in
                            SportSelectionChip(
                                sport: sport,
                                isSelected: viewModel.selectedSports.contains(sport),
                                onTap: {
                                    if viewModel.selectedSports.contains(sport) {
                                        viewModel.selectedSports.remove(sport)
                                    } else {
                                        viewModel.selectedSports.insert(sport)
                                    }
                                }
                            )
                        }
                        // Fill remaining space if row has fewer than 4 items
                        if row.count < 4 {
                            ForEach(0..<(4 - row.count), id: \.self) { _ in
                                Color.clear.frame(maxWidth: .infinity)
                            }
                        }
                    }
                }
            }
            .padding(.vertical, Theme.Spacing.xs)
        }
    }

    private var datesSection: some View {
        ThemedSection(title: "Dates") {
            DateRangePicker(
                startDate: $viewModel.startDate,
                endDate: $viewModel.endDate
            )
        }
    }

    private var gamesSection: some View {
        ThemedSection(title: "Must-See Games") {
            Button {
                showGamePicker = true
            } label: {
                HStack(spacing: Theme.Spacing.md) {
                    ZStack {
                        Circle()
                            .fill(Theme.warmOrange.opacity(0.15))
                            .frame(width: 40, height: 40)
                        Image(systemName: "star.fill")
                            .foregroundStyle(Theme.warmOrange)
                    }

                    Text("Select Games")
                        .font(.system(size: Theme.FontSize.body, weight: .medium))
                        .foregroundStyle(Theme.textPrimary(colorScheme))

                    Spacer()

                    Text("\(viewModel.selectedGamesCount) selected")
                        .font(.system(size: Theme.FontSize.caption))
                        .foregroundStyle(Theme.textSecondary(colorScheme))

                    Image(systemName: "chevron.right")
                        .foregroundStyle(Theme.textMuted(colorScheme))
                }
                .padding(Theme.Spacing.md)
                .background(Theme.cardBackgroundElevated(colorScheme))
                .clipShape(RoundedRectangle(cornerRadius: Theme.CornerRadius.medium))
            }
            .buttonStyle(.plain)
        }
    }

    private var travelSection: some View {
        ThemedSection(title: "Travel") {
            VStack(spacing: Theme.Spacing.md) {
                // Region selector
                VStack(alignment: .leading, spacing: Theme.Spacing.xs) {
                    Text("Regions")
                        .font(.system(size: Theme.FontSize.caption))
                        .foregroundStyle(Theme.textSecondary(colorScheme))

                    RegionMapSelector(
                        selectedRegions: $viewModel.selectedRegions,
                        onToggle: { region in
                            viewModel.toggleRegion(region)
                        }
                    )

                    if viewModel.selectedRegions.isEmpty {
                        Text("Select at least one region")
                            .font(.system(size: Theme.FontSize.micro))
                            .foregroundStyle(Theme.warmOrange)
                            .padding(.top, Theme.Spacing.xxs)
                    } else {
                        Text("Games will be found in selected regions")
                            .font(.system(size: Theme.FontSize.micro))
                            .foregroundStyle(Theme.textMuted(colorScheme))
                            .padding(.top, Theme.Spacing.xxs)
                    }
                }

                // Route preference
                VStack(alignment: .leading, spacing: Theme.Spacing.xs) {
                    Text("Route Preference")
                        .font(.system(size: Theme.FontSize.caption))
                        .foregroundStyle(Theme.textSecondary(colorScheme))

                    Picker("Route Preference", selection: $viewModel.routePreference) {
                        ForEach(RoutePreference.allCases) { pref in
                            Text(pref.displayName).tag(pref)
                        }
                    }
                    .pickerStyle(.segmented)
                }

                // Allow repeat cities
                ThemedToggle(
                    label: "Allow Repeat Cities",
                    isOn: $viewModel.allowRepeatCities,
                    icon: "arrow.triangle.2.circlepath"
                )

                if !viewModel.allowRepeatCities {
                    Text("Each city will only be visited on one day")
                        .font(.system(size: Theme.FontSize.micro))
                        .foregroundStyle(Theme.textMuted(colorScheme))
                        .padding(.leading, 32)
                }
            }
            .animation(.easeInOut(duration: 0.2), value: viewModel.selectedRegions)
        }
    }

    private var optionalSection: some View {
        ThemedSection(title: "More Options") {
            VStack(spacing: Theme.Spacing.md) {
                // Must-Stop Locations
                VStack(alignment: .leading, spacing: Theme.Spacing.sm) {
                    HStack {
                        Image(systemName: "mappin.circle")
                            .foregroundStyle(Theme.warmOrange)
                        Text("Must-Stop Locations")
                            .font(.system(size: Theme.FontSize.body, weight: .medium))
                            .foregroundStyle(Theme.textPrimary(colorScheme))
                        Spacer()
                        Text("\(viewModel.mustStopLocations.count)")
                            .font(.system(size: Theme.FontSize.caption))
                            .foregroundStyle(Theme.textSecondary(colorScheme))
                    }

                    ForEach(viewModel.mustStopLocations, id: \.name) { location in
                        HStack {
                            VStack(alignment: .leading, spacing: 2) {
                                Text(location.name)
                                    .font(.system(size: Theme.FontSize.caption))
                                    .foregroundStyle(Theme.textPrimary(colorScheme))
                                if let address = location.address, !address.isEmpty {
                                    Text(address)
                                        .font(.system(size: Theme.FontSize.micro))
                                        .foregroundStyle(Theme.textMuted(colorScheme))
                                }
                            }
                            Spacer()
                            Button {
                                viewModel.removeMustStopLocation(location)
                            } label: {
                                Image(systemName: "xmark.circle.fill")
                                    .foregroundStyle(Theme.textMuted(colorScheme))
                            }
                        }
                        .padding(Theme.Spacing.sm)
                        .background(Theme.cardBackgroundElevated(colorScheme))
                        .clipShape(RoundedRectangle(cornerRadius: Theme.CornerRadius.small))
                    }

                    Button {
                        cityInputType = .mustStop
                        showCityInput = true
                    } label: {
                        HStack {
                            Image(systemName: "plus.circle.fill")
                            Text("Add Location")
                        }
                        .font(.system(size: Theme.FontSize.caption, weight: .medium))
                        .foregroundStyle(Theme.warmOrange)
                    }
                }

                Divider()
                    .overlay(Theme.surfaceGlow(colorScheme))

                // EV Charging (feature flagged)
                if FeatureFlags.enableEVCharging {
                    ThemedToggle(
                        label: "EV Charging Needed",
                        isOn: $viewModel.needsEVCharging,
                        icon: "bolt.car"
                    )
                }

                // Drivers
                ThemedStepper(
                    label: "Number of Drivers",
                    value: viewModel.numberOfDrivers,
                    range: 1...4,
                    onIncrement: { viewModel.numberOfDrivers += 1 },
                    onDecrement: { viewModel.numberOfDrivers -= 1 }
                )
            }
        }
    }

    private var planningOverlay: some View {
        ZStack {
            Color.black.opacity(0.5)
                .ignoresSafeArea()

            PlanningProgressView()
                .padding(40)
                .background(.ultraThinMaterial, in: RoundedRectangle(cornerRadius: 24))
        }
    }

    private var planButton: some View {
        Button {
            Task {
                await viewModel.planTrip()
            }
        } label: {
            HStack(spacing: Theme.Spacing.sm) {
                Image(systemName: "map.fill")
                Text("Plan My Trip")
                    .fontWeight(.semibold)
            }
            .frame(maxWidth: .infinity)
            .padding(Theme.Spacing.md)
            .background(viewModel.isFormValid ? Theme.warmOrange : Theme.textMuted(colorScheme))
            .foregroundStyle(.white)
            .clipShape(RoundedRectangle(cornerRadius: Theme.CornerRadius.medium))
        }
        .disabled(!viewModel.isFormValid)
        .padding(.top, Theme.Spacing.md)
        .glowEffect(color: viewModel.isFormValid ? Theme.warmOrange : .clear, radius: 12)
    }

    private func validationBanner(message: String) -> some View {
        HStack(spacing: Theme.Spacing.sm) {
            Image(systemName: "exclamationmark.triangle.fill")
                .foregroundStyle(.orange)
            Text(message)
                .font(.system(size: Theme.FontSize.caption))
                .foregroundStyle(Theme.textPrimary(colorScheme))
        }
        .padding(Theme.Spacing.md)
        .frame(maxWidth: .infinity, alignment: .leading)
        .background(Color.orange.opacity(0.15))
        .clipShape(RoundedRectangle(cornerRadius: Theme.CornerRadius.medium))
    }

    // MARK: - Helpers

    private func binding(for sport: Sport) -> Binding<Bool> {
        Binding(
            get: { viewModel.selectedSports.contains(sport) },
            set: { isSelected in
                if isSelected {
                    viewModel.selectedSports.insert(sport)
                } else {
                    viewModel.selectedSports.remove(sport)
                }
            }
        )
    }

    private func buildGamesDictionary() -> [UUID: RichGame] {
        viewModel.availableGames.reduce(into: [:]) { $0[$1.id] = $1 }
    }
}

// MARK: - View State Extensions

extension TripCreationViewModel.ViewState {
    var isError: Bool {
        if case .error = self { return true }
        return false
    }

    var isCompleted: Bool {
        if case .completed = self { return true }
        return false
    }
}

// MARK: - Game Picker Sheet (Calendar view: Sport → Team → Date)

struct GamePickerSheet: View {
    let games: [RichGame]
    @Binding var selectedIds: Set<UUID>
    @Environment(\.dismiss) private var dismiss
    @Environment(\.colorScheme) private var colorScheme

    @State private var expandedSports: Set<Sport> = []
    @State private var expandedTeams: Set<UUID> = []

    // Group games by Sport → Team (home team only to avoid duplicates)
    private var gamesBySport: [Sport: [TeamWithGames]] {
        var result: [Sport: [UUID: TeamWithGames]] = [:]

        for game in games {
            let sport = game.game.sport
            let team = game.homeTeam

            if result[sport] == nil {
                result[sport] = [:]
            }

            if var teamData = result[sport]?[team.id] {
                teamData.games.append(game)
                result[sport]?[team.id] = teamData
            } else {
                result[sport]?[team.id] = TeamWithGames(
                    team: team,
                    sport: sport,
                    games: [game]
                )
            }
        }

        // Convert to sorted arrays
        var sortedResult: [Sport: [TeamWithGames]] = [:]
        for (sport, teamsDict) in result {
            sortedResult[sport] = teamsDict.values.sorted { $0.team.name < $1.team.name }
        }
        return sortedResult
    }

    private var sortedSports: [Sport] {
        Sport.supported.filter { gamesBySport[$0] != nil }
    }

    private var selectedGamesCount: Int {
        selectedIds.count
    }

    private func selectedCountForSport(_ sport: Sport) -> Int {
        guard let teams = gamesBySport[sport] else { return 0 }
        return teams.flatMap { $0.games }.filter { selectedIds.contains($0.id) }.count
    }

    private func selectedCountForTeam(_ teamData: TeamWithGames) -> Int {
        teamData.games.filter { selectedIds.contains($0.id) }.count
    }

    var body: some View {
        NavigationStack {
            ScrollView {
                LazyVStack(spacing: 0) {
                    // Selected games summary
                    if !selectedIds.isEmpty {
                        HStack {
                            Image(systemName: "checkmark.circle.fill")
                                .foregroundStyle(.green)
                            Text("\(selectedGamesCount) game(s) selected")
                                .font(.system(size: 15, weight: .semibold))
                            Spacer()
                        }
                        .padding(Theme.Spacing.md)
                        .background(Theme.cardBackground(colorScheme))
                    }

                    // Sport sections
                    ForEach(sortedSports) { sport in
                        SportSection(
                            sport: sport,
                            teams: gamesBySport[sport] ?? [],
                            selectedIds: $selectedIds,
                            expandedSports: $expandedSports,
                            expandedTeams: $expandedTeams,
                            selectedCount: selectedCountForSport(sport)
                        )
                    }
                }
            }
            .themedBackground()
            .navigationTitle("Select Games")
            .navigationBarTitleDisplayMode(.inline)
            .toolbar {
                ToolbarItem(placement: .cancellationAction) {
                    if !selectedIds.isEmpty {
                        Button("Reset") {
                            selectedIds.removeAll()
                        }
                        .foregroundStyle(.red)
                    }
                }
                ToolbarItem(placement: .confirmationAction) {
                    Button("Done") {
                        dismiss()
                    }
                    .fontWeight(.semibold)
                }
            }
        }
    }
}

// MARK: - Sport Section

struct SportSection: View {
    let sport: Sport
    let teams: [TeamWithGames]
    @Binding var selectedIds: Set<UUID>
    @Binding var expandedSports: Set<Sport>
    @Binding var expandedTeams: Set<UUID>
    let selectedCount: Int

    @Environment(\.colorScheme) private var colorScheme

    private var isExpanded: Bool {
        expandedSports.contains(sport)
    }

    var body: some View {
        VStack(spacing: 0) {
            // Sport header
            Button {
                withAnimation(.easeInOut(duration: 0.2)) {
                    if isExpanded {
                        expandedSports.remove(sport)
                    } else {
                        expandedSports.insert(sport)
                    }
                }
            } label: {
                HStack(spacing: Theme.Spacing.sm) {
                    Image(systemName: sport.iconName)
                        .font(.system(size: 20))
                        .foregroundStyle(sport.themeColor)
                        .frame(width: 32)

                    Text(sport.rawValue)
                        .font(.system(size: 17, weight: .bold))
                        .foregroundStyle(Theme.textPrimary(colorScheme))

                    Text("\(teams.flatMap { $0.games }.count) games")
                        .font(.system(size: 13))
                        .foregroundStyle(Theme.textMuted(colorScheme))

                    Spacer()

                    if selectedCount > 0 {
                        Text("\(selectedCount)")
                            .font(.system(size: 12, weight: .bold))
                            .foregroundStyle(.white)
                            .padding(.horizontal, 8)
                            .padding(.vertical, 4)
                            .background(sport.themeColor)
                            .clipShape(Capsule())
                    }

                    Image(systemName: "chevron.right")
                        .font(.system(size: 14, weight: .semibold))
                        .foregroundStyle(Theme.textMuted(colorScheme))
                        .rotationEffect(.degrees(isExpanded ? 90 : 0))
                }
                .padding(Theme.Spacing.md)
                .background(Theme.cardBackground(colorScheme))
            }
            .buttonStyle(.plain)

            // Teams list (when expanded)
            if isExpanded {
                VStack(spacing: 0) {
                    ForEach(teams) { teamData in
                        TeamSection(
                            teamData: teamData,
                            selectedIds: $selectedIds,
                            expandedTeams: $expandedTeams
                        )
                    }
                }
                .padding(.leading, Theme.Spacing.lg)
            }

            Divider()
                .overlay(Theme.surfaceGlow(colorScheme))
        }
    }
}

// MARK: - Team Section

struct TeamSection: View {
    let teamData: TeamWithGames
    @Binding var selectedIds: Set<UUID>
    @Binding var expandedTeams: Set<UUID>

    @Environment(\.colorScheme) private var colorScheme

    private var isExpanded: Bool {
        expandedTeams.contains(teamData.id)
    }

    private var selectedCount: Int {
        teamData.games.filter { selectedIds.contains($0.id) }.count
    }

    // Group games by date
    private var gamesByDate: [(date: String, games: [RichGame])] {
        let grouped = Dictionary(grouping: teamData.sortedGames) { game in
            game.game.formattedDate
        }
        return grouped.sorted { $0.value.first!.game.dateTime < $1.value.first!.game.dateTime }
            .map { (date: $0.key, games: $0.value) }
    }

    var body: some View {
        VStack(spacing: 0) {
            // Team header
            Button {
                withAnimation(.easeInOut(duration: 0.2)) {
                    if isExpanded {
                        expandedTeams.remove(teamData.id)
                    } else {
                        expandedTeams.insert(teamData.id)
                    }
                }
            } label: {
                HStack(spacing: Theme.Spacing.sm) {
                    // Team color
                    if let colorHex = teamData.team.primaryColor {
                        Circle()
                            .fill(Color(hex: colorHex))
                            .frame(width: 10, height: 10)
                    }

                    Text("\(teamData.team.city) \(teamData.team.name)")
                        .font(.system(size: 15, weight: .medium))
                        .foregroundStyle(Theme.textPrimary(colorScheme))

                    Text("\(teamData.games.count)")
                        .font(.system(size: 12))
                        .foregroundStyle(Theme.textMuted(colorScheme))

                    Spacer()

                    if selectedCount > 0 {
                        Text("\(selectedCount)")
                            .font(.system(size: 11, weight: .bold))
                            .foregroundStyle(.white)
                            .padding(.horizontal, 6)
                            .padding(.vertical, 3)
                            .background(Theme.warmOrange)
                            .clipShape(Capsule())
                    }

                    Image(systemName: "chevron.right")
                        .font(.system(size: 12, weight: .semibold))
                        .foregroundStyle(Theme.textMuted(colorScheme))
                        .rotationEffect(.degrees(isExpanded ? 90 : 0))
                }
                .padding(.vertical, Theme.Spacing.sm)
                .padding(.horizontal, Theme.Spacing.md)
                .background(Theme.cardBackgroundElevated(colorScheme))
            }
            .buttonStyle(.plain)

            // Games grouped by date (when expanded)
            if isExpanded {
                VStack(spacing: 0) {
                    ForEach(gamesByDate, id: \.date) { dateGroup in
                        VStack(alignment: .leading, spacing: 0) {
                            // Date header
                            Text(dateGroup.date)
                                .font(.system(size: 12, weight: .semibold))
                                .foregroundStyle(Theme.warmOrange)
                                .padding(.horizontal, Theme.Spacing.md)
                                .padding(.top, Theme.Spacing.sm)
                                .padding(.bottom, Theme.Spacing.xs)

                            // Games on this date
                            ForEach(dateGroup.games) { game in
                                GameCalendarRow(
                                    game: game,
                                    isSelected: selectedIds.contains(game.id),
                                    onTap: {
                                        if selectedIds.contains(game.id) {
                                            selectedIds.remove(game.id)
                                        } else {
                                            selectedIds.insert(game.id)
                                        }
                                    }
                                )
                            }
                        }
                    }
                }
                .padding(.leading, Theme.Spacing.md)
                .background(Theme.cardBackgroundElevated(colorScheme).opacity(0.5))
            }
        }
    }
}

// MARK: - Game Calendar Row

struct GameCalendarRow: View {
    let game: RichGame
    let isSelected: Bool
    let onTap: () -> Void

    @Environment(\.colorScheme) private var colorScheme

    var body: some View {
        Button(action: onTap) {
            HStack(spacing: Theme.Spacing.sm) {
                // Selection indicator
                Image(systemName: isSelected ? "checkmark.circle.fill" : "circle")
                    .font(.system(size: 22))
                    .foregroundStyle(isSelected ? Theme.warmOrange : Theme.textMuted(colorScheme))

                VStack(alignment: .leading, spacing: 2) {
                    Text("vs \(game.awayTeam.name)")
                        .font(.system(size: 14, weight: .medium))
                        .foregroundStyle(Theme.textPrimary(colorScheme))

                    HStack(spacing: Theme.Spacing.xs) {
                        Text(game.game.gameTime)
                            .font(.system(size: 12))
                            .foregroundStyle(Theme.textSecondary(colorScheme))

                        Text("•")
                            .foregroundStyle(Theme.textMuted(colorScheme))

                        Text(game.stadium.name)
                            .font(.system(size: 12))
                            .foregroundStyle(Theme.textMuted(colorScheme))
                            .lineLimit(1)
                    }
                }

                Spacer()
            }
            .padding(.vertical, Theme.Spacing.sm)
            .padding(.horizontal, Theme.Spacing.md)
            .background(isSelected ? Theme.warmOrange.opacity(0.1) : Color.clear)
        }
        .buttonStyle(.plain)
    }
}

// MARK: - Team With Games Model

struct TeamWithGames: Identifiable {
    let team: Team
    let sport: Sport
    var games: [RichGame]

    var id: UUID { team.id }

    var sortedGames: [RichGame] {
        games.sorted { $0.game.dateTime < $1.game.dateTime }
    }
}

// MARK: - Location Search Sheet

struct LocationSearchSheet: View {
    let inputType: TripCreationView.CityInputType
    let onAdd: (LocationInput) -> Void

    @Environment(\.dismiss) private var dismiss
    @State private var searchText = ""
    @State private var searchResults: [LocationSearchResult] = []
    @State private var isSearching = false
    @State private var searchTask: Task<Void, Never>?

    private let locationService = LocationService.shared

    var body: some View {
        NavigationStack {
            VStack(spacing: 0) {
                // Search field
                HStack {
                    Image(systemName: "magnifyingglass")
                        .foregroundStyle(.secondary)
                    TextField("Search cities, addresses, places...", text: $searchText)
                        .textFieldStyle(.plain)
                        .autocorrectionDisabled()
                    if isSearching {
                        ThemedSpinnerCompact(size: 16)
                    } else if !searchText.isEmpty {
                        Button {
                            searchText = ""
                            searchResults = []
                        } label: {
                            Image(systemName: "xmark.circle.fill")
                                .foregroundStyle(.secondary)
                        }
                    }
                }
                .padding()
                .background(Color(.secondarySystemBackground))
                .clipShape(RoundedRectangle(cornerRadius: 10))
                .padding()

                // Results list
                if searchResults.isEmpty && !searchText.isEmpty && !isSearching {
                    ContentUnavailableView(
                        "No Results",
                        systemImage: "mappin.slash",
                        description: Text("Try a different search term")
                    )
                } else {
                    List(searchResults) { result in
                        Button {
                            onAdd(result.toLocationInput())
                            dismiss()
                        } label: {
                            HStack {
                                Image(systemName: "mappin.circle.fill")
                                    .foregroundStyle(.red)
                                    .font(.title2)
                                VStack(alignment: .leading) {
                                    Text(result.name)
                                        .foregroundStyle(.primary)
                                    if !result.address.isEmpty {
                                        Text(result.address)
                                            .font(.caption)
                                            .foregroundStyle(.secondary)
                                    }
                                }
                                Spacer()
                                Image(systemName: "plus.circle")
                                    .foregroundStyle(.blue)
                            }
                        }
                        .buttonStyle(.plain)
                    }
                    .listStyle(.plain)
                }

                Spacer()
            }
            .navigationTitle(inputType == .mustStop ? "Add Must-Stop" : "Add Location")
            .navigationBarTitleDisplayMode(.inline)
            .toolbar {
                ToolbarItem(placement: .cancellationAction) {
                    Button("Cancel") {
                        dismiss()
                    }
                }
            }
        }
        .presentationDetents([.large])
        .onChange(of: searchText) { _, newValue in
            // Debounce search
            searchTask?.cancel()
            searchTask = Task {
                try? await Task.sleep(for: .milliseconds(300))
                guard !Task.isCancelled else { return }
                await performSearch(query: newValue)
            }
        }
    }

    private func performSearch(query: String) async {
        guard !query.isEmpty else {
            searchResults = []
            return
        }

        isSearching = true
        do {
            searchResults = try await locationService.searchLocations(query)
        } catch {
            searchResults = []
        }
        isSearching = false
    }
}

// MARK: - Trip Options View

// MARK: - Sort Options

enum TripSortOption: String, CaseIterable, Identifiable {
    case recommended = "Recommended"
    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 .mostGames, .leastGames: return "sportscourt"
        case .mostMiles, .leastMiles: return "road.lanes"
        case .bestEfficiency: return "gauge.with.dots.needle.33percent"
        }
    }
}

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"
        }
    }
}

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"
        }
    }
}

struct TripOptionsView: View {
    let options: [ItineraryOption]
    let games: [UUID: 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 .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)
    }

    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(.system(size: 40))
                        .foregroundStyle(Theme.warmOrange)

                    Text("\(filteredAndSortedOptions.count) of \(options.count) Routes")
                        .font(.system(size: Theme.FontSize.sectionTitle, weight: .bold, design: .rounded))
                        .foregroundStyle(Theme.textPrimary(colorScheme))
                }
                .padding(.top, Theme.Spacing.lg)

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

                // Options list
                if filteredAndSortedOptions.isEmpty {
                    emptyFilterState
                        .padding(.top, Theme.Spacing.xl)
                } else {
                    ForEach(filteredAndSortedOptions) { 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, games: games)
            }
        }
        .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(.system(size: 14))
                Text(sortOption.rawValue)
                    .font(.system(size: 14, weight: .medium))
                Image(systemName: "chevron.down")
                    .font(.system(size: 12))
            }
            .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 {
                    withAnimation(.easeInOut(duration: 0.2)) {
                        paceFilter = pace
                    }
                } label: {
                    Label(pace.rawValue, systemImage: pace.icon)
                }
            }
        } label: {
            HStack(spacing: 6) {
                Image(systemName: paceFilter.icon)
                    .font(.system(size: 12))
                Text(paceFilter.rawValue)
                    .font(.system(size: 13, weight: .medium))
                Image(systemName: "chevron.down")
                    .font(.system(size: 10))
            }
            .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(.system(size: 13, weight: .medium))
                .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(.system(size: Theme.FontSize.body, weight: .medium))
                .foregroundStyle(Theme.textSecondary(colorScheme))

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

// MARK: - Trip Option Card

struct TripOptionCard: View {
    let option: ItineraryOption
    let games: [UUID: 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(.system(size: 15, weight: .semibold))
                            .foregroundStyle(Theme.textPrimary(colorScheme))

                        VStack(spacing: 0) {
                            Text("|")
                                .font(.system(size: 10))
                            Image(systemName: "chevron.down")
                                .font(.system(size: 8, weight: .bold))
                        }
                        .foregroundStyle(Theme.warmOrange)

                        Text(uniqueCities.last ?? "")
                            .font(.system(size: 15, weight: .semibold))
                            .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(.system(size: 12))
                    .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(.system(size: 9))
                                Text("\(item.sport.rawValue.uppercased()) \(item.count)")
                                    .font(.system(size: 9, weight: .semibold))
                            }
                            .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) {
                            ThemedSpinnerCompact(size: 12)
                            Text("Generating...")
                                .font(.system(size: 11))
                                .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 }
    }
}

// MARK: - Themed Form Components

struct ThemedSection<Content: View>: View {
    let title: String
    @ViewBuilder let content: () -> Content
    @Environment(\.colorScheme) private var colorScheme

    var body: some View {
        VStack(alignment: .leading, spacing: Theme.Spacing.sm) {
            Text(title)
                .font(.system(size: Theme.FontSize.sectionTitle, weight: .bold, design: .rounded))
                .foregroundStyle(Theme.textPrimary(colorScheme))

            VStack(alignment: .leading, spacing: Theme.Spacing.md) {
                content()
            }
            .padding(Theme.Spacing.lg)
            .background(Theme.cardBackground(colorScheme))
            .clipShape(RoundedRectangle(cornerRadius: Theme.CornerRadius.large))
            .overlay {
                RoundedRectangle(cornerRadius: Theme.CornerRadius.large)
                    .stroke(Theme.surfaceGlow(colorScheme), lineWidth: 1)
            }
        }
    }
}

struct ThemedTextField: View {
    let label: String
    let placeholder: String
    @Binding var text: String
    var icon: String = "mappin"
    @Environment(\.colorScheme) private var colorScheme

    var body: some View {
        VStack(alignment: .leading, spacing: Theme.Spacing.xs) {
            Text(label)
                .font(.system(size: Theme.FontSize.caption))
                .foregroundStyle(Theme.textSecondary(colorScheme))

            HStack(spacing: Theme.Spacing.sm) {
                Image(systemName: icon)
                    .foregroundStyle(Theme.warmOrange)
                    .frame(width: 24)

                TextField(placeholder, text: $text)
                    .font(.system(size: Theme.FontSize.body))
                    .foregroundStyle(Theme.textPrimary(colorScheme))
            }
            .padding(Theme.Spacing.md)
            .background(Theme.cardBackgroundElevated(colorScheme))
            .clipShape(RoundedRectangle(cornerRadius: Theme.CornerRadius.medium))
        }
    }
}

struct ThemedToggle: View {
    let label: String
    @Binding var isOn: Bool
    var icon: String = "checkmark.circle"
    @Environment(\.colorScheme) private var colorScheme

    var body: some View {
        HStack(spacing: Theme.Spacing.sm) {
            Image(systemName: icon)
                .foregroundStyle(isOn ? Theme.warmOrange : Theme.textMuted(colorScheme))
                .frame(width: 24)

            Text(label)
                .font(.system(size: Theme.FontSize.body))
                .foregroundStyle(Theme.textPrimary(colorScheme))

            Spacer()

            Toggle("", isOn: $isOn)
                .labelsHidden()
                .tint(Theme.warmOrange)
        }
    }
}

struct ThemedStepper: View {
    let label: String
    let value: Int
    let range: ClosedRange<Int>
    let onIncrement: () -> Void
    let onDecrement: () -> Void
    @Environment(\.colorScheme) private var colorScheme

    var body: some View {
        HStack {
            Text(label)
                .font(.system(size: Theme.FontSize.body))
                .foregroundStyle(Theme.textPrimary(colorScheme))

            Spacer()

            HStack(spacing: Theme.Spacing.sm) {
                Button {
                    if value > range.lowerBound {
                        onDecrement()
                    }
                } label: {
                    Image(systemName: "minus.circle.fill")
                        .font(.title2)
                        .foregroundStyle(value > range.lowerBound ? Theme.warmOrange : Theme.textMuted(colorScheme))
                }
                .disabled(value <= range.lowerBound)

                Text("\(value)")
                    .font(.system(size: Theme.FontSize.body, weight: .bold))
                    .foregroundStyle(Theme.textPrimary(colorScheme))
                    .frame(minWidth: 30)

                Button {
                    if value < range.upperBound {
                        onIncrement()
                    }
                } label: {
                    Image(systemName: "plus.circle.fill")
                        .font(.title2)
                        .foregroundStyle(value < range.upperBound ? Theme.warmOrange : Theme.textMuted(colorScheme))
                }
                .disabled(value >= range.upperBound)
            }
        }
    }
}

struct ThemedDatePicker: View {
    let label: String
    @Binding var selection: Date
    @Environment(\.colorScheme) private var colorScheme

    var body: some View {
        HStack {
            HStack(spacing: Theme.Spacing.sm) {
                Image(systemName: "calendar")
                    .foregroundStyle(Theme.warmOrange)
                Text(label)
                    .font(.system(size: Theme.FontSize.body))
                    .foregroundStyle(Theme.textPrimary(colorScheme))
            }

            Spacer()

            DatePicker("", selection: $selection, displayedComponents: .date)
                .labelsHidden()
                .tint(Theme.warmOrange)
        }
    }
}

// MARK: - Date Range Picker

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
        }
    }

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

            // Arrow
            Image(systemName: "arrow.right")
                .font(.system(size: 14, weight: .medium))
                .foregroundStyle(Theme.textMuted(colorScheme))

            // End date
            VStack(alignment: .trailing, spacing: 4) {
                Text("END")
                    .font(.system(size: 10, weight: .semibold))
                    .foregroundStyle(Theme.textMuted(colorScheme))
                Text(endDate.formatted(.dateTime.month(.abbreviated).day().year()))
                    .font(.system(size: Theme.FontSize.body, weight: .semibold))
                    .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(.system(size: 16, weight: .semibold))
                    .foregroundStyle(Theme.warmOrange)
                    .frame(width: 36, height: 36)
                    .background(Theme.warmOrange.opacity(0.15))
                    .clipShape(Circle())
            }

            Spacer()

            Text(monthYearString)
                .font(.system(size: Theme.FontSize.cardTitle, weight: .bold, design: .rounded))
                .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(.system(size: 16, weight: .semibold))
                    .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(.system(size: 12, weight: .semibold))
                    .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(.system(size: Theme.FontSize.caption, weight: .medium))
                .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)
    }
}

struct SportSelectionChip: View {
    let sport: Sport
    let isSelected: Bool
    let onTap: () -> Void
    @Environment(\.colorScheme) private var colorScheme
    @State private var isPressed = false

    var body: some View {
        Button(action: onTap) {
            VStack(spacing: 6) {
                ZStack {
                    Circle()
                        .fill(isSelected ? sport.themeColor : sport.themeColor.opacity(0.15))
                        .frame(width: 48, height: 48)
                        .overlay {
                            if isSelected {
                                Circle()
                                    .stroke(sport.themeColor.opacity(0.3), lineWidth: 3)
                                    .frame(width: 54, height: 54)
                            }
                        }

                    Image(systemName: sport.iconName)
                        .font(.system(size: 20))
                        .foregroundStyle(isSelected ? .white : sport.themeColor)
                }

                Text(sport.rawValue)
                    .font(.system(size: 10, weight: isSelected ? .semibold : .medium))
                    .foregroundStyle(isSelected ? Theme.textPrimary(colorScheme) : Theme.textSecondary(colorScheme))
            }
            .frame(maxWidth: .infinity)
            .scaleEffect(isPressed ? 0.9 : 1.0)
        }
        .buttonStyle(.plain)
        .simultaneousGesture(
            DragGesture(minimumDistance: 0)
                .onChanged { _ in
                    withAnimation(Theme.Animation.spring) { isPressed = true }
                }
                .onEnded { _ in
                    withAnimation(Theme.Animation.spring) { isPressed = false }
                }
        )
    }
}

#Preview {
    TripCreationView(viewModel: TripCreationViewModel())
}
