//
//  TripWizardViewModel.swift
//  SportsTime
//
//  ViewModel for trip wizard.
//

import Foundation
import SwiftUI

@Observable
final class TripWizardViewModel {

    // MARK: - Planning Mode

    var planningMode: PlanningMode? = nil {
        didSet {
            if oldValue != nil && oldValue != planningMode {
                resetAllSelections()
            }
        }
    }

    // MARK: - Sports Selection

    var selectedSports: Set<Sport> = []

    // MARK: - Dates

    var startDate: Date = Date()
    var endDate: Date = Date().addingTimeInterval(86400 * 7)
    var hasSetDates: Bool = false

    // MARK: - Regions

    var selectedRegions: Set<Region> = []

    // MARK: - Route Preferences

    var routePreference: RoutePreference = .balanced
    var hasSetRoutePreference: Bool = false

    // MARK: - Repeat Cities

    var allowRepeatCities: Bool = false
    var hasSetRepeatCities: Bool = false

    // MARK: - Must Stops

    var mustStopLocations: [LocationInput] = []

    // MARK: - Mode-Specific: gameFirst (cascading selection)

    var gamePickerSports: Set<Sport> = []
    var gamePickerTeamIds: Set<String> = []
    var selectedGameIds: Set<String> = []

    // MARK: - Mode-Specific: followTeam

    var selectedTeamId: String? = nil
    var teamPickerSport: Sport? = nil

    // MARK: - Mode-Specific: locations

    var startLocation: LocationInput? = nil
    var endLocation: LocationInput? = nil

    // MARK: - Mode-Specific: teamFirst

    var teamFirstSport: Sport? = nil
    var teamFirstSelectedTeamIds: Set<String> = []

    // MARK: - Planning State

    var isPlanning: Bool = false

    // MARK: - Sport Availability

    var sportAvailability: [Sport: Bool] = [:]
    var isLoadingSportAvailability: Bool = false

    // MARK: - Visibility

    /// All steps visible once planning mode is selected
    var areStepsVisible: Bool {
        planningMode != nil
    }

    /// Mode-specific step visibility
    var showDatesStep: Bool {
        planningMode == .dateRange || planningMode == .followTeam || planningMode == .locations
    }

    var showSportsStep: Bool {
        planningMode == .dateRange || planningMode == .locations
    }

    var showRegionsStep: Bool {
        planningMode == .dateRange
    }

    var showGamePickerStep: Bool {
        planningMode == .gameFirst
    }

    var showTeamPickerStep: Bool {
        planningMode == .followTeam
    }

    var showLocationsStep: Bool {
        planningMode == .locations
    }

    var showTeamFirstStep: Bool {
        planningMode == .teamFirst
    }

    // MARK: - Validation

    /// All required fields must be set before planning
    var canPlanTrip: Bool {
        guard let mode = planningMode else { return false }

        // Common requirements for all modes
        guard hasSetRoutePreference && hasSetRepeatCities else { return false }

        switch mode {
        case .dateRange:
            return hasSetDates && !selectedSports.isEmpty && !selectedRegions.isEmpty
        case .gameFirst:
            return !selectedGameIds.isEmpty
        case .locations:
            return startLocation != nil && endLocation != nil && hasSetDates && !selectedSports.isEmpty
        case .followTeam:
            return selectedTeamId != nil && hasSetDates
        case .teamFirst:
            return teamFirstSport != nil && teamFirstSelectedTeamIds.count >= 2
        }
    }

    /// Field validation for the review step - shows which fields are missing
    var fieldValidation: FieldValidation {
        FieldValidation(
            planningMode: planningMode,
            sports: selectedSports.isEmpty ? .missing : .valid,
            dates: hasSetDates ? .valid : .missing,
            regions: selectedRegions.isEmpty ? .missing : .valid,
            routePreference: hasSetRoutePreference ? .valid : .missing,
            repeatCities: hasSetRepeatCities ? .valid : .missing,
            selectedGames: selectedGameIds.isEmpty ? .missing : .valid,
            selectedTeam: selectedTeamId == nil ? .missing : .valid,
            startLocation: startLocation == nil ? .missing : .valid,
            endLocation: endLocation == nil ? .missing : .valid,
            teamFirstTeams: teamFirstSelectedTeamIds.count >= 2 ? .valid : .missing,
            teamFirstTeamCount: teamFirstSelectedTeamIds.count
        )
    }

    // MARK: - Sport Availability

    func canSelectSport(_ sport: Sport) -> Bool {
        sportAvailability[sport] ?? true // Default to available if not checked
    }

    func fetchSportAvailability() async {
        guard hasSetDates else { return }

        isLoadingSportAvailability = true
        defer { isLoadingSportAvailability = false }

        var availability: [Sport: Bool] = [:]

        for sport in Sport.supported {
            do {
                let games = try await AppDataProvider.shared.filterGames(
                    sports: [sport],
                    startDate: startDate,
                    endDate: endDate
                )
                availability[sport] = !games.isEmpty
            } catch {
                availability[sport] = true // Default to available on error
            }
        }

        await MainActor.run {
            self.sportAvailability = availability
        }
    }

    // MARK: - Reset Logic

    private func resetAllSelections() {
        // Common fields
        selectedSports = []
        hasSetDates = false
        selectedRegions = []
        hasSetRoutePreference = false
        hasSetRepeatCities = false
        mustStopLocations = []

        // gameFirst mode fields
        gamePickerSports = []
        gamePickerTeamIds = []
        selectedGameIds = []

        // followTeam mode fields
        selectedTeamId = nil
        teamPickerSport = nil

        // locations mode fields
        startLocation = nil
        endLocation = nil

        // teamFirst mode fields
        teamFirstSport = nil
        teamFirstSelectedTeamIds = []
    }
}

// MARK: - Field Validation

struct FieldValidation {
    enum Status {
        case valid
        case missing
    }

    let planningMode: PlanningMode?

    // Common fields
    let sports: Status
    let dates: Status
    let regions: Status
    let routePreference: Status
    let repeatCities: Status

    // Mode-specific fields
    let selectedGames: Status
    let selectedTeam: Status
    let startLocation: Status
    let endLocation: Status
    let teamFirstTeams: Status
    let teamFirstTeamCount: Int

    /// Returns only the fields that are required for the current planning mode
    var requiredFields: [(name: String, status: Status)] {
        var fields: [(String, Status)] = []

        guard let mode = planningMode else { return fields }

        switch mode {
        case .dateRange:
            fields = [
                ("Dates", dates),
                ("Sports", sports),
                ("Regions", regions),
                ("Route Preference", routePreference),
                ("Repeat Cities", repeatCities)
            ]
        case .gameFirst:
            fields = [
                ("Games", selectedGames),
                ("Route Preference", routePreference),
                ("Repeat Cities", repeatCities)
            ]
        case .locations:
            fields = [
                ("Start Location", startLocation),
                ("End Location", endLocation),
                ("Dates", dates),
                ("Sports", sports),
                ("Route Preference", routePreference),
                ("Repeat Cities", repeatCities)
            ]
        case .followTeam:
            fields = [
                ("Team", selectedTeam),
                ("Dates", dates),
                ("Route Preference", routePreference),
                ("Repeat Cities", repeatCities)
            ]
        case .teamFirst:
            fields = [
                ("Teams", teamFirstTeams),
                ("Route Preference", routePreference),
                ("Repeat Cities", repeatCities)
            ]
        }

        return fields
    }

    /// Returns only the missing required fields for the current mode
    var missingFields: [String] {
        requiredFields.filter { $0.status == .missing }.map { $0.name }
    }

    /// Whether all required fields for the current mode are valid
    var allRequiredFieldsValid: Bool {
        requiredFields.allSatisfy { $0.status == .valid }
    }
}
