use crate::derived::{
    runtime_company_annual_bond_policy_state, runtime_company_annual_creditor_pressure_state,
    runtime_company_annual_deep_distress_state, runtime_company_annual_finance_state,
    runtime_company_annual_stock_issue_state, runtime_company_annual_stock_repurchase_state,
    runtime_company_control_transfer_stat_value_f64,
    runtime_company_year_or_control_transfer_metric_value, runtime_decode_saved_f32_value,
    runtime_round_f64_to_i64, runtime_world_annual_finance_mode_active,
    runtime_world_building_density_growth_setting, runtime_world_dividend_adjustment_allowed,
};
use crate::event::metrics::RUNTIME_COMPANY_STAT_SLOT_CURRENT_CASH;
use crate::state::{RuntimeCompanyAnnualDividendPolicyState, RuntimeState};

pub(super) fn runtime_company_board_approved_dividend_rate_ceiling_f64(
    state: &RuntimeState,
    company_id: u32,
) -> Option<f64> {
    const REVENUE_GUARD_DIVISOR: f64 = 2.0;
    const EARLY_SUPPORT_MULTIPLIER: f64 = 0.05;
    const HISTORICAL_GUARD_SCALE: f64 = 1.25;
    const ANCHOR_SCALE: f64 = 0.35;

    let market_state = state.service_state.company_market_state.get(&company_id)?;
    let current_cash = runtime_company_control_transfer_stat_value_f64(
        state,
        company_id,
        RUNTIME_COMPANY_STAT_SLOT_CURRENT_CASH,
    )?;
    let shares_plus_one = market_state.outstanding_shares.checked_add(1)?;
    let shares_plus_one_f64 = shares_plus_one as f64;
    let current_cash_per_share_ceiling = current_cash / shares_plus_one_f64;
    let current_year_word = u32::from(state.world_restore.packed_year_word_raw_u16?);
    let years_since_founding = current_year_word
        .checked_sub(market_state.founding_year)
        .unwrap_or(0)
        .min(3);
    let start_year_offset = if state.world_restore.partial_year_progress_raw_u8 == Some(0x0c) {
        0
    } else {
        1
    };

    let mut strongest_net_profit_guard = 0.0f64;
    let mut strongest_revenue_guard = 0.0f64;
    if start_year_offset <= years_since_founding {
        for year_offset in start_year_offset..=years_since_founding {
            let year_word = current_year_word.checked_sub(year_offset)?;
            let net_profit = runtime_company_year_or_control_transfer_metric_value(
                state, company_id, year_word, 0x2b,
            )?;
            strongest_net_profit_guard = strongest_net_profit_guard.max(net_profit);

            let revenue = runtime_company_year_or_control_transfer_metric_value(
                state, company_id, year_word, 0x2c,
            )?;
            strongest_revenue_guard = strongest_revenue_guard.max(revenue);
        }
    }

    let mut historical_guard_total =
        strongest_net_profit_guard.min(strongest_revenue_guard / REVENUE_GUARD_DIVISOR);
    if years_since_founding <= 1 {
        let early_support_guard = market_state.outstanding_shares as f64
            * runtime_decode_saved_f32_value(market_state.young_company_support_scalar_raw_u32)?
            * EARLY_SUPPORT_MULTIPLIER;
        historical_guard_total = historical_guard_total.max(early_support_guard);
    }

    let historical_guard_per_share_ceiling =
        historical_guard_total / shares_plus_one_f64 * HISTORICAL_GUARD_SCALE;
    let mut ceiling = current_cash_per_share_ceiling.min(historical_guard_per_share_ceiling);
    let anchor_value = if years_since_founding == 0 {
        runtime_decode_saved_f32_value(market_state.young_company_support_scalar_raw_u32)?
    } else {
        runtime_company_year_or_control_transfer_metric_value(
            state,
            company_id,
            current_year_word.checked_sub(1)?,
            0x1c,
        )?
    };
    ceiling = ceiling.min(anchor_value * ANCHOR_SCALE);
    Some(ceiling.max(0.0))
}

pub fn runtime_company_annual_dividend_policy_state(
    state: &RuntimeState,
    company_id: u32,
) -> Option<RuntimeCompanyAnnualDividendPolicyState> {
    const WEIGHTED_NET_PROFIT_DIVISOR: f64 = 6.0;
    const CASH_SUPPLEMENT_DIVISOR: f64 = 3.0;
    const STANDARD_TARGET_DIVISOR: f64 = 6.0;
    const DIVIDEND_DELTA_COLLAPSE_THRESHOLD: f64 = 0.1;
    const GROWTH_SETTING_ONE_DIVIDEND_SCALE: f64 = 0.66;

    let annual_finance_state = runtime_company_annual_finance_state(state, company_id)?;
    let current_cash = runtime_company_control_transfer_stat_value_f64(
        state,
        company_id,
        RUNTIME_COMPANY_STAT_SLOT_CURRENT_CASH,
    )
    .and_then(runtime_round_f64_to_i64);
    let current_year_word = u32::from(state.world_restore.packed_year_word_raw_u16?);
    let current_dividend_per_share =
        runtime_company_control_transfer_stat_value_f64(state, company_id, 0x20)?;
    let building_density_growth_setting = runtime_world_building_density_growth_setting(state);
    let weighted_recent_net_profit_total = Some(
        runtime_company_year_or_control_transfer_metric_value(
            state,
            company_id,
            current_year_word,
            0x2b,
        )
        .and_then(runtime_round_f64_to_i64)?
        .checked_mul(3)?
        .checked_add(
            runtime_company_year_or_control_transfer_metric_value(
                state,
                company_id,
                current_year_word.checked_sub(1)?,
                0x2b,
            )
            .and_then(runtime_round_f64_to_i64)?
            .checked_mul(2)?,
        )?
        .checked_add(
            runtime_company_year_or_control_transfer_metric_value(
                state,
                company_id,
                current_year_word.checked_sub(2)?,
                0x2b,
            )
            .and_then(runtime_round_f64_to_i64)?,
        )?,
    );
    let weighted_recent_net_profit_average = weighted_recent_net_profit_total
        .and_then(|value| runtime_round_f64_to_i64(value as f64 / WEIGHTED_NET_PROFIT_DIVISOR));
    let tiny_unassigned_share_cash_supplement_branch =
        annual_finance_state.unassigned_share_pool <= 1_000;
    let tentative_target_dividend_per_share =
        weighted_recent_net_profit_average.and_then(|value| {
            if annual_finance_state.outstanding_shares == 0 {
                return None;
            }
            let shares = annual_finance_state.outstanding_shares as f64;
            if tiny_unassigned_share_cash_supplement_branch {
                let cash_component = current_cash.unwrap_or(0).max(0) as f64;
                Some(
                    ((value as f64 / CASH_SUPPLEMENT_DIVISOR)
                        + cash_component / CASH_SUPPLEMENT_DIVISOR)
                        / shares,
                )
            } else {
                Some((value as f64 / STANDARD_TARGET_DIVISOR) / shares)
            }
        });
    let growth_adjusted_current_dividend_per_share = Some(match building_density_growth_setting {
        Some(1) => current_dividend_per_share * GROWTH_SETTING_ONE_DIVIDEND_SCALE,
        Some(2) => 0.0,
        _ => current_dividend_per_share,
    });
    let proposed_dividend_per_share = if tentative_target_dividend_per_share
        .is_some_and(|value| value <= DIVIDEND_DELTA_COLLAPSE_THRESHOLD)
    {
        Some(0.0)
    } else {
        growth_adjusted_current_dividend_per_share
            .zip(tentative_target_dividend_per_share)
            .map(|(current_dividend, target)| {
                ((current_dividend + target + DIVIDEND_DELTA_COLLAPSE_THRESHOLD) / 2.0 * 10.0)
                    .round()
                    / 10.0
            })
    };
    let board_approved_dividend_rate_ceiling =
        runtime_company_board_approved_dividend_rate_ceiling_f64(state, company_id);
    let proposed_dividend_per_share = proposed_dividend_per_share
        .zip(board_approved_dividend_rate_ceiling)
        .map(|(proposed, ceiling)| proposed.min(ceiling));
    let current_dividend_per_share_tenths =
        runtime_round_f64_to_i64(current_dividend_per_share * 10.0);
    let eligible_for_dividend_adjustment_branch = runtime_world_annual_finance_mode_active(state)
        == Some(true)
        && runtime_world_dividend_adjustment_allowed(state) == Some(true)
        && annual_finance_state
            .years_since_last_dividend
            .is_some_and(|years| years >= 1)
        && annual_finance_state
            .years_since_founding
            .is_some_and(|years| years >= 2)
        && !runtime_company_annual_creditor_pressure_state(state, company_id)?
            .eligible_for_bankruptcy_branch
        && !runtime_company_annual_deep_distress_state(state, company_id)?
            .eligible_for_bankruptcy_fallback
        && !runtime_company_annual_bond_policy_state(state, company_id)?
            .eligible_for_bond_issue_branch
        && !runtime_company_annual_stock_repurchase_state(state, company_id)?
            .eligible_for_single_batch_repurchase
        && !runtime_company_annual_stock_issue_state(state, company_id)?
            .eligible_for_double_tranche_issue
        && proposed_dividend_per_share.and_then(|value| runtime_round_f64_to_i64(value * 10.0))
            != current_dividend_per_share_tenths;
    Some(RuntimeCompanyAnnualDividendPolicyState {
        company_id,
        annual_mode_active: runtime_world_annual_finance_mode_active(state),
        dividend_adjustment_allowed: runtime_world_dividend_adjustment_allowed(state),
        years_since_last_dividend: annual_finance_state.years_since_last_dividend,
        years_since_founding: annual_finance_state.years_since_founding,
        outstanding_shares: Some(annual_finance_state.outstanding_shares),
        unassigned_share_pool: Some(annual_finance_state.unassigned_share_pool),
        weighted_recent_net_profit_total,
        weighted_recent_net_profit_average,
        current_cash,
        tiny_unassigned_share_cash_supplement_branch,
        tentative_target_dividend_per_share_tenths: tentative_target_dividend_per_share
            .and_then(|value| runtime_round_f64_to_i64(value * 10.0)),
        current_dividend_per_share_tenths,
        building_density_growth_setting,
        growth_adjusted_current_dividend_per_share_tenths:
            growth_adjusted_current_dividend_per_share
                .and_then(|value| runtime_round_f64_to_i64(value * 10.0)),
        board_approved_dividend_rate_ceiling_tenths: board_approved_dividend_rate_ceiling
            .and_then(|value| runtime_round_f64_to_i64(value * 10.0)),
        proposed_dividend_per_share_tenths: proposed_dividend_per_share
            .and_then(|value| runtime_round_f64_to_i64(value * 10.0)),
        eligible_for_dividend_adjustment_branch,
    })
}
