use crate::derived::{
    runtime_company_support_adjusted_share_price_scalar, runtime_round_f64_to_i64,
};
use crate::event::metrics::{
    RUNTIME_WORLD_ISSUE_CREDIT_MARKET, RUNTIME_WORLD_ISSUE_INVESTOR_CONFIDENCE,
    RUNTIME_WORLD_ISSUE_MANAGEMENT_ATTITUDE, RUNTIME_WORLD_ISSUE_PRIME_RATE,
    RuntimeWorldIssueState,
};
use crate::state::RuntimeState;

pub fn runtime_company_investor_confidence(state: &RuntimeState, company_id: u32) -> Option<i64> {
    let company = state
        .companies
        .iter()
        .find(|company| company.company_id == company_id)?;
    if company.investor_confidence != 0 {
        return Some(company.investor_confidence);
    }
    runtime_company_support_adjusted_share_price_scalar(state, company_id)
        .and_then(runtime_round_f64_to_i64)
}

pub fn runtime_company_management_attitude(state: &RuntimeState, company_id: u32) -> Option<i64> {
    let company = state
        .companies
        .iter()
        .find(|company| company.company_id == company_id)?;
    if company.management_attitude != 0 {
        return Some(company.management_attitude);
    }
    runtime_world_issue_opinion_term_sum_raw(
        state,
        RUNTIME_WORLD_ISSUE_MANAGEMENT_ATTITUDE,
        company.linked_chairman_profile_id,
        Some(company_id),
        None,
    )
}

pub fn runtime_world_issue_opinion_term_sum_raw(
    state: &RuntimeState,
    issue_id: u32,
    chairman_profile_id: Option<u32>,
    company_id: Option<u32>,
    territory_id: Option<u32>,
) -> Option<i64> {
    let mut total = i64::from(
        *state
            .service_state
            .world_issue_opinion_base_terms_raw_i32
            .get(issue_id as usize)?,
    );
    let mut resolved_company_id = company_id;
    if let Some(profile_id) = chairman_profile_id {
        if let Some(profile_terms) = state
            .service_state
            .chairman_issue_opinion_terms_raw_i32
            .get(&profile_id)
        {
            if let Some(value) = profile_terms.get(issue_id as usize) {
                total = total.checked_add(i64::from(*value))?;
            }
        }
        if resolved_company_id.is_none() {
            resolved_company_id = state
                .chairman_profiles
                .iter()
                .find(|profile| profile.profile_id == profile_id)
                .and_then(|profile| profile.linked_company_id);
        }
    }
    if let Some(company_id) = resolved_company_id {
        if let Some(company_terms) = state
            .service_state
            .company_market_state
            .get(&company_id)
            .map(|market_state| &market_state.issue_opinion_terms_raw_i32)
        {
            if let Some(value) = company_terms.get(issue_id as usize) {
                total = total.checked_add(i64::from(*value))?;
            }
        }
    }
    if territory_id.is_some() {
        return None;
    }
    Some(total)
}

pub fn runtime_world_issue_opinion_multiplier(
    state: &RuntimeState,
    issue_id: u32,
    chairman_profile_id: Option<u32>,
    company_id: Option<u32>,
    territory_id: Option<u32>,
) -> Option<f64> {
    let normalize = |raw: i32| (i64::from(raw.max(-99)) as f64) / 100.0 + 1.0;
    let base_raw = *state
        .service_state
        .world_issue_opinion_base_terms_raw_i32
        .get(issue_id as usize)?;
    let mut multiplier = normalize(base_raw);
    let mut resolved_company_id = company_id;
    if let Some(profile_id) = chairman_profile_id {
        if let Some(profile_terms) = state
            .service_state
            .chairman_issue_opinion_terms_raw_i32
            .get(&profile_id)
        {
            if let Some(value) = profile_terms.get(issue_id as usize) {
                multiplier *= normalize(*value);
            }
        }
        if resolved_company_id.is_none() {
            resolved_company_id = state
                .chairman_profiles
                .iter()
                .find(|profile| profile.profile_id == profile_id)
                .and_then(|profile| profile.linked_company_id);
        }
    }
    if let Some(company_id) = resolved_company_id {
        if let Some(company_terms) = state
            .service_state
            .company_market_state
            .get(&company_id)
            .map(|market_state| &market_state.issue_opinion_terms_raw_i32)
        {
            if let Some(value) = company_terms.get(issue_id as usize) {
                multiplier *= normalize(*value);
            }
        }
    }
    if territory_id.is_some() {
        return None;
    }
    Some(multiplier.max(0.01))
}

pub fn runtime_world_issue_state(
    state: &RuntimeState,
    issue_id: u32,
) -> Option<RuntimeWorldIssueState> {
    match issue_id {
        RUNTIME_WORLD_ISSUE_INVESTOR_CONFIDENCE => Some(RuntimeWorldIssueState {
            issue_id,
            raw_value_u32: state.world_restore.issue_37_value?,
            multiplier_raw_u32: state.world_restore.issue_37_multiplier_raw_u32,
            multiplier_value_f32_text: state
                .world_restore
                .issue_37_multiplier_value_f32_text
                .clone(),
        }),
        RUNTIME_WORLD_ISSUE_CREDIT_MARKET => Some(RuntimeWorldIssueState {
            issue_id,
            raw_value_u32: state.world_restore.issue_38_value?,
            multiplier_raw_u32: None,
            multiplier_value_f32_text: None,
        }),
        RUNTIME_WORLD_ISSUE_PRIME_RATE => Some(RuntimeWorldIssueState {
            issue_id,
            raw_value_u32: state.world_restore.issue_39_value?,
            multiplier_raw_u32: None,
            multiplier_value_f32_text: None,
        }),
        RUNTIME_WORLD_ISSUE_MANAGEMENT_ATTITUDE => Some(RuntimeWorldIssueState {
            issue_id,
            raw_value_u32: state.world_restore.issue_3a_value?,
            multiplier_raw_u32: None,
            multiplier_value_f32_text: None,
        }),
        _ => None,
    }
}

pub fn runtime_world_prime_rate_baseline(state: &RuntimeState) -> Option<f64> {
    let raw = state.world_restore.issue_37_value?;
    let value = f32::from_bits(raw) as f64;
    if !value.is_finite() {
        return None;
    }
    let scaled = (value + 0.001) * 100.0;
    if !scaled.is_finite() {
        return None;
    }
    Some(scaled.round() / 100.0)
}

pub fn runtime_company_prime_rate(state: &RuntimeState, company_id: u32) -> Option<i64> {
    let company = state
        .companies
        .iter()
        .find(|company| company.company_id == company_id)?;
    if let Some(prime_rate) = company.prime_rate {
        return Some(prime_rate);
    }
    let baseline = runtime_world_prime_rate_baseline(state)?;
    let raw_issue_sum = runtime_world_issue_opinion_term_sum_raw(
        state,
        RUNTIME_WORLD_ISSUE_PRIME_RATE,
        company.linked_chairman_profile_id,
        Some(company_id),
        None,
    )?;
    runtime_round_f64_to_i64(baseline + (raw_issue_sum as f64) * 0.01)
}
