use serde::{Deserialize, Serialize};

use crate::inspect::smp::bundle::{
    SmpContainerProfile, SmpRt3105PostSpanBridgeProbe, SmpRt3105SaveBridgePayloadProbe,
    SmpRuntimeAnchorCycleBlock, SmpRuntimePostSpanProbe, SmpRuntimeTrailerBlock,
    SmpSaveAnchorRunBlock, SmpSaveBootstrapBlock,
};
use crate::inspect::smp::common::{
    SmpAsciiPreview, SmpSaveTaggedCollectionHeaderProbe, SmpSaveTrainCollectionDirectoryProbe,
    SmpSaveUnclassifiedTaggedCollectionHeaderProbe,
};
use crate::inspect::smp::events::SmpLoadedEventRuntimeCollectionSummary;
use crate::inspect::smp::map_title::SmpMapTitleHintProbe;
use crate::inspect::smp::profiles::{
    SmpClassicRehydrateProfileProbe, SmpRt3105PackedProfileProbe, SmpRt3105SaveNameTableProbe,
    SmpRt3105SaveNamedLocomotiveAvailabilityProbe,
};
use crate::inspect::smp::regions::{
    SmpSaveRegionFixedRowRunCandidateProbe, SmpSaveRegionQueuedNoticeRecordProbe,
    SmpSaveRegionRecordTripletProbe,
};
use crate::inspect::smp::save_load::SmpSaveLoadSummary;
use crate::inspect::smp::special_conditions::{
    SmpAlignedRuntimeRuleBandProbe, SmpLocomotivePolicyNeighborhoodProbe,
    SmpPostSpecialConditionsScalarProbe, SmpPostTextFieldNeighborhoodProbe,
    SmpPreRecipeScalarPlateauProbe, SmpRecipeBookSummaryProbe, SmpSpecialConditionsProbe,
};
use crate::inspect::smp::structures::{
    SmpSavePlacedStructureDynamicSideBufferProbe, SmpSavePlacedStructureRecordTripletProbe,
};
use crate::inspect::smp::world::{
    SmpLoadedChairmanProfileTable, SmpLoadedCompanyRoster, SmpSaveWorldEconomicTuningProbe,
    SmpSaveWorldFinanceNeighborhoodProbe, SmpSaveWorldIssue37Probe,
    SmpSaveWorldSelectionContextProbe,
};

#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct SmpKnownTagHit {
    pub tag_id: u16,
    pub tag_hex: String,
    pub label: String,
    pub grounded_meaning: String,
    pub hit_count: usize,
    pub sample_offsets: Vec<usize>,
    pub last_offset: Option<usize>,
}

#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct SmpPreambleWord {
    pub index: usize,
    pub offset: usize,
    pub value_le: u32,
    pub value_hex: String,
}

#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct SmpPreamble {
    pub byte_len: usize,
    pub word_count: usize,
    pub words: Vec<SmpPreambleWord>,
}

#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]

pub struct SmpSharedHeader {
    pub byte_len: usize,
    pub root_kind_word: u32,
    pub root_kind_word_hex: String,
    pub primary_family_tag: u32,
    pub primary_family_tag_hex: String,
    pub shared_signature_words_1_to_7: Vec<u32>,
    pub shared_signature_hex_words_1_to_7: Vec<String>,
    pub matches_grounded_common_signature: bool,
    pub payload_window_words_8_to_9: Vec<u32>,
    pub payload_window_hex_words_8_to_9: Vec<String>,
    pub reserved_words_10_to_14: Vec<u32>,
    pub reserved_words_10_to_14_all_zero: bool,
    pub final_flag_word: u32,
    pub final_flag_word_hex: String,
}

#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct SmpHeaderVariantProbe {
    pub variant_family: String,
    pub variant_evidence: Vec<String>,
    pub is_known_family: bool,
}

#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct SmpEarlyContentProbe {
    pub first_post_text_nonzero_offset: usize,
    pub zero_pad_after_text_len: usize,
    pub first_post_text_block_len: usize,
    pub first_post_text_block_hex: String,
    pub trailing_zero_pad_after_first_block_len: usize,
    pub secondary_nonzero_offset: Option<usize>,
    pub secondary_aligned_word_window_offset: Option<usize>,
    pub secondary_aligned_word_window_words: Vec<u32>,
    pub secondary_aligned_word_window_hex_words: Vec<String>,
    pub secondary_preview_hex: String,
}

#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct SmpSecondaryVariantProbe {
    pub aligned_window_offset: usize,
    pub words: Vec<u32>,
    pub hex_words: Vec<String>,
    pub variant_family: String,
    pub variant_evidence: Vec<String>,
}

#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct SmpInspectionReport {
    pub inspection_mode: String,
    pub file_extension_hint: Option<String>,
    pub file_size: usize,
    pub sha256: String,
    pub preamble: SmpPreamble,
    pub shared_header: Option<SmpSharedHeader>,
    pub header_variant_probe: Option<SmpHeaderVariantProbe>,
    pub first_ascii_run: Option<SmpAsciiPreview>,
    pub early_content_probe: Option<SmpEarlyContentProbe>,
    pub secondary_variant_probe: Option<SmpSecondaryVariantProbe>,
    pub container_profile: Option<SmpContainerProfile>,
    pub save_bootstrap_block: Option<SmpSaveBootstrapBlock>,
    pub save_anchor_run_block: Option<SmpSaveAnchorRunBlock>,
    pub runtime_anchor_cycle_block: Option<SmpRuntimeAnchorCycleBlock>,
    pub runtime_trailer_block: Option<SmpRuntimeTrailerBlock>,
    pub runtime_post_span_probe: Option<SmpRuntimePostSpanProbe>,
    pub rt3_105_post_span_bridge_probe: Option<SmpRt3105PostSpanBridgeProbe>,
    pub rt3_105_save_bridge_payload_probe: Option<SmpRt3105SaveBridgePayloadProbe>,
    pub save_world_selection_context_probe: Option<SmpSaveWorldSelectionContextProbe>,
    pub save_world_issue_37_probe: Option<SmpSaveWorldIssue37Probe>,
    pub save_world_economic_tuning_probe: Option<SmpSaveWorldEconomicTuningProbe>,
    pub save_world_finance_neighborhood_probe: Option<SmpSaveWorldFinanceNeighborhoodProbe>,
    pub save_company_collection_header_probe: Option<SmpSaveTaggedCollectionHeaderProbe>,
    pub save_chairman_profile_collection_header_probe: Option<SmpSaveTaggedCollectionHeaderProbe>,
    pub save_train_collection_header_probe: Option<SmpSaveTaggedCollectionHeaderProbe>,
    pub save_train_collection_directory_probe: Option<SmpSaveTrainCollectionDirectoryProbe>,
    pub save_region_collection_header_probe: Option<SmpSaveTaggedCollectionHeaderProbe>,
    pub save_region_record_triplet_probe: Option<SmpSaveRegionRecordTripletProbe>,
    #[serde(default)]
    pub save_region_queued_notice_record_probe: Option<SmpSaveRegionQueuedNoticeRecordProbe>,
    #[serde(default)]
    pub save_region_fixed_row_run_candidate_probe: Option<SmpSaveRegionFixedRowRunCandidateProbe>,
    pub save_placed_structure_collection_header_probe: Option<SmpSaveTaggedCollectionHeaderProbe>,
    pub save_placed_structure_record_triplet_probe:
        Option<SmpSavePlacedStructureRecordTripletProbe>,
    #[serde(default)]
    pub save_placed_structure_dynamic_side_buffer_probe:
        Option<SmpSavePlacedStructureDynamicSideBufferProbe>,
    #[serde(default)]
    pub save_unclassified_tagged_collection_header_probes:
        Vec<SmpSaveUnclassifiedTaggedCollectionHeaderProbe>,
    #[serde(default)]
    pub save_company_roster_probe: Option<SmpLoadedCompanyRoster>,
    #[serde(default)]
    pub save_chairman_profile_table_probe: Option<SmpLoadedChairmanProfileTable>,
    #[serde(default)]
    pub map_title_hint_probe: Option<SmpMapTitleHintProbe>,
    pub rt3_105_save_name_table_probe: Option<SmpRt3105SaveNameTableProbe>,
    pub rt3_105_save_named_locomotive_availability_probe:
        Option<SmpRt3105SaveNamedLocomotiveAvailabilityProbe>,
    pub special_conditions_probe: Option<SmpSpecialConditionsProbe>,
    pub smp_aligned_runtime_rule_band_probe: Option<SmpAlignedRuntimeRuleBandProbe>,
    pub post_special_conditions_scalar_probe: Option<SmpPostSpecialConditionsScalarProbe>,
    pub post_text_field_neighborhood_probe: Option<SmpPostTextFieldNeighborhoodProbe>,
    pub locomotive_policy_neighborhood_probe: Option<SmpLocomotivePolicyNeighborhoodProbe>,
    pub pre_recipe_scalar_plateau_probe: Option<SmpPreRecipeScalarPlateauProbe>,
    pub recipe_book_summary_probe: Option<SmpRecipeBookSummaryProbe>,
    pub classic_rehydrate_profile_probe: Option<SmpClassicRehydrateProfileProbe>,
    pub rt3_105_packed_profile_probe: Option<SmpRt3105PackedProfileProbe>,
    pub save_load_summary: Option<SmpSaveLoadSummary>,
    pub event_runtime_collection_summary: Option<SmpLoadedEventRuntimeCollectionSummary>,
    pub contains_grounded_runtime_tags: bool,
    pub known_tag_hits: Vec<SmpKnownTagHit>,
    pub notes: Vec<String>,
    pub warnings: Vec<String>,
}
