use crate::inspect::smp::catalog::*;
use serde::Deserialize;
use std::collections::BTreeMap;
use std::sync::OnceLock;

#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub(in crate::inspect::smp) struct RealGroupedEffectDescriptorMetadata {
    pub(in crate::inspect::smp) descriptor_id: u32,
    pub(in crate::inspect::smp) label: &'static str,
    pub(in crate::inspect::smp) target_mask_bits: u8,
    pub(in crate::inspect::smp) parameter_family: &'static str,
    pub(in crate::inspect::smp) runtime_key: Option<&'static str>,
    pub(in crate::inspect::smp) runtime_status: RealGroupedEffectRuntimeStatus,
    pub(in crate::inspect::smp) executable_in_runtime: bool,
}

#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub(in crate::inspect::smp) enum RealGroupedEffectRuntimeStatus {
    Executable,
    ShellOwned,
    EvidenceBlocked,
    VariantOrScopeBlocked,
}

#[derive(Debug, Clone, PartialEq, Deserialize)]
pub(in crate::inspect::smp) struct CheckedInEventEffectsSemanticCatalogArtifact {
    pub(in crate::inspect::smp) descriptors: Vec<CheckedInEventEffectSemanticRow>,
}

#[derive(Debug, Clone, PartialEq, Deserialize)]
pub(in crate::inspect::smp) struct CheckedInEventEffectSemanticRow {
    pub(in crate::inspect::smp) descriptor_id: u32,
    pub(in crate::inspect::smp) label: String,
    pub(in crate::inspect::smp) target_mask_bits: u8,
    pub(in crate::inspect::smp) parameter_family: String,
    pub(in crate::inspect::smp) runtime_key: Option<String>,
    pub(in crate::inspect::smp) runtime_status: String,
    pub(in crate::inspect::smp) executable_in_runtime: bool,
}

pub(in crate::inspect::smp) const REAL_GROUPED_EFFECT_DESCRIPTOR_METADATA:
    [RealGroupedEffectDescriptorMetadata; 12] = [
    RealGroupedEffectDescriptorMetadata {
        descriptor_id: 1,
        label: "Player Cash",
        target_mask_bits: 0x02,
        parameter_family: "player_finance_scalar",
        runtime_key: None,
        runtime_status: RealGroupedEffectRuntimeStatus::Executable,
        executable_in_runtime: true,
    },
    RealGroupedEffectDescriptorMetadata {
        descriptor_id: 2,
        label: "Company Cash",
        target_mask_bits: 0x01,
        parameter_family: "company_finance_scalar",
        runtime_key: None,
        runtime_status: RealGroupedEffectRuntimeStatus::Executable,
        executable_in_runtime: true,
    },
    RealGroupedEffectDescriptorMetadata {
        descriptor_id: 3,
        label: "Territory - Allow All",
        target_mask_bits: 0x05,
        parameter_family: "territory_access_toggle",
        runtime_key: None,
        runtime_status: RealGroupedEffectRuntimeStatus::Executable,
        executable_in_runtime: true,
    },
    RealGroupedEffectDescriptorMetadata {
        descriptor_id: 8,
        label: "Economic Status",
        target_mask_bits: 0x08,
        parameter_family: "whole_game_state_enum",
        runtime_key: None,
        runtime_status: RealGroupedEffectRuntimeStatus::Executable,
        executable_in_runtime: true,
    },
    RealGroupedEffectDescriptorMetadata {
        descriptor_id: 108,
        label: "Use Wartime Cargos",
        target_mask_bits: 0x08,
        parameter_family: "special_condition_scalar",
        runtime_key: None,
        runtime_status: RealGroupedEffectRuntimeStatus::Executable,
        executable_in_runtime: true,
    },
    RealGroupedEffectDescriptorMetadata {
        descriptor_id: 109,
        label: "Turbo Diesel Availability",
        target_mask_bits: 0x08,
        parameter_family: "candidate_availability_scalar",
        runtime_key: None,
        runtime_status: RealGroupedEffectRuntimeStatus::Executable,
        executable_in_runtime: true,
    },
    RealGroupedEffectDescriptorMetadata {
        descriptor_id: 110,
        label: "Disable Stock Buying and Selling",
        target_mask_bits: 0x08,
        parameter_family: "world_flag_toggle",
        runtime_key: Some("world.disable_stock_buying_and_selling"),
        runtime_status: RealGroupedEffectRuntimeStatus::Executable,
        executable_in_runtime: true,
    },
    RealGroupedEffectDescriptorMetadata {
        descriptor_id: 9,
        label: "Confiscate All",
        target_mask_bits: 0x01,
        parameter_family: "company_confiscation_variant",
        runtime_key: None,
        runtime_status: RealGroupedEffectRuntimeStatus::Executable,
        executable_in_runtime: true,
    },
    RealGroupedEffectDescriptorMetadata {
        descriptor_id: 13,
        label: "Deactivate Company",
        target_mask_bits: 0x01,
        parameter_family: "company_lifecycle_toggle",
        runtime_key: None,
        runtime_status: RealGroupedEffectRuntimeStatus::Executable,
        executable_in_runtime: true,
    },
    RealGroupedEffectDescriptorMetadata {
        descriptor_id: 14,
        label: "Deactivate Player",
        target_mask_bits: 0x02,
        parameter_family: "player_lifecycle_toggle",
        runtime_key: None,
        runtime_status: RealGroupedEffectRuntimeStatus::Executable,
        executable_in_runtime: true,
    },
    RealGroupedEffectDescriptorMetadata {
        descriptor_id: 15,
        label: "Retire Train",
        target_mask_bits: 0x0d,
        parameter_family: "company_or_territory_asset_toggle",
        runtime_key: None,
        runtime_status: RealGroupedEffectRuntimeStatus::Executable,
        executable_in_runtime: true,
    },
    RealGroupedEffectDescriptorMetadata {
        descriptor_id: 16,
        label: "Company Track Pieces Buildable",
        target_mask_bits: 0x01,
        parameter_family: "company_build_limit_scalar",
        runtime_key: None,
        runtime_status: RealGroupedEffectRuntimeStatus::Executable,
        executable_in_runtime: true,
    },
];

pub(in crate::inspect::smp) fn real_grouped_effect_runtime_status_name(
    status: RealGroupedEffectRuntimeStatus,
) -> &'static str {
    match status {
        RealGroupedEffectRuntimeStatus::Executable => "executable",
        RealGroupedEffectRuntimeStatus::ShellOwned => "shell_owned",
        RealGroupedEffectRuntimeStatus::EvidenceBlocked => "evidence_blocked",
        RealGroupedEffectRuntimeStatus::VariantOrScopeBlocked => "variant_or_scope_blocked",
    }
}

pub(in crate::inspect::smp) fn checked_in_event_effect_descriptor_rows()
-> &'static BTreeMap<u32, RealGroupedEffectDescriptorMetadata> {
    static ROWS: OnceLock<BTreeMap<u32, RealGroupedEffectDescriptorMetadata>> = OnceLock::new();
    ROWS.get_or_init(|| {
        let artifact: CheckedInEventEffectsSemanticCatalogArtifact =
            serde_json::from_str(include_str!(
                "../../../../../../artifacts/exports/rt3-1.06/event-effects-semantic-catalog.json"
            ))
            .expect("checked-in event-effects semantic catalog should parse");
        artifact
            .descriptors
            .into_iter()
            .map(|row| {
                (
                    row.descriptor_id,
                    checked_in_event_effect_descriptor_metadata(row),
                )
            })
            .collect()
    })
}

pub(in crate::inspect::smp) fn checked_in_event_effect_descriptor_metadata(
    row: CheckedInEventEffectSemanticRow,
) -> RealGroupedEffectDescriptorMetadata {
    let label = Box::leak(row.label.clone().into_boxed_str()) as &'static str;
    let parameter_family = Box::leak(row.parameter_family.into_boxed_str()) as &'static str;
    let runtime_key = row
        .runtime_key
        .map(|key| Box::leak(key.into_boxed_str()) as &'static str);
    let runtime_status = match row.runtime_status.as_str() {
        "executable" => RealGroupedEffectRuntimeStatus::Executable,
        "shell_owned" => RealGroupedEffectRuntimeStatus::ShellOwned,
        "evidence_blocked" => RealGroupedEffectRuntimeStatus::EvidenceBlocked,
        "variant_or_scope_blocked" => RealGroupedEffectRuntimeStatus::VariantOrScopeBlocked,
        other => panic!("unknown checked-in event-effect runtime status {other}"),
    };
    RealGroupedEffectDescriptorMetadata {
        descriptor_id: row.descriptor_id,
        label,
        target_mask_bits: row.target_mask_bits,
        parameter_family,
        runtime_key,
        runtime_status,
        executable_in_runtime: row.executable_in_runtime,
    }
}

pub(crate) fn grouped_effect_descriptor_runtime_status_name(
    descriptor_id: u32,
) -> Option<&'static str> {
    real_grouped_effect_descriptor_metadata(descriptor_id)
        .map(|metadata| real_grouped_effect_runtime_status_name(metadata.runtime_status))
}
