use serde::{Deserialize, Serialize};

use crate::inspect::smp::common::{SmpSaveDwordCandidate, SmpSaveRegionProfileCollectionProbe};

#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct SmpSaveRegionRecordTripletEntryProbe {
    pub record_index: usize,
    pub name: String,
    pub record_payload_relative_offset: usize,
    pub record_payload_relative_offset_hex: String,
    pub name_tag_relative_offset: usize,
    pub policy_tag_relative_offset: usize,
    pub profile_tag_relative_offset: usize,
    pub pre_name_prefix_len: usize,
    #[serde(default)]
    pub pre_name_prefix_hex_bytes: Vec<String>,
    #[serde(default)]
    pub pre_name_prefix_dword_candidates: Vec<SmpSaveDwordCandidate>,
    pub policy_chunk_len: usize,
    pub profile_chunk_len: usize,
    pub policy_leading_f32_0: f32,
    pub policy_leading_f32_1: f32,
    pub policy_leading_f32_2: f32,
    #[serde(default)]
    pub policy_reserved_dwords: Vec<u32>,
    #[serde(default)]
    pub policy_reserved_dword_candidates: Vec<SmpSaveDwordCandidate>,
    pub policy_trailing_word: u16,
    pub policy_trailing_word_hex: String,
    #[serde(default)]
    pub profile_collection: Option<SmpSaveRegionProfileCollectionProbe>,
}

#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct SmpSaveRegionRecordTripletProbe {
    pub profile_family: String,
    pub source_kind: String,
    pub semantic_family: String,
    pub records_tag_offset: usize,
    pub close_tag_offset: usize,
    pub record_count: usize,
    #[serde(default)]
    pub entries: Vec<SmpSaveRegionRecordTripletEntryProbe>,
    pub evidence: Vec<String>,
}

#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct SmpLoadedRegionProfileEntry {
    pub entry_index: usize,
    pub name: String,
    pub trailing_weight_f32: f32,
}

#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct SmpLoadedRegionProfileCollection {
    pub direct_collection_flag: u32,
    pub entry_stride: u32,
    pub live_id_bound: u32,
    pub live_record_count: u32,
    pub trailing_padding_len: usize,
    #[serde(default)]
    pub entries: Vec<SmpLoadedRegionProfileEntry>,
}

#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct SmpLoadedRegionEntry {
    pub record_index: usize,
    pub name: String,
    pub pre_name_prefix_len: usize,
    pub policy_leading_f32_0: f32,
    pub policy_leading_f32_1: f32,
    pub policy_leading_f32_2: f32,
    #[serde(default)]
    pub policy_reserved_dwords: Vec<u32>,
    pub policy_trailing_word: u16,
    pub policy_trailing_word_hex: String,
    #[serde(default)]
    pub profile_collection: Option<SmpLoadedRegionProfileCollection>,
}

#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct SmpLoadedRegionCollection {
    pub source_kind: String,
    pub semantic_family: String,
    pub observed_entry_count: usize,
    #[serde(default)]
    pub entries: Vec<SmpLoadedRegionEntry>,
}

#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct SmpLoadedRegionFixedRowRunSummary {
    pub source_kind: String,
    pub semantic_family: String,
    pub target_row_count: usize,
    pub target_row_stride: usize,
    pub target_row_stride_hex: String,
    #[serde(default)]
    pub candidates: Vec<SmpSaveRegionFixedRowRunCandidate>,
}

#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct SmpSaveRegionQueuedNoticeRecordEntryProbe {
    pub node_base_offset: usize,
    pub payload_seed_offset: usize,
    pub next_link_raw: u32,
    pub next_link_raw_hex: String,
    pub payload_seed_dword: u32,
    pub payload_seed_dword_hex: String,
    pub kind: u32,
    pub kind_hex: String,
    pub promotion_latch_dword: u32,
    pub promotion_latch_dword_hex: String,
    pub region_id: u32,
    pub region_id_hex: String,
    pub amount: u32,
    pub amount_hex: String,
    pub trailing_sentinel_i32_0: i32,
    pub trailing_sentinel_i32_0_hex: String,
    pub trailing_sentinel_i32_1: i32,
    pub trailing_sentinel_i32_1_hex: String,
}

#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct SmpSaveRegionQueuedNoticeRecordProbe {
    pub profile_family: String,
    pub source_kind: String,
    pub semantic_family: String,
    pub payload_seed_dword: u32,
    pub payload_seed_dword_hex: String,
    #[serde(default)]
    pub entries: Vec<SmpSaveRegionQueuedNoticeRecordEntryProbe>,
    pub evidence: Vec<String>,
}

#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct SmpSaveFixedRowRunDwordLaneSummary {
    pub relative_offset: usize,
    pub relative_offset_hex: String,
    pub zero_count: usize,
    pub nonzero_count: usize,
    pub distinct_value_count: usize,
    pub probable_normal_f32_count: usize,
    pub small_unsigned_count: usize,
    #[serde(default)]
    pub sample_values_hex: Vec<String>,
}

#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct SmpSaveRegionFixedRowRunCandidate {
    pub count_offset: usize,
    pub count_offset_hex: String,
    pub row_count: usize,
    pub row_stride: usize,
    pub row_stride_hex: String,
    pub rows_offset: usize,
    pub rows_offset_hex: String,
    pub rows_end_offset: usize,
    pub rows_end_offset_hex: String,
    pub distance_to_region_metadata_tag: usize,
    pub distance_to_region_metadata_tag_hex: String,
    #[serde(default)]
    pub dword_lane_summaries: Vec<SmpSaveFixedRowRunDwordLaneSummary>,
    pub shape_signature: String,
    pub shape_family_signature: String,
    pub trailing_byte_zero_count: usize,
    pub trailing_byte_nonzero_count: usize,
    pub trailing_byte_distinct_value_count: usize,
    #[serde(default)]
    pub trailing_byte_sample_values_hex: Vec<String>,
    #[serde(default)]
    pub best_probable_density_lane_relative_offset_hex: Option<String>,
}

#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct SmpSaveRegionFixedRowRunCandidateProbe {
    pub profile_family: String,
    pub source_kind: String,
    pub semantic_family: String,
    pub target_row_count: usize,
    pub target_row_stride: usize,
    pub target_row_stride_hex: String,
    pub scan_start_offset: usize,
    pub scan_start_offset_hex: String,
    pub scan_end_offset: usize,
    pub scan_end_offset_hex: String,
    #[serde(default)]
    pub candidates: Vec<SmpSaveRegionFixedRowRunCandidate>,
    pub evidence: Vec<String>,
}

#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct SmpSaveRegionFixedRowRunSharedShapeMatch {
    pub shape_signature: String,
    pub left_rank: usize,
    pub left_rows_offset_hex: String,
    pub left_best_probable_density_lane_relative_offset_hex: Option<String>,
    pub right_rank: usize,
    pub right_rows_offset_hex: String,
    pub right_best_probable_density_lane_relative_offset_hex: Option<String>,
}

#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct SmpSaveRegionFixedRowRunComparisonReport {
    pub left_profile_family: String,
    pub right_profile_family: String,
    pub left_best_rows_offset_hex: Option<String>,
    pub right_best_rows_offset_hex: Option<String>,
    pub left_best_shape_signature: Option<String>,
    pub right_best_shape_signature: Option<String>,
    pub left_best_shape_family_signature: Option<String>,
    pub right_best_shape_family_signature: Option<String>,
    #[serde(default)]
    pub shared_shape_matches: Vec<SmpSaveRegionFixedRowRunSharedShapeMatch>,
    #[serde(default)]
    pub shared_shape_family_matches: Vec<SmpSaveRegionFixedRowRunSharedShapeMatch>,
    #[serde(default)]
    pub left_only_shape_signatures: Vec<String>,
    #[serde(default)]
    pub right_only_shape_signatures: Vec<String>,
    #[serde(default)]
    pub left_only_shape_family_signatures: Vec<String>,
    #[serde(default)]
    pub right_only_shape_family_signatures: Vec<String>,
    pub evidence: Vec<String>,
}
