//
//  TripPlanningEngine.swift
//  SportsTime
//
//  Thin orchestrator that delegates to scenario-specific planners.
//

import Foundation

/// Main entry point for trip planning.
/// Delegates to scenario-specific planners via the ScenarioPlanner protocol.
///
/// - Expected Behavior:
///   - Uses ScenarioPlannerFactory.planner(for:) to select the right planner
///   - Delegates entirely to the selected scenario planner
///   - Applies repeat city filter to successful results
///   - If all options violate repeat city constraint → .failure with .repeatCityViolation
///   - Passes through failures from scenario planners unchanged
///
/// - Invariants:
///   - Never modifies the logic of scenario planners
///   - Always returns a result (success or failure), never throws
///   - Repeat city filter only applied when allowRepeatCities is false
///
final class TripPlanningEngine {

    /// Plans itineraries based on the request inputs.
    /// Automatically detects which scenario applies and delegates to the appropriate planner.
    ///
    /// - Parameter request: The planning request containing all inputs
    /// - Returns: Ranked itineraries on success, or explicit failure with reason
    func planItineraries(request: PlanningRequest) -> ItineraryResult {

        // Detect scenario and get the appropriate planner
        let planner = ScenarioPlannerFactory.planner(for: request)

        // Delegate to the scenario planner
        let result = planner.plan(request: request)

        // Apply preference filters to successful results
        return applyPreferenceFilters(to: result, request: request)
    }

    // MARK: - Private

    /// Applies allowRepeatCities filter after scenario planners return.
    /// Note: Region filtering is done during game selection in scenario planners.
    private func applyPreferenceFilters(
        to result: ItineraryResult,
        request: PlanningRequest
    ) -> ItineraryResult {
        guard case .success(let originalOptions) = result else {
            return result
        }

        var options = originalOptions

        // Filter repeat cities (this is enforced during beam search, but double-check here)
        options = RouteFilters.filterRepeatCities(
            options,
            allow: request.preferences.allowRepeatCities
        )

        if options.isEmpty && !request.preferences.allowRepeatCities {
            let violatingCities = RouteFilters.findRepeatCities(in: originalOptions)
            return .failure(PlanningFailure(
                reason: .repeatCityViolation(cities: violatingCities)
            ))
        }

        // Region filtering is applied during game selection in scenario planners

        return .success(options)
    }
}
