//
//  GamePickerStep.swift
//  SportsTime
//
//  Game selection step for "By Games" planning mode.
//  Uses sheet-based drill-down: Sports → Teams → Games.
//

import SwiftUI

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

    @Binding var selectedSports: Set<Sport>
    @Binding var selectedTeamIds: Set<String>
    @Binding var selectedGameIds: Set<String>
    @Binding var startDate: Date
    @Binding var endDate: Date

    @State private var showSportsPicker = false
    @State private var showTeamsPicker = false
    @State private var showGamesPicker = false

    var body: some View {
        VStack(alignment: .leading, spacing: Theme.Spacing.md) {
            StepHeader(
                title: "Select games for your trip",
                subtitle: "Pick sports, then teams, then games"
            )

            // Step 1: Sports Selection
            selectionRow(
                icon: "sportscourt.fill",
                label: "Sports",
                value: selectedSports.isEmpty ? nil : selectedSports.map(\.rawValue).sorted().joined(separator: ", "),
                placeholder: "Select sports",
                onTap: { showSportsPicker = true },
                onClear: {
                    selectedSports = []
                    selectedTeamIds = []
                    selectedGameIds = []
                }
            )

            // Step 2: Teams Selection (enabled after sports)
            selectionRow(
                icon: "person.2.fill",
                label: "Teams",
                value: selectedTeamIds.isEmpty ? nil : "\(selectedTeamIds.count) team\(selectedTeamIds.count == 1 ? "" : "s")",
                placeholder: "Select teams",
                isEnabled: !selectedSports.isEmpty,
                onTap: { showTeamsPicker = true },
                onClear: {
                    selectedTeamIds = []
                    selectedGameIds = []
                }
            )

            // Step 3: Games Selection (enabled after teams)
            selectionRow(
                icon: "ticket.fill",
                label: "Games",
                value: selectedGameIds.isEmpty ? nil : "\(selectedGameIds.count) game\(selectedGameIds.count == 1 ? "" : "s")",
                placeholder: "Select games",
                isEnabled: !selectedTeamIds.isEmpty,
                onTap: { showGamesPicker = true },
                onClear: { selectedGameIds = [] }
            )

            // Selected Games Summary
            if !selectedGameIds.isEmpty {
                selectedGamesSummary

                // Date Range Section - shown when games are selected
                dateRangeSection
            }
        }
        .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)
        }
        .sheet(isPresented: $showSportsPicker) {
            SportsPickerSheet(selectedSports: $selectedSports) {
                // Clear downstream when sports change
                selectedTeamIds = []
                selectedGameIds = []
            }
        }
        .sheet(isPresented: $showTeamsPicker) {
            TeamsPickerSheet(
                selectedSports: selectedSports,
                selectedTeamIds: $selectedTeamIds
            ) {
                // Clear games when teams change
                selectedGameIds = []
            }
        }
        .sheet(isPresented: $showGamesPicker) {
            GamesPickerSheet(
                selectedTeamIds: selectedTeamIds,
                selectedGameIds: $selectedGameIds
            )
        }
    }

    // MARK: - Selection Row

    private func selectionRow(
        icon: String,
        label: String,
        value: String?,
        placeholder: String,
        isEnabled: Bool = true,
        onTap: @escaping () -> Void,
        onClear: @escaping () -> Void
    ) -> some View {
        VStack(alignment: .leading, spacing: Theme.Spacing.xs) {
            Text(label)
                .font(.caption)
                .fontWeight(.medium)
                .foregroundStyle(Theme.textSecondary(colorScheme))

            if let value = value {
                HStack(spacing: Theme.Spacing.sm) {
                    Button {
                        if isEnabled { onTap() }
                    } label: {
                        HStack {
                            Image(systemName: icon)
                                .foregroundStyle(isEnabled ? Theme.warmOrange : Theme.textMuted(colorScheme))
                                .accessibilityHidden(true)

                            Text(value)
                                .font(.subheadline)
                                .foregroundStyle(Theme.textPrimary(colorScheme))
                                .lineLimit(1)

                            Spacer()
                        }
                        .contentShape(Rectangle())
                    }
                    .buttonStyle(.plain)
                    .disabled(!isEnabled)

                    Button(action: onClear) {
                        Image(systemName: "xmark.circle.fill")
                            .foregroundStyle(Theme.textMuted(colorScheme))
                    }
                    .buttonStyle(.plain)
                    .minimumHitTarget()
                    .accessibilityLabel("Clear \(label.lowercased()) selection")
                }
                .padding(Theme.Spacing.md)
                .background(Theme.cardBackgroundElevated(colorScheme))
                .clipShape(RoundedRectangle(cornerRadius: Theme.CornerRadius.medium))
                .overlay(
                    RoundedRectangle(cornerRadius: Theme.CornerRadius.medium)
                        .stroke(Theme.warmOrange, lineWidth: 2)
                )
                .opacity(isEnabled ? 1 : 0.5)
            } else {
                Button {
                    if isEnabled { onTap() }
                } label: {
                    HStack {
                        Image(systemName: icon)
                            .foregroundStyle(isEnabled ? Theme.warmOrange : Theme.textMuted(colorScheme))
                            .accessibilityHidden(true)

                        Text(placeholder)
                            .font(.subheadline)
                            .foregroundStyle(Theme.textMuted(colorScheme))

                        Spacer()

                        Image(systemName: "chevron.right")
                            .font(.caption)
                            .foregroundStyle(Theme.textMuted(colorScheme))
                            .accessibilityHidden(true)
                    }
                    .padding(Theme.Spacing.md)
                    .background(Theme.cardBackgroundElevated(colorScheme))
                    .clipShape(RoundedRectangle(cornerRadius: Theme.CornerRadius.medium))
                    .overlay(
                        RoundedRectangle(cornerRadius: Theme.CornerRadius.medium)
                            .stroke(Theme.textMuted(colorScheme).opacity(0.3), lineWidth: 1)
                    )
                    .opacity(isEnabled ? 1 : 0.5)
                }
                .buttonStyle(.plain)
                .disabled(!isEnabled)
            }
        }
    }

    // MARK: - Selected Games Summary

    @State private var summaryGames: [RichGame] = []

    private var selectedGamesSummary: some View {
        VStack(alignment: .leading, spacing: Theme.Spacing.sm) {
            HStack {
                Image(systemName: "checkmark.circle.fill")
                    .foregroundStyle(Theme.warmOrange)
                    .accessibilityHidden(true)
                Text("\(selectedGameIds.count) game\(selectedGameIds.count == 1 ? "" : "s") selected")
                    .font(.subheadline)
                    .fontWeight(.medium)
                    .foregroundStyle(Theme.textPrimary(colorScheme))
            }

            ForEach(summaryGames.filter { selectedGameIds.contains($0.id) }) { game in
                HStack {
                    VStack(alignment: .leading, spacing: 2) {
                        Text(game.matchupDescription)
                            .font(.caption)
                            .fontWeight(.medium)
                            .foregroundStyle(Theme.textPrimary(colorScheme))
                        Text("\(game.stadium.city) • \(game.game.dateTime, style: .date)")
                            .font(.caption2)
                            .foregroundStyle(Theme.textMuted(colorScheme))
                    }
                    Spacer()
                    Button {
                        selectedGameIds.remove(game.id)
                    } label: {
                        Image(systemName: "xmark.circle.fill")
                            .foregroundStyle(Theme.textMuted(colorScheme))
                    }
                    .minimumHitTarget()
                    .accessibilityLabel("Remove \(game.matchupDescription)")
                }
                .padding(Theme.Spacing.sm)
                .background(Theme.cardBackgroundElevated(colorScheme))
                .clipShape(RoundedRectangle(cornerRadius: Theme.CornerRadius.small))
            }
        }
        .padding(Theme.Spacing.sm)
        .background(Theme.warmOrange.opacity(0.1))
        .clipShape(RoundedRectangle(cornerRadius: Theme.CornerRadius.medium))
        .task(id: selectedGameIds) {
            await loadSummaryGames()
        }
    }

    private func loadSummaryGames() async {
        var games: [RichGame] = []
        for teamId in selectedTeamIds {
            if let teamGames = try? await AppDataProvider.shared.gamesForTeam(teamId: teamId) {
                games.append(contentsOf: teamGames)
            }
        }
        await MainActor.run {
            summaryGames = Array(Set(games))
        }
        // Update date range after games are loaded (not before)
        await updateDateRangeForSelectedGames()
    }

    // MARK: - Date Range Section

    private var dateRangeSection: some View {
        VStack(alignment: .leading, spacing: Theme.Spacing.sm) {
            HStack {
                Image(systemName: "calendar")
                    .foregroundStyle(Theme.warmOrange)
                    .accessibilityHidden(true)
                Text("Trip Date Range")
                    .font(.subheadline)
                    .fontWeight(.medium)
                    .foregroundStyle(Theme.textPrimary(colorScheme))

                Spacer()

                // Show auto-calculated indicator
                Text("Auto-adjusted")
                    .font(.caption2)
                    .foregroundStyle(Theme.textMuted(colorScheme))
                    .padding(.horizontal, 8)
                    .padding(.vertical, 4)
                    .background(Theme.cardBackgroundElevated(colorScheme))
                    .clipShape(Capsule())
            }

            DateRangePicker(startDate: $startDate, endDate: $endDate)

            // Game date markers legend
            if !summaryGames.isEmpty {
                let selectedGamesWithDates = summaryGames.filter { selectedGameIds.contains($0.id) }
                if !selectedGamesWithDates.isEmpty {
                    VStack(alignment: .leading, spacing: 4) {
                        Text("Game dates:")
                            .font(.caption2)
                            .foregroundStyle(Theme.textMuted(colorScheme))

                        ForEach(selectedGamesWithDates.sorted { $0.game.dateTime < $1.game.dateTime }) { game in
                            HStack(spacing: 6) {
                                Circle()
                                    .fill(game.game.sport.themeColor)
                                    .frame(width: 6, height: 6)
                                Text("\(game.matchupDescription) - \(game.game.dateTime, style: .date)")
                                    .font(.caption2)
                                    .foregroundStyle(Theme.textSecondary(colorScheme))
                            }
                        }
                    }
                    .padding(.top, Theme.Spacing.xs)
                }
            }
        }
        .padding(Theme.Spacing.md)
        .background(Theme.cardBackgroundElevated(colorScheme))
        .clipShape(RoundedRectangle(cornerRadius: Theme.CornerRadius.medium))
    }

    /// Updates the date range based on selected games
    /// - Single game: 7-day span centered on game (position 4 of 7, so game is day 4)
    /// - Multiple games: range from earliest to latest with 1-day buffer
    private func updateDateRangeForSelectedGames() async {
        let selectedGames = summaryGames.filter { selectedGameIds.contains($0.id) }

        guard !selectedGames.isEmpty else { return }

        let gameDates = selectedGames.map { $0.game.dateTime }.sorted()
        let calendar = Calendar.current

        await MainActor.run {
            if gameDates.count == 1 {
                // Single game: 7-day span centered on game
                // Position 4 of 7 means: 3 days before, game day, 3 days after
                let gameDate = gameDates[0]
                let newStart = calendar.date(byAdding: .day, value: -3, to: gameDate) ?? gameDate
                let newEnd = calendar.date(byAdding: .day, value: 3, to: gameDate) ?? gameDate
                startDate = calendar.startOfDay(for: newStart)
                endDate = calendar.startOfDay(for: newEnd)
            } else {
                // Multiple games: span from first to last with 1-day buffer
                let firstGameDate = gameDates.first!
                let lastGameDate = gameDates.last!
                let newStart = calendar.date(byAdding: .day, value: -1, to: firstGameDate) ?? firstGameDate
                let newEnd = calendar.date(byAdding: .day, value: 1, to: lastGameDate) ?? lastGameDate
                startDate = calendar.startOfDay(for: newStart)
                endDate = calendar.startOfDay(for: newEnd)
            }
        }
    }
}

// MARK: - Sports Picker Sheet

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

    @Binding var selectedSports: Set<Sport>
    let onChanged: () -> Void

    var body: some View {
        NavigationStack {
            List {
                ForEach(Sport.supported, id: \.self) { sport in
                    Button {
                        if selectedSports.contains(sport) {
                            selectedSports.remove(sport)
                        } else {
                            selectedSports.insert(sport)
                        }
                        onChanged()
                    } label: {
                        HStack(spacing: Theme.Spacing.sm) {
                            Image(systemName: sport.iconName)
                                .font(.title2)
                                .foregroundStyle(sport.themeColor)
                                .frame(width: 32)

                            Text(sport.rawValue)
                                .font(.body)
                                .foregroundStyle(Theme.textPrimary(colorScheme))

                            Spacer()

                            if selectedSports.contains(sport) {
                                Image(systemName: "checkmark.circle.fill")
                                    .foregroundStyle(Theme.warmOrange)
                                    .accessibilityHidden(true)
                            } else {
                                Image(systemName: "circle")
                                    .foregroundStyle(Theme.textMuted(colorScheme))
                                    .accessibilityHidden(true)
                            }
                        }
                        .padding(.vertical, Theme.Spacing.xs)
                        .contentShape(Rectangle())
                    }
                    .buttonStyle(.plain)
                    .accessibilityAddTraits(selectedSports.contains(sport) ? .isSelected : [])
                }
            }
            .listStyle(.plain)
            .navigationTitle("Select Sports")
            .navigationBarTitleDisplayMode(.inline)
            .toolbar {
                ToolbarItem(placement: .cancellationAction) {
                    Button("Cancel") { dismiss() }
                }
                ToolbarItem(placement: .confirmationAction) {
                    Button("Done") { dismiss() }
                        .fontWeight(.semibold)
                }
            }
        }
        .presentationDetents([.medium])
    }
}

// MARK: - Teams Picker Sheet

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

    let selectedSports: Set<Sport>
    @Binding var selectedTeamIds: Set<String>
    let onChanged: () -> Void

    @State private var searchText = ""

    private var teams: [Team] {
        let allTeams = AppDataProvider.shared.teams
            .filter { selectedSports.contains($0.sport) }
            .sorted { $0.fullName < $1.fullName }

        if searchText.isEmpty {
            return allTeams
        }

        return allTeams.filter {
            $0.fullName.localizedCaseInsensitiveContains(searchText) ||
            $0.city.localizedCaseInsensitiveContains(searchText)
        }
    }

    private var groupedTeams: [(Sport, [Team])] {
        let grouped = Dictionary(grouping: teams) { $0.sport }
        return selectedSports.sorted { $0.rawValue < $1.rawValue }
            .compactMap { sport in
                guard let sportTeams = grouped[sport], !sportTeams.isEmpty else { return nil }
                return (sport, sportTeams)
            }
    }

    var body: some View {
        NavigationStack {
            List {
                ForEach(groupedTeams, id: \.0) { sport, sportTeams in
                    Section {
                        ForEach(sportTeams) { team in
                            Button {
                                if selectedTeamIds.contains(team.id) {
                                    selectedTeamIds.remove(team.id)
                                } else {
                                    selectedTeamIds.insert(team.id)
                                }
                                onChanged()
                            } label: {
                                HStack(spacing: Theme.Spacing.sm) {
                                    Circle()
                                        .fill(team.primaryColor.map { Color(hex: $0) } ?? sport.themeColor)
                                        .frame(width: 28, height: 28)

                                    VStack(alignment: .leading, spacing: 2) {
                                        Text(team.fullName)
                                            .font(.body)
                                            .foregroundStyle(Theme.textPrimary(colorScheme))

                                        Text(team.city)
                                            .font(.caption)
                                            .foregroundStyle(Theme.textMuted(colorScheme))
                                    }

                                    Spacer()

                                    if selectedTeamIds.contains(team.id) {
                                        Image(systemName: "checkmark.circle.fill")
                                            .foregroundStyle(Theme.warmOrange)
                                            .accessibilityHidden(true)
                                    } else {
                                        Image(systemName: "circle")
                                            .foregroundStyle(Theme.textMuted(colorScheme))
                                            .accessibilityHidden(true)
                                    }
                                }
                                .padding(.vertical, Theme.Spacing.xs)
                                .contentShape(Rectangle())
                            }
                            .buttonStyle(.plain)
                            .accessibilityAddTraits(selectedTeamIds.contains(team.id) ? .isSelected : [])
                        }
                    } header: {
                        HStack(spacing: Theme.Spacing.xs) {
                            Image(systemName: sport.iconName)
                                .foregroundStyle(sport.themeColor)
                            Text(sport.rawValue)
                        }
                    }
                }
            }
            .listStyle(.plain)
            .searchable(text: $searchText, prompt: "Search teams")
            .navigationTitle("Select Teams")
            .navigationBarTitleDisplayMode(.inline)
            .toolbar {
                ToolbarItem(placement: .cancellationAction) {
                    Button("Cancel") { dismiss() }
                }
                ToolbarItem(placement: .confirmationAction) {
                    Button("Done") { dismiss() }
                        .fontWeight(.semibold)
                }
            }
        }
        .presentationDetents([.large])
    }
}

// MARK: - Games Picker Sheet

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

    let selectedTeamIds: Set<String>
    @Binding var selectedGameIds: Set<String>

    @State private var games: [RichGame] = []
    @State private var isLoading = true

    private var groupedGames: [(Date, [RichGame])] {
        let grouped = Dictionary(grouping: games) { game in
            Calendar.current.startOfDay(for: game.game.dateTime)
        }
        return grouped.keys.sorted().map { date in
            (date, grouped[date] ?? [])
        }
    }

    var body: some View {
        NavigationStack {
            Group {
                if isLoading {
                    ProgressView("Loading games...")
                        .frame(maxWidth: .infinity, maxHeight: .infinity)
                } else if games.isEmpty {
                    ContentUnavailableView(
                        "No Games Found",
                        systemImage: "ticket",
                        description: Text("No upcoming games found for the selected teams")
                    )
                } else {
                    List {
                        ForEach(groupedGames, id: \.0) { date, dateGames in
                            Section {
                                ForEach(dateGames) { game in
                                    Button {
                                        if selectedGameIds.contains(game.id) {
                                            selectedGameIds.remove(game.id)
                                        } else {
                                            selectedGameIds.insert(game.id)
                                        }
                                    } label: {
                                        HStack {
                                            VStack(alignment: .leading, spacing: 2) {
                                                HStack(spacing: Theme.Spacing.xs) {
                                                    Image(systemName: game.game.sport.iconName)
                                                        .font(.caption)
                                                        .foregroundStyle(game.game.sport.themeColor)

                                                    Text(game.matchupDescription)
                                                        .font(.body)
                                                        .foregroundStyle(Theme.textPrimary(colorScheme))
                                                }

                                                Text("\(game.stadium.name) • \(game.localGameTimeShort)")
                                                    .font(.caption)
                                                    .foregroundStyle(Theme.textMuted(colorScheme))
                                            }

                                            Spacer()

                                            if selectedGameIds.contains(game.id) {
                                                Image(systemName: "checkmark.circle.fill")
                                                    .foregroundStyle(Theme.warmOrange)
                                                    .accessibilityHidden(true)
                                            } else {
                                                Image(systemName: "circle")
                                                    .foregroundStyle(Theme.textMuted(colorScheme))
                                                    .accessibilityHidden(true)
                                            }
                                        }
                                        .padding(.vertical, Theme.Spacing.xs)
                                        .contentShape(Rectangle())
                                        .accessibilityElement(children: .combine)
                                    }
                                    .buttonStyle(.plain)
                                    .accessibilityAddTraits(selectedGameIds.contains(game.id) ? .isSelected : [])
                                }
                            } header: {
                                Text(date, style: .date)
                            }
                        }
                    }
                    .listStyle(.plain)
                }
            }
            .navigationTitle("Select Games")
            .navigationBarTitleDisplayMode(.inline)
            .toolbar {
                ToolbarItem(placement: .cancellationAction) {
                    Button("Cancel") { dismiss() }
                }
                ToolbarItem(placement: .confirmationAction) {
                    Button("Done") { dismiss() }
                        .fontWeight(.semibold)
                }
            }
        }
        .presentationDetents([.large])
        .task {
            await loadGames()
        }
    }

    private func loadGames() async {
        var allGames: [RichGame] = []
        for teamId in selectedTeamIds {
            if let teamGames = try? await AppDataProvider.shared.gamesForTeam(teamId: teamId) {
                let futureGames = teamGames.filter { $0.game.dateTime > Date() }
                allGames.append(contentsOf: futureGames)
            }
        }

        let uniqueGames = Array(Set(allGames)).sorted { $0.game.dateTime < $1.game.dateTime }
        await MainActor.run {
            games = uniqueGames
            isLoading = false
        }
    }
}

// MARK: - Preview

#Preview {
    GamePickerStep(
        selectedSports: .constant([.mlb]),
        selectedTeamIds: .constant([]),
        selectedGameIds: .constant([]),
        startDate: .constant(Date()),
        endDate: .constant(Date().addingTimeInterval(86400 * 7))
    )
    .padding()
    .themedBackground()
}
