use std::collections::BTreeSet;

use crate::engine::conditions::ResolvedConditionContext;
use crate::event::conditions::RuntimeCondition;
use crate::event::targets::RuntimeCargoClass;
use crate::state::RuntimeState;

use super::{catalogs, context, entities, territories, world_state};

pub(in crate::engine) fn evaluate_record_conditions(
    state: &RuntimeState,
    conditions: &[RuntimeCondition],
) -> Result<Option<ResolvedConditionContext>, String> {
    if conditions.is_empty() {
        return Ok(Some(ResolvedConditionContext::default()));
    }

    let mut company_matches: Option<BTreeSet<u32>> = None;
    let mut player_matches: Option<BTreeSet<u32>> = None;
    let mut chairman_matches: Option<BTreeSet<u32>> = None;

    for condition in conditions {
        match condition {
            RuntimeCondition::WorldVariableThreshold {
                index,
                comparator,
                value,
            } => {
                if !world_state::world_variable_threshold_matches(
                    state,
                    *index,
                    *comparator,
                    *value,
                ) {
                    return Ok(None);
                }
            }
            RuntimeCondition::CompanyNumericThreshold {
                target,
                metric,
                comparator,
                value,
            } => {
                let matching = entities::matching_company_numeric_threshold(
                    state,
                    target,
                    *metric,
                    *comparator,
                    *value,
                )?;
                if matching.is_empty() {
                    return Ok(None);
                }
                context::intersect_company_matches(&mut company_matches, matching);
                if company_matches.as_ref().is_some_and(BTreeSet::is_empty) {
                    return Ok(None);
                }
            }
            RuntimeCondition::CompanyVariableThreshold {
                target,
                index,
                comparator,
                value,
            } => {
                let matching = entities::matching_company_variable_threshold(
                    state,
                    target,
                    *index,
                    *comparator,
                    *value,
                )?;
                if matching.is_empty() {
                    return Ok(None);
                }
                context::intersect_company_matches(&mut company_matches, matching);
                if company_matches.as_ref().is_some_and(BTreeSet::is_empty) {
                    return Ok(None);
                }
            }
            RuntimeCondition::TerritoryNumericThreshold {
                target,
                metric,
                comparator,
                value,
            } => {
                if !territories::territory_numeric_threshold_matches(
                    state,
                    target,
                    *metric,
                    *comparator,
                    *value,
                )? {
                    return Ok(None);
                }
            }
            RuntimeCondition::TerritoryVariableThreshold {
                target,
                index,
                comparator,
                value,
            } => {
                if !territories::territory_variable_threshold_matches(
                    state,
                    target,
                    *index,
                    *comparator,
                    *value,
                )? {
                    return Ok(None);
                }
            }
            RuntimeCondition::PlayerVariableThreshold {
                target,
                index,
                comparator,
                value,
            } => {
                let matching = entities::matching_player_variable_threshold(
                    state,
                    target,
                    *index,
                    *comparator,
                    *value,
                )?;
                if matching.is_empty() {
                    return Ok(None);
                }
                context::intersect_player_matches(&mut player_matches, matching);
                if player_matches.as_ref().is_some_and(BTreeSet::is_empty) {
                    return Ok(None);
                }
            }
            RuntimeCondition::ChairmanNumericThreshold {
                target,
                metric,
                comparator,
                value,
            } => {
                let matching = entities::matching_chairman_numeric_threshold(
                    state,
                    target,
                    *metric,
                    *comparator,
                    *value,
                )?;
                if matching.is_empty() {
                    return Ok(None);
                }
                context::intersect_chairman_matches(&mut chairman_matches, matching);
                if chairman_matches.as_ref().is_some_and(BTreeSet::is_empty) {
                    return Ok(None);
                }
            }
            RuntimeCondition::CompanyTerritoryNumericThreshold {
                target,
                territory,
                metric,
                comparator,
                value,
            } => {
                let matching = entities::matching_company_territory_numeric_threshold(
                    state,
                    target,
                    territory,
                    *metric,
                    *comparator,
                    *value,
                )?;
                if matching.is_empty() {
                    return Ok(None);
                }
                context::intersect_company_matches(&mut company_matches, matching);
                if company_matches.as_ref().is_some_and(BTreeSet::is_empty) {
                    return Ok(None);
                }
            }
            RuntimeCondition::SpecialConditionThreshold {
                label,
                comparator,
                value,
            } => {
                if !world_state::special_condition_threshold_matches(
                    state,
                    label,
                    *comparator,
                    *value,
                ) {
                    return Ok(None);
                }
            }
            RuntimeCondition::CandidateAvailabilityThreshold {
                name,
                comparator,
                value,
            } => {
                if !catalogs::candidate_availability_threshold_matches(
                    state,
                    name,
                    *comparator,
                    *value,
                ) {
                    return Ok(None);
                }
            }
            RuntimeCondition::NamedLocomotiveAvailabilityThreshold {
                name,
                comparator,
                value,
            } => {
                if !catalogs::named_locomotive_availability_threshold_matches(
                    state,
                    name,
                    *comparator,
                    *value,
                ) {
                    return Ok(None);
                }
            }
            RuntimeCondition::NamedLocomotiveCostThreshold {
                name,
                comparator,
                value,
            } => {
                if !catalogs::named_locomotive_cost_threshold_matches(
                    state,
                    name,
                    *comparator,
                    *value,
                ) {
                    return Ok(None);
                }
            }
            RuntimeCondition::CargoProductionSlotThreshold {
                slot,
                comparator,
                value,
                ..
            } => {
                if !catalogs::cargo_production_slot_threshold_matches(
                    state,
                    *slot,
                    *comparator,
                    *value,
                ) {
                    return Ok(None);
                }
            }
            RuntimeCondition::CargoProductionTotalThreshold { comparator, value } => {
                if !catalogs::cargo_production_total_threshold_matches(state, *comparator, *value) {
                    return Ok(None);
                }
            }
            RuntimeCondition::FactoryProductionTotalThreshold { comparator, value } => {
                if !catalogs::cargo_production_class_threshold_matches(
                    state,
                    RuntimeCargoClass::Factory,
                    *comparator,
                    *value,
                ) {
                    return Ok(None);
                }
            }
            RuntimeCondition::FarmMineProductionTotalThreshold { comparator, value } => {
                if !catalogs::cargo_production_class_threshold_matches(
                    state,
                    RuntimeCargoClass::FarmMine,
                    *comparator,
                    *value,
                ) {
                    return Ok(None);
                }
            }
            RuntimeCondition::OtherCargoProductionTotalThreshold { comparator, value } => {
                if !catalogs::cargo_production_class_threshold_matches(
                    state,
                    RuntimeCargoClass::Other,
                    *comparator,
                    *value,
                ) {
                    return Ok(None);
                }
            }
            RuntimeCondition::LimitedTrackBuildingAmountThreshold { comparator, value } => {
                if !world_state::limited_track_building_amount_threshold_matches(
                    state,
                    *comparator,
                    *value,
                ) {
                    return Ok(None);
                }
            }
            RuntimeCondition::TerritoryAccessCostThreshold { comparator, value } => {
                if !world_state::territory_access_cost_threshold_matches(state, *comparator, *value)
                {
                    return Ok(None);
                }
            }
            RuntimeCondition::EconomicStatusCodeThreshold { comparator, value } => {
                if !world_state::economic_status_code_threshold_matches(state, *comparator, *value)
                {
                    return Ok(None);
                }
            }
            RuntimeCondition::WorldFlagEquals { key, value } => {
                if !world_state::world_flag_equals(state, key, *value) {
                    return Ok(None);
                }
            }
        }
    }

    Ok(Some(ResolvedConditionContext {
        matching_company_ids: company_matches.unwrap_or_default(),
        matching_player_ids: player_matches.unwrap_or_default(),
        matching_chairman_profile_ids: chairman_matches.unwrap_or_default(),
    }))
}
