use super::super::super::*;
use super::super::embedded_names::EmbeddedNameRow;
use super::super::payload_envelope::PayloadEnvelopeRow;
use super::candidate_rows::build_name_prelude_candidate_rows;
use super::correlations::{
    build_candidate_pattern_correlations, build_compact_prefix_correlations,
    build_profile_span_correlations,
};
use std::collections::BTreeMap;

pub(in crate::inspect::smp) fn build_name_prelude_candidate_summary(
    records_payload: &[u8],
    payload_envelope_rows: &[PayloadEnvelopeRow],
    embedded_name_rows: &[EmbeddedNameRow],
) -> Option<SmpSavePlacedStructureDynamicSideBufferNamePreludeCandidateSummary> {
    let name_prelude_candidate_rows = build_name_prelude_candidate_rows(
        records_payload,
        payload_envelope_rows,
        embedded_name_rows,
    );
    let mut name_prelude_candidate_pattern_counts = BTreeMap::<(u16, u8), usize>::new();
    let mut name_prelude_child_count_counts = BTreeMap::<u16, usize>::new();
    let mut name_prelude_saved_primary_counts = BTreeMap::<u8, usize>::new();
    for (_, _, _, _, _, _, child_count_candidate, saved_primary_child_byte_candidate, _, _) in
        &name_prelude_candidate_rows
    {
        *name_prelude_candidate_pattern_counts
            .entry((*child_count_candidate, *saved_primary_child_byte_candidate))
            .or_default() += 1;
        *name_prelude_child_count_counts
            .entry(*child_count_candidate)
            .or_default() += 1;
        *name_prelude_saved_primary_counts
            .entry(*saved_primary_child_byte_candidate)
            .or_default() += 1;
    }
    let dominant_name_prelude_candidate_pattern = name_prelude_candidate_pattern_counts
        .iter()
        .max_by(|(left_key, left_count), (right_key, right_count)| {
            left_count
                .cmp(right_count)
                .then_with(|| right_key.cmp(left_key))
        })
        .map(
            |((child_count_candidate, saved_primary_child_byte_candidate), count)| {
                SmpSavePlacedStructureDynamicSideBufferNamePreludeCandidatePattern {
                    child_count_candidate: *child_count_candidate,
                    child_count_candidate_hex: format!("0x{child_count_candidate:04x}"),
                    saved_primary_child_byte_candidate: *saved_primary_child_byte_candidate,
                    saved_primary_child_byte_candidate_hex: format!(
                        "0x{saved_primary_child_byte_candidate:02x}"
                    ),
                    count: *count,
                }
            },
        );
    let dominant_name_prelude_child_count = name_prelude_child_count_counts
        .iter()
        .max_by(|(left_key, left_count), (right_key, right_count)| {
            left_count
                .cmp(right_count)
                .then_with(|| right_key.cmp(left_key))
        })
        .map(|(value, count)| (*value, *count));
    let dominant_name_prelude_saved_primary = name_prelude_saved_primary_counts
        .iter()
        .max_by(|(left_key, left_count), (right_key, right_count)| {
            left_count
                .cmp(right_count)
                .then_with(|| right_key.cmp(left_key))
        })
        .map(|(value, count)| (*value, *count));

    Some(
        SmpSavePlacedStructureDynamicSideBufferNamePreludeCandidateSummary {
            row_count_with_candidate_window: name_prelude_candidate_rows.len(),
            unique_candidate_pattern_count: name_prelude_candidate_pattern_counts.len(),
            dominant_child_count_candidate: dominant_name_prelude_child_count
                .map(|(value, _)| value),
            dominant_child_count_candidate_count: dominant_name_prelude_child_count
                .map(|(_, count)| count)
                .unwrap_or_default(),
            dominant_saved_primary_child_byte_candidate: dominant_name_prelude_saved_primary
                .map(|(value, _)| value),
            dominant_saved_primary_child_byte_candidate_hex: dominant_name_prelude_saved_primary
                .map(|(value, _)| format!("0x{value:02x}")),
            dominant_saved_primary_child_byte_candidate_count: dominant_name_prelude_saved_primary
                .map(|(_, count)| count)
                .unwrap_or_default(),
            dominant_candidate_pattern: dominant_name_prelude_candidate_pattern.clone(),
            candidate_pattern_correlations: build_candidate_pattern_correlations(
                &name_prelude_candidate_rows,
            ),
            profile_span_correlations: build_profile_span_correlations(
                &name_prelude_candidate_rows,
            ),
            compact_prefix_correlations: build_compact_prefix_correlations(
                &name_prelude_candidate_rows,
            ),
            sample_rows: name_prelude_candidate_rows
                .iter()
                .take(8)
                .enumerate()
                .map(
                    |(
                        sample_index,
                        (
                            name_tag_relative_offset,
                            primary_name,
                            secondary_name,
                            _,
                            _,
                            _,
                            child_count_candidate,
                            saved_primary_child_byte_candidate,
                            previous_profile_chunk_len_to_next_name_or_end,
                            _,
                        ),
                    )| {
                        SmpSavePlacedStructureDynamicSideBufferNamePreludeCandidateSample {
                            sample_index,
                            name_tag_relative_offset: *name_tag_relative_offset,
                            primary_name: primary_name.clone(),
                            secondary_name: secondary_name.clone(),
                            child_count_candidate: *child_count_candidate,
                            child_count_candidate_hex: format!("0x{child_count_candidate:04x}"),
                            saved_primary_child_byte_candidate: *saved_primary_child_byte_candidate,
                            saved_primary_child_byte_candidate_hex: format!(
                                "0x{saved_primary_child_byte_candidate:02x}"
                            ),
                            previous_profile_chunk_len_to_next_name_or_end:
                                *previous_profile_chunk_len_to_next_name_or_end,
                        }
                    },
                )
                .collect(),
        },
    )
}
