use crate::inspect::smp::bundle::SmpInspectionReport;
use crate::inspect::smp::common::{
    SmpSaveTrainCollectionDirectoryProbe, SmpSaveUnclassifiedTaggedCollectionHeaderProbe,
};
use crate::inspect::smp::regions::{
    SmpSaveRegionFixedRowRunCandidateProbe, SmpSaveRegionQueuedNoticeRecordProbe,
    SmpSaveRegionRecordTripletProbe,
};
use crate::inspect::smp::structures::{
    SmpSavePlacedStructureDynamicSideBufferAlignmentProbe,
    SmpSavePlacedStructureDynamicSideBufferProbe, SmpSavePlacedStructureRecordTripletProbe,
};
use crate::inspect::smp::world::*;

pub(in crate::inspect::smp) struct SaveCompanyChairmanAnalysisNotesInputs<'a> {
    pub(super) report: &'a SmpInspectionReport,
    pub(super) world_selection_context: Option<&'a SmpSaveWorldSelectionRoleAnalysis>,
    pub(super) train_collection_directory: Option<&'a SmpSaveTrainCollectionDirectoryProbe>,
    pub(super) region_record_triplets: Option<&'a SmpSaveRegionRecordTripletProbe>,
    pub(super) region_queued_notice_records: Option<&'a SmpSaveRegionQueuedNoticeRecordProbe>,
    pub(super) region_fixed_row_run_candidates: Option<&'a SmpSaveRegionFixedRowRunCandidateProbe>,
    pub(super) placed_structure_record_triplets:
        Option<&'a SmpSavePlacedStructureRecordTripletProbe>,
    pub(super) placed_structure_dynamic_side_buffer:
        Option<&'a SmpSavePlacedStructureDynamicSideBufferProbe>,
    pub(super) placed_structure_dynamic_side_buffer_alignment:
        Option<&'a SmpSavePlacedStructureDynamicSideBufferAlignmentProbe>,
    pub(super) unclassified_tagged_collection_headers:
        &'a [SmpSaveUnclassifiedTaggedCollectionHeaderProbe],
    pub(super) company_entries: &'a [SmpSaveCompanyRecordAnalysisEntry],
    pub(super) chairman_entries: &'a [SmpSaveChairmanRecordAnalysisEntry],
}

pub(in crate::inspect::smp) fn build_save_company_chairman_analysis_notes(
    inputs: SaveCompanyChairmanAnalysisNotesInputs<'_>,
) -> Vec<String> {
    let mut notes = Vec::new();
    if inputs.world_selection_context.is_some() {
        notes.push(
            "World selection context now exports the grounded chairman-slot selector bytes and per-slot role-gate bytes from the fixed save-side 0x32c8 world block.".to_string(),
        );
    }
    if inputs.report.save_world_issue_37_probe.is_some() {
        notes.push(
            "World analysis now also exports the grounded issue-0x37 pair from the same 0x32c8 world payload: the clamped small issue value at [world+0x2d] and its companion multiplier lane at [world+0x29].".to_string(),
        );
    }
    if inputs.report.save_world_economic_tuning_probe.is_some() {
        notes.push(
            "World analysis now also exports the fixed six-lane economic tuning float block from the same 0x32c8 world payload; current atlas evidence still treats that band as distinct from the issue-0x37 investor-confidence family.".to_string(),
        );
    }
    if inputs
        .report
        .save_world_finance_neighborhood_probe
        .is_some()
    {
        notes.push(
            "World analysis now also exports one fixed dword finance neighborhood around the grounded issue/calendar lanes, so future issue-0x38/0x39 closure can build on rehosted owner-state candidates instead of ad hoc byte guesses.".to_string(),
        );
    }
    if let Some(header) = inputs.report.save_train_collection_header_probe.as_ref() {
        notes.push(format!(
            "Train analysis now also exports the tagged train collection header: live_record_count={} live_id_bound={} direct_record_stride=0x{:x}.",
            header.live_record_count, header.live_id_bound, header.direct_record_stride
        ));
    }
    if let Some(directory) = inputs.train_collection_directory {
        notes.push(format!(
            "Train analysis now also exports the tagged live-entry directory rooted at metadata dword {}: {} entries chained from {:?} to {:?}.",
            directory.directory_root_dword_index,
            directory.entries.len(),
            directory.chain_head_live_entry_id,
            directory.chain_tail_live_entry_id
        ));
    }
    if let Some(header) = inputs.report.save_region_collection_header_probe.as_ref() {
        notes.push(format!(
            "Region analysis now also exports the non-direct tagged region collection header: live_record_count={} live_id_bound={} serialized_stride_hint=0x{:x}.",
            header.live_record_count, header.live_id_bound, header.direct_record_stride
        ));
    }
    if let Some(triplets) = inputs.region_record_triplets {
        notes.push(format!(
            "Region analysis now also exports {} tagged 0x55f1/0x55f2/0x55f3 record triplets; first serialized region name={:?}, first policy lanes=({:.3}, {:.3}, {:.3}), first profile collection count={:?}, first profile collection trailing_padding_len={:?}.",
            triplets.record_count,
            triplets.entries.first().map(|entry| entry.name.as_str()),
            triplets.entries.first().map(|entry| entry.policy_leading_f32_0).unwrap_or_default(),
            triplets.entries.first().map(|entry| entry.policy_leading_f32_1).unwrap_or_default(),
            triplets.entries.first().map(|entry| entry.policy_leading_f32_2).unwrap_or_default(),
            triplets.entries.first().and_then(|entry| entry.profile_collection.as_ref().map(|collection| collection.live_record_count)),
            triplets.entries.first().and_then(|entry| entry.profile_collection.as_ref().map(|collection| collection.trailing_padding_len))
        ));
    }
    if let Some(queue_probe) = inputs.region_queued_notice_records {
        notes.push(format!(
            "Region analysis now also exports {} queued kind-7 notice nodes with payload seed {}: first region id={} amount={} promotion={} tails={}/{}.",
            queue_probe.entries.len(),
            queue_probe.payload_seed_dword_hex,
            queue_probe.entries[0].region_id,
            queue_probe.entries[0].amount,
            queue_probe.entries[0].promotion_latch_dword_hex,
            queue_probe.entries[0].trailing_sentinel_i32_0_hex,
            queue_probe.entries[0].trailing_sentinel_i32_1_hex
        ));
    }
    if let Some(fixed_row_candidates) = inputs.region_fixed_row_run_candidates {
        notes.push(format!(
            "Region analysis now also exports {} fixed-row run candidates keyed to live_record_count={} and stride {} before the tagged region metadata; best candidate rows offset is {:?} with shape signature {:?}.",
            fixed_row_candidates.candidates.len(),
            fixed_row_candidates.target_row_count,
            fixed_row_candidates.target_row_stride_hex,
            fixed_row_candidates.candidates.first().map(|candidate| candidate.rows_offset_hex.as_str()),
            fixed_row_candidates.candidates.first().map(|candidate| candidate.shape_signature.as_str())
        ));
    }
    if let Some(header) = inputs
        .report
        .save_placed_structure_collection_header_probe
        .as_ref()
    {
        notes.push(format!(
            "Placed-structure analysis now also exports the tagged collection header: live_record_count={} live_id_bound={} serialized_stride_hint=0x{:x}.",
            header.live_record_count, header.live_id_bound, header.direct_record_stride
        ));
    }
    if let Some(triplets) = inputs.placed_structure_record_triplets {
        notes.push(format!(
            "Placed-structure analysis now also exports {} tagged 0x55f1/0x55f2/0x55f3 record triplets; first stems={:?}/{:?}, first footer payload={}, first footer status kind={:?}.",
            triplets.record_count,
            triplets.entries.first().map(|entry| entry.primary_name.as_str()),
            triplets.entries.first().map(|entry| entry.secondary_name.as_str()),
            triplets.entries.first().map(|entry| entry.profile_payload_dword_hex.as_str()).unwrap_or("0x00000000"),
            triplets.entries.first().map(|entry| entry.profile_status_kind.as_str())
        ));
    }
    if let Some(side_buffer) = inputs.placed_structure_dynamic_side_buffer {
        let dominant_pattern = side_buffer.compact_prefix_pattern_summaries.first();
        let payload_envelope_summary = side_buffer.payload_envelope_summary.as_ref();
        let short_profile_flag_pair_summary = payload_envelope_summary
            .and_then(|summary| summary.short_profile_flag_pair_summary.as_ref());
        notes.push(format!(
            "Placed-structure analysis now also exports the separate 0x38a5 dynamic side-buffer owner seam with {} embedded name rows, {} decoded rows across {} unique name pairs, {} rows with a tertiary 0x55f1 string, {} unique compact prefix patterns, {} rows whose leading dword matches 0x55f3, {} complete 0x55f1/0x55f2/0x55f3 envelopes, dominant 0x55f2 chunk len=0x{:x} x{}, dominant 0x55f3 span=0x{:x} x{}, dominant short 0x55f3 flag pair={}/{} x{}, and dominant compact pattern={}/{}/{} x{}.",
            side_buffer.embedded_name_tag_count,
            side_buffer.decoded_embedded_name_row_count,
            side_buffer.unique_embedded_name_pair_count,
            side_buffer.decoded_embedded_name_row_with_tertiary_name_count,
            side_buffer.unique_compact_prefix_pattern_count,
            side_buffer.prefix_leading_dword_matching_embedded_profile_tag_count,
            payload_envelope_summary.map(|summary| summary.row_count_with_complete_0x55f1_0x55f2_0x55f3_envelope).unwrap_or_default(),
            payload_envelope_summary.and_then(|summary| summary.dominant_policy_chunk_len).unwrap_or_default(),
            payload_envelope_summary.map(|summary| summary.dominant_policy_chunk_len_count).unwrap_or_default(),
            payload_envelope_summary.and_then(|summary| summary.dominant_profile_chunk_len).unwrap_or_default(),
            payload_envelope_summary.map(|summary| summary.dominant_profile_chunk_len_count).unwrap_or_default(),
            short_profile_flag_pair_summary.and_then(|summary| summary.dominant_flag_pair.as_ref()).map(|pair| pair.first_flag_byte_hex.as_str()).unwrap_or("0x00"),
            short_profile_flag_pair_summary.and_then(|summary| summary.dominant_flag_pair.as_ref()).map(|pair| pair.second_flag_byte_hex.as_str()).unwrap_or("0x00"),
            short_profile_flag_pair_summary.and_then(|summary| summary.dominant_flag_pair.as_ref()).map(|pair| pair.count).unwrap_or_default(),
            dominant_pattern.map(|pattern| pattern.prefix_leading_dword_hex.as_str()).unwrap_or("0x00000000"),
            dominant_pattern.map(|pattern| pattern.prefix_trailing_word_hex.as_str()).unwrap_or("0x0000"),
            dominant_pattern.map(|pattern| pattern.prefix_separator_byte_hex.as_str()).unwrap_or("0x00"),
            dominant_pattern.map(|pattern| pattern.count).unwrap_or_default()
        ));
    }
    if let Some(alignment) = inputs.placed_structure_dynamic_side_buffer_alignment {
        notes.push(format!(
            "Placed-structure analysis now also compares the 0x38a5 side-buffer against the grounded 0x36b1 triplet corpus: {} of {} decoded side-buffer rows reuse {} overlapping placed-structure name pairs, leaving {} unmatched side-buffer rows and {} triplet-only name pairs.",
            alignment.side_buffer_rows_with_matching_triplet_name_pair_count,
            alignment.side_buffer_row_count,
            alignment.overlapping_name_pair_count,
            alignment.side_buffer_rows_without_matching_triplet_name_pair_count,
            alignment.triplet_name_pairs_without_side_buffer_match_count
        ));
    }
    if let Some(candidate) = inputs.unclassified_tagged_collection_headers.first() {
        notes.push(format!(
            "Generic save-side tagged collection scan also found {} unclassified candidate families; largest current candidate uses tags {}/{}/{} with live_record_count={} stride=0x{:x} records_span_len=0x{:x}.",
            inputs.unclassified_tagged_collection_headers.len(),
            candidate.metadata_tag_hex,
            candidate.records_tag_hex,
            candidate.close_tag_hex,
            candidate.live_record_count,
            candidate.direct_record_stride,
            candidate.records_span_len
        ));
    }
    if !inputs.company_entries.is_empty() {
        notes.push("Company debt is derived from the grounded bond table at [company+0x5b/+0x5f] by summing live principal slots.".to_string());
        notes.push("Company available_track_laying_capacity is derived from the grounded tail dword [company+0x7680], with negative values treated as the unlimited sentinel.".to_string());
        notes.push("Company scalar_dword_candidates expose the current checked-in raw save windows around support/share-price/calendar lanes, and post_capacity_dword_candidates expose the immediate dwords after [company+0x7680] for deeper track-count and record-tail analysis.".to_string());
        notes.push("Company stat-band root candidates now also expose the first dword windows rooted at [company+0x0cfb], [company+0x0d7f], and [company+0x1c47], the same broader stat bands the grounded cheat reset branch clears before later finance/detail readers rebuild them.".to_string());
        notes.push("Current atlas evidence ties company current_cash and book_value_per_share to stat-family 0x2329 slots 0x0d and 0x1d, so the remaining save-native company finance/governance closure likely needs a structured company-stat family reconstruction instead of more isolated raw offsets.".to_string());
    }
    if !inputs.chairman_entries.is_empty() {
        notes.push("Chairman cached_scalar_candidates expose the adjacent qword band rooted at [profile+0x1e9], now including raw qword hex and signed/f64 views for further purchasing-power analysis.".to_string());
        notes.push("Chairman analysis now also derives one holdings-at-cached-share-price total from the grounded company cached_share_price lane and one strongest-cached purchasing-power total from the nonnegative qword cache band.".to_string());
    }
    notes
}
