use super::super::super::blockers::record_uses_condition_true_chairman;
use super::predicates::{record_uses_condition_true_company, record_uses_condition_true_player};
use crate::documents::RuntimeImportBlocker;
use crate::event::conditions::RuntimeCondition;
use crate::event::metrics::{RuntimeCompanyConditionTestScope, RuntimePlayerConditionTestScope};
use crate::event::targets::{RuntimeCompanyTarget, RuntimePlayerTarget};
use crate::inspect::smp::events::SmpLoadedPackedEventRecordSummary;

pub(crate) fn lowered_condition_true_company_target(
    record: &SmpLoadedPackedEventRecordSummary,
) -> Result<Option<RuntimeCompanyTarget>, RuntimeImportBlocker> {
    if !record_uses_condition_true_company(record) {
        return Ok(None);
    }
    let scope = record
        .negative_sentinel_scope
        .as_ref()
        .ok_or(RuntimeImportBlocker::MissingConditionContext)?;
    match scope.company_test_scope {
        RuntimeCompanyConditionTestScope::Disabled => {
            Err(RuntimeImportBlocker::CompanyConditionScopeDisabled)
        }
        RuntimeCompanyConditionTestScope::AllCompanies => Ok(Some(RuntimeCompanyTarget::AllActive)),
        RuntimeCompanyConditionTestScope::SelectedCompanyOnly => {
            Ok(Some(RuntimeCompanyTarget::SelectedCompany))
        }
        RuntimeCompanyConditionTestScope::AiCompaniesOnly => {
            Ok(Some(RuntimeCompanyTarget::AiCompanies))
        }
        RuntimeCompanyConditionTestScope::HumanCompaniesOnly => {
            Ok(Some(RuntimeCompanyTarget::HumanCompanies))
        }
    }
}

pub(crate) fn lowered_condition_true_player_target(
    record: &SmpLoadedPackedEventRecordSummary,
) -> Result<Option<RuntimePlayerTarget>, RuntimeImportBlocker> {
    if !record_uses_condition_true_player(record) {
        return Ok(None);
    }
    let scope = record
        .negative_sentinel_scope
        .as_ref()
        .ok_or(RuntimeImportBlocker::MissingPlayerConditionContext)?;
    match scope.player_test_scope {
        RuntimePlayerConditionTestScope::Disabled => {
            Err(RuntimeImportBlocker::MissingPlayerConditionContext)
        }
        RuntimePlayerConditionTestScope::AllPlayers => Ok(Some(RuntimePlayerTarget::AllActive)),
        RuntimePlayerConditionTestScope::SelectedPlayerOnly => {
            Ok(Some(RuntimePlayerTarget::SelectedPlayer))
        }
        RuntimePlayerConditionTestScope::AiPlayersOnly => Ok(Some(RuntimePlayerTarget::AiPlayers)),
        RuntimePlayerConditionTestScope::HumanPlayersOnly => {
            Ok(Some(RuntimePlayerTarget::HumanPlayers))
        }
    }
}

pub(crate) fn lower_condition_true_company_target_in_company_target(
    target: &RuntimeCompanyTarget,
    lowered_target: Option<&RuntimeCompanyTarget>,
) -> Result<RuntimeCompanyTarget, RuntimeImportBlocker> {
    match target {
        RuntimeCompanyTarget::ConditionTrueCompany => lowered_target
            .cloned()
            .ok_or(RuntimeImportBlocker::MissingConditionContext),
        _ => Ok(target.clone()),
    }
}

pub(crate) fn lower_condition_true_player_target_in_player_target(
    target: &RuntimePlayerTarget,
    lowered_target: Option<&RuntimePlayerTarget>,
) -> Result<RuntimePlayerTarget, RuntimeImportBlocker> {
    match target {
        RuntimePlayerTarget::ConditionTruePlayer => lowered_target
            .cloned()
            .ok_or(RuntimeImportBlocker::MissingPlayerConditionContext),
        _ => Ok(target.clone()),
    }
}

pub(crate) fn ensure_condition_true_chairman_context(
    record: &SmpLoadedPackedEventRecordSummary,
) -> Result<(), RuntimeImportBlocker> {
    if !record_uses_condition_true_chairman(record) {
        return Ok(());
    }
    if record
        .decoded_conditions
        .iter()
        .any(|condition| matches!(condition, RuntimeCondition::ChairmanNumericThreshold { .. }))
    {
        Ok(())
    } else {
        Err(RuntimeImportBlocker::MissingConditionContext)
    }
}
