use crate::documents::{RuntimeImportBlocker, RuntimeImportContext};
use crate::event::targets::{RuntimeCompanyTarget, RuntimePlayerTarget};

pub(crate) fn company_target_allowed_for_import(
    target: &RuntimeCompanyTarget,
    runtime_context: &RuntimeImportContext,
    allow_condition_true_company: bool,
) -> bool {
    match company_target_import_blocker(target, runtime_context) {
        None => true,
        Some(RuntimeImportBlocker::MissingConditionContext)
            if allow_condition_true_company
                && matches!(target, RuntimeCompanyTarget::ConditionTrueCompany) =>
        {
            true
        }
        Some(_) => false,
    }
}

pub(crate) fn player_target_allowed_for_import(
    target: &RuntimePlayerTarget,
    runtime_context: &RuntimeImportContext,
    allow_condition_true_player: bool,
) -> bool {
    match player_target_import_blocker(target, runtime_context) {
        None => true,
        Some(RuntimeImportBlocker::MissingPlayerConditionContext)
            if allow_condition_true_player
                && matches!(target, RuntimePlayerTarget::ConditionTruePlayer) =>
        {
            true
        }
        Some(_) => false,
    }
}

pub(crate) fn company_target_import_blocker(
    target: &RuntimeCompanyTarget,
    runtime_context: &RuntimeImportContext,
) -> Option<RuntimeImportBlocker> {
    match target {
        RuntimeCompanyTarget::AllActive => None,
        RuntimeCompanyTarget::Ids { ids } => {
            if ids.is_empty()
                || ids
                    .iter()
                    .any(|company_id| !runtime_context.known_company_ids.contains(company_id))
            {
                Some(RuntimeImportBlocker::MissingCompanyContext)
            } else {
                None
            }
        }
        RuntimeCompanyTarget::HumanCompanies | RuntimeCompanyTarget::AiCompanies => {
            if !runtime_context.has_complete_company_controller_context {
                Some(RuntimeImportBlocker::MissingCompanyRoleContext)
            } else {
                None
            }
        }
        RuntimeCompanyTarget::SelectedCompany => {
            if runtime_context.selected_company_id.is_some() {
                None
            } else {
                Some(RuntimeImportBlocker::MissingSelectionContext)
            }
        }
        RuntimeCompanyTarget::ConditionTrueCompany => {
            Some(RuntimeImportBlocker::MissingConditionContext)
        }
    }
}

pub(crate) fn company_target_import_error_message(
    target: &RuntimeCompanyTarget,
    runtime_context: &RuntimeImportContext,
) -> String {
    match company_target_import_blocker(target, runtime_context) {
        Some(RuntimeImportBlocker::MissingCompanyContext) => {
            "packed company effect requires resolved company ids".to_string()
        }
        Some(RuntimeImportBlocker::MissingSelectionContext) => {
            "packed company effect requires selected_company_id context".to_string()
        }
        Some(RuntimeImportBlocker::MissingCompanyRoleContext) => {
            "packed company effect requires company controller role context".to_string()
        }
        Some(RuntimeImportBlocker::MissingConditionContext) => {
            "packed company effect requires condition-relative context".to_string()
        }
        Some(RuntimeImportBlocker::CompanyConditionScopeDisabled) => {
            "packed company effect disables company-side negative-sentinel condition scope"
                .to_string()
        }
        Some(RuntimeImportBlocker::MissingTerritoryContext) => {
            "packed condition requires territory runtime context".to_string()
        }
        Some(RuntimeImportBlocker::NamedTerritoryBinding) => {
            "packed condition requires named territory binding".to_string()
        }
        Some(RuntimeImportBlocker::EvidenceBlockedDescriptor) => {
            "packed descriptor is still evidence-blocked".to_string()
        }
        Some(RuntimeImportBlocker::UnmappedOrdinaryCondition) => {
            "packed ordinary condition is not yet mapped".to_string()
        }
        Some(RuntimeImportBlocker::UnmappedWorldCondition) => {
            "packed whole-game condition is not yet mapped".to_string()
        }
        Some(RuntimeImportBlocker::MissingTrainContext) => {
            "packed effect requires runtime train context".to_string()
        }
        Some(RuntimeImportBlocker::MissingTrainTerritoryContext) => {
            "packed train effect requires runtime train territory context".to_string()
        }
        Some(RuntimeImportBlocker::MissingLocomotiveCatalogContext) => {
            "packed locomotive availability row requires locomotive catalog context".to_string()
        }
        Some(RuntimeImportBlocker::MissingPlayerContext)
        | Some(RuntimeImportBlocker::MissingPlayerSelectionContext)
        | Some(RuntimeImportBlocker::MissingPlayerRoleContext)
        | Some(RuntimeImportBlocker::MissingChairmanContext)
        | Some(RuntimeImportBlocker::ChairmanTargetScope)
        | Some(RuntimeImportBlocker::MissingPlayerConditionContext) => {
            "packed company effect is blocked by non-company import context".to_string()
        }
        None => "packed company effect is importable".to_string(),
    }
}

pub(crate) fn player_target_import_blocker(
    target: &RuntimePlayerTarget,
    runtime_context: &RuntimeImportContext,
) -> Option<RuntimeImportBlocker> {
    match target {
        RuntimePlayerTarget::AllActive => {
            if runtime_context.known_player_ids.is_empty() {
                Some(RuntimeImportBlocker::MissingPlayerContext)
            } else {
                None
            }
        }
        RuntimePlayerTarget::Ids { ids } => {
            if ids.is_empty()
                || ids
                    .iter()
                    .any(|player_id| !runtime_context.known_player_ids.contains(player_id))
            {
                Some(RuntimeImportBlocker::MissingPlayerContext)
            } else {
                None
            }
        }
        RuntimePlayerTarget::HumanPlayers | RuntimePlayerTarget::AiPlayers => {
            if !runtime_context.has_complete_player_controller_context {
                Some(RuntimeImportBlocker::MissingPlayerRoleContext)
            } else {
                None
            }
        }
        RuntimePlayerTarget::SelectedPlayer => {
            if runtime_context.selected_player_id.is_some() {
                None
            } else {
                Some(RuntimeImportBlocker::MissingPlayerSelectionContext)
            }
        }
        RuntimePlayerTarget::ConditionTruePlayer => {
            Some(RuntimeImportBlocker::MissingPlayerConditionContext)
        }
    }
}

pub(crate) fn player_target_import_error_message(
    target: &RuntimePlayerTarget,
    runtime_context: &RuntimeImportContext,
) -> String {
    match player_target_import_blocker(target, runtime_context) {
        Some(RuntimeImportBlocker::MissingPlayerContext) => {
            "packed player effect requires resolved player ids".to_string()
        }
        Some(RuntimeImportBlocker::MissingPlayerSelectionContext) => {
            "packed player effect requires selected_player_id context".to_string()
        }
        Some(RuntimeImportBlocker::MissingPlayerRoleContext) => {
            "packed player effect requires player controller role context".to_string()
        }
        Some(RuntimeImportBlocker::MissingPlayerConditionContext) => {
            "packed player effect requires player condition-relative context".to_string()
        }
        _ => "packed player effect is importable".to_string(),
    }
}
