use std::collections::{BTreeMap, BTreeSet};

use crate::derived::runtime_company_annual_finance_policy_state;
use crate::engine::command::ServiceEvent;
use crate::state::{RuntimeCompanyAnnualFinancePolicyAction, RuntimeState};

use super::{bankruptcy, bond_issue, dividend, news, stock_issue, stock_repurchase};

pub(crate) fn service_company_annual_finance_policy(
    state: &mut RuntimeState,
    service_events: &mut Vec<ServiceEvent>,
) -> Result<(), String> {
    let active_company_ids = state
        .companies
        .iter()
        .filter(|company| company.active)
        .map(|company| company.company_id)
        .collect::<Vec<_>>();
    let active_company_id_set = active_company_ids.iter().copied().collect::<BTreeSet<_>>();
    state
        .service_state
        .annual_finance_last_actions
        .retain(|company_id, _| active_company_id_set.contains(company_id));
    state
        .service_state
        .annual_finance_last_news_family_candidates
        .retain(|company_id, _| active_company_id_set.contains(company_id));
    state.service_state.annual_finance_last_news_events.clear();
    state.service_state.annual_finance_service_calls += 1;
    state.service_state.annual_bond_last_retired_principal_total = 0;
    state.service_state.annual_bond_last_issued_principal_total = 0;
    state.service_state.annual_stock_repurchase_last_share_count = 0;
    state.service_state.annual_stock_issue_last_share_count = 0;

    let mut mutated_company_ids = BTreeSet::new();
    let mut applied_effect_count = 0u32;
    let mut finance_news_family_candidates = BTreeMap::new();
    let mut annual_finance_news_events = Vec::new();

    for company_id in active_company_ids {
        let Some(policy_state) = runtime_company_annual_finance_policy_state(state, company_id)
        else {
            continue;
        };
        let action = policy_state.action;
        state
            .service_state
            .annual_finance_last_actions
            .insert(company_id, action);
        state
            .service_state
            .annual_finance_last_news_family_candidates
            .remove(&company_id);
        *state
            .service_state
            .annual_finance_action_counts
            .entry(action)
            .or_insert(0) += 1;

        let mutated = match action {
            RuntimeCompanyAnnualFinancePolicyAction::DividendAdjustment => {
                dividend::apply_dividend_adjustment(state, company_id)
            }
            RuntimeCompanyAnnualFinancePolicyAction::CreditorPressureBankruptcy
            | RuntimeCompanyAnnualFinancePolicyAction::DeepDistressBankruptcyFallback => {
                bankruptcy::apply_bankruptcy(state, company_id)
            }
            RuntimeCompanyAnnualFinancePolicyAction::StockIssue => {
                stock_issue::apply_stock_issue(state, company_id)
            }
            RuntimeCompanyAnnualFinancePolicyAction::BondIssue => {
                bond_issue::apply_bond_issue(state, company_id)
            }
            RuntimeCompanyAnnualFinancePolicyAction::StockRepurchase => {
                stock_repurchase::apply_stock_repurchase(state, company_id)
            }
            _ => false,
        };

        if !mutated {
            continue;
        }

        if matches!(
            action,
            RuntimeCompanyAnnualFinancePolicyAction::CreditorPressureBankruptcy
                | RuntimeCompanyAnnualFinancePolicyAction::DeepDistressBankruptcyFallback
                | RuntimeCompanyAnnualFinancePolicyAction::StockIssue
                | RuntimeCompanyAnnualFinancePolicyAction::BondIssue
                | RuntimeCompanyAnnualFinancePolicyAction::StockRepurchase
        ) {
            news::record_annual_finance_news(
                state,
                company_id,
                action,
                &mut finance_news_family_candidates,
                &mut annual_finance_news_events,
            );
        }

        applied_effect_count += 1;
        mutated_company_ids.insert(company_id);
    }

    service_events.push(ServiceEvent {
        kind: "annual_finance_policy".to_string(),
        trigger_kind: None,
        serviced_record_ids: Vec::new(),
        applied_effect_count,
        mutated_company_ids: mutated_company_ids.into_iter().collect(),
        mutated_player_ids: Vec::new(),
        appended_record_ids: Vec::new(),
        activated_record_ids: Vec::new(),
        deactivated_record_ids: Vec::new(),
        removed_record_ids: Vec::new(),
        finance_news_family_candidates,
        annual_finance_news_events,
        near_city_acquisition_news_family_candidates: BTreeMap::new(),
        near_city_acquisition_news_events: Vec::new(),
        dirty_rerun: false,
    });

    Ok(())
}
