//
// framecpp_verify_descriptions - Validate frame file descriptions against program definitions
//
// Copyright (C) 2025 California Institute of Technology
//
// LDASTools frameCPP is free software; you may redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 (GPLv2) of the
// License or at your discretion, any later version.
//

#include <iostream>
#include <memory>
#include <map>
#include <set>
#include <algorithm>
#include <iomanip>

#include <boost/program_options.hpp>

#include "framecpp/FrameCPP.hh"
#include "framecpp/FrameCPPDebugManager.hh"
#include "framecpp/Common/SequentialFrameReader.hh"
#include "framecpp/Common/Description.hh"
#include "framecpp/Common/FrameCPPServices.hh"
#include "framecpp/FrSH.hh"
#include "framecpp/FrSE.hh"

// Frame objects for GetDescription()
#include "framecpp/FrAdcData.hh"
#include "framecpp/FrProcData.hh"
#include "framecpp/FrSimData.hh"
#include "framecpp/FrSerData.hh"
#include "framecpp/FrRawData.hh"
#include "framecpp/FrStatData.hh"
#include "framecpp/FrSummary.hh"
#include "framecpp/FrTable.hh"
#include "framecpp/FrVect.hh"
#include "framecpp/FrameH.hh"
#include "framecpp/FrDetector.hh"
#include "framecpp/FrEvent.hh"
#include "framecpp/FrSimEvent.hh"
#include "framecpp/FrHistory.hh"

#include "ldastoolsal/LoggerManager.hh"

using namespace FrameCPP;
namespace po = boost::program_options;

/// \brief Description verification results
struct ValidationResult {
    bool is_valid = true;
    std::string structure_name;
    size_t file_object_count = 0;
    size_t program_object_count = 0;
    std::vector<std::string> errors;
    std::vector<std::string> warnings;
};

/// \brief Description verifier using SequentialFrameReader
class DescriptionVerifier {
private:
    Common::SequentialFrameReader m_reader;
    const Common::FrameCPPServices& m_services;
    
    // State management
    enum class State { IDLE, COLLECTING };
    State m_state = State::IDLE;
    std::unique_ptr<Common::Description> m_current_description;
    std::string m_current_structure_name;
    int m_verbose_level = 0;
    
    // Statistics
    size_t m_structures_verified = 0;
    size_t m_verification_failures = 0;
    size_t m_unknown_structures = 0;

public:
    DescriptionVerifier(const std::string& filename,
                       const Common::FrameCPPServices& services)
        : m_reader(filename, services),
          m_services(services) {
        // Enable optimized mode - only read FrSH and FrSE
        m_reader.setMode(Common::SequentialFrameReader::Mode::DESCRIPTION_ONLY);
        
        // Set callback to handle failed FrSH objects
        m_reader.setFrSHStateCallback([this](bool failed) {
            handleFrSHStateTransition(failed);
        });
    }
    
    /// \brief Set verbose level for detailed output
    /// \param level 0=none, 1=failures only, 2=successes, 3+=detailed comparison
    void setVerboseLevel(int level) { m_verbose_level = level; }
    
    /// \brief Get failure count for exit code
    size_t getFailureCount() const { return m_verification_failures; }
    
    /// \brief Run verification on the frame file
    void verifyAllDescriptions() {
        // SequentialFrameReader now handles initialization automatically
        // in readNextObject() when first called
        
        // Log frame information
        auto header = m_reader.getFrameHeader();
        if (header) {
            logger_log_debug(logger(), 20,
                          "Processing frame file with version: ", 
                          header->GetVersion());
        }
        
        // Process all objects (only FrSH/FrSE due to filtering)
        m_reader.processAllObjects([this](auto obj) {
            return processObject(obj);
        });
        
        // Handle any pending description
        if (m_state == State::COLLECTING) {
            verifyCurrentDescription();
        }
        
        // Report final summary
        reportSummary();
    }
    
    /// \brief Get verification statistics
    size_t getStructuresVerified() const { return m_structures_verified; }
    size_t getUnknownCount() const { return m_unknown_structures; }
    
private:
    bool processObject(boost::shared_ptr<Common::FrameSpec::Object> obj) {
        // FrSH - start new description collection
        if (auto* frsh = dynamic_cast<Universal::FrSH*>(obj.get())) {
            // Complete any pending description
            if (m_state == State::COLLECTING) {
                verifyCurrentDescription();
            }
            
            startCollection(obj, frsh->GetName());
            return true;
        }
        
        // FrSE - add to current collection
        if (auto* frse = dynamic_cast<Universal::FrSE*>(obj.get())) {
            if (m_state == State::COLLECTING && m_current_description) {
                // DIAGNOSTIC: Detailed FrSE association tracking
                size_t objects_before = m_current_description->size();
                (*m_current_description)(obj);
                size_t objects_after = m_current_description->size();
                
                logger_log_debug(logger(), 10,
                               "ASSOCIATION: Adding FrSE '", frse->GetName(),
                               "' to structure '", m_current_structure_name, "'",
                               " (Description: ", objects_before, " -> ", objects_after, " objects)");
                
                logger_log_debug(logger(), 40, 
                               "Added FrSE '", frse->GetName(), 
                               "' to description for ", m_current_structure_name);
            } else {
                // DIAGNOSTIC: Track orphaned FrSE objects
                logger_log_warning(logger(),
                                 "ORPHANED FrSE: Found FrSE '", frse->GetName(),
                                 "' but not in COLLECTING state or no current description",
                                 " (state=", (m_state == State::COLLECTING ? "COLLECTING" : "IDLE"),
                                 ", has_description=", (m_current_description ? "YES" : "NO"), ")");
            }
            return true;
        }
        
        // Should not reach here in DESCRIPTION_ONLY mode, but handle gracefully
        logger_log_warning(logger(), 
                         "Unexpected object type in description-only mode");
        return true;
    }
    
    void handleFrSHStateTransition(bool failed) {
        // CRITICAL FIX: Handle state transition when FrSH is encountered
        // This is called even when FrSH fails to deserialize
        
        if (failed) {
            logger_log_warning(logger(),
                             "FAILED FrSH DETECTED: Resetting collection state to prevent FrSE accumulation");
            
            // Complete any pending description before resetting
            if (m_state == State::COLLECTING) {
                logger_log_debug(logger(), 10,
                               "STATE RESET DUE TO FAILED FrSH: Completing structure '",
                               m_current_structure_name, "' before reset");
                verifyCurrentDescription();
            }
            
            // Reset to IDLE to prevent orphaned FrSE objects from being collected
            m_state = State::IDLE;
            m_current_description.reset();
            m_current_structure_name.clear();
        }
    }
    
    void startCollection(boost::shared_ptr<Common::FrameSpec::Object> frsh_obj,
                        const std::string& name) {
        // DIAGNOSTIC: State transition monitoring
        logger_log_debug(logger(), 10,
                       "STATE TRANSITION: Starting collection for '", name, "'",
                       ", previous_state=", (m_state == State::COLLECTING ? "COLLECTING" : "IDLE"),
                       ", previous_structure='", m_current_structure_name, "'");
        
        m_current_description = std::make_unique<Common::Description>();
        (*m_current_description)(frsh_obj);
        m_current_structure_name = name;
        m_state = State::COLLECTING;
        
        logger_log_debug(logger(), 20, "Collecting description for structure: ", name);
        logger_log_debug(logger(), 10,
                       "STATE SET: Now collecting for '", name, "', Description has ", 
                       m_current_description->size(), " objects (FrSH added)");
    }
    
    void verifyCurrentDescription() {
        if (!m_current_description) return;
        
        // DIAGNOSTIC: Verification process tracking
        logger_log_debug(logger(), 10,
                       "VERIFICATION START: Processing structure '", m_current_structure_name,
                       "' with ", m_current_description->size(), " objects");
        
        // DIAGNOSTIC: Log Description contents before verification
        if (logger()) {
            logger_log_debug(logger(), 15, "DESCRIPTION CONTENTS for '", m_current_structure_name, "':");
            size_t obj_count = 0;
            for (const auto& element : *m_current_description) {
                if (auto* frsh = dynamic_cast<const Universal::FrSH*>(element.get())) {
                    logger_log_debug(logger(), 15, "  [", obj_count, "] FrSH: '", frsh->GetName(), "'");
                } else if (auto* frse = dynamic_cast<const Universal::FrSE*>(element.get())) {
                    logger_log_debug(logger(), 15, "  [", obj_count, "] FrSE: '", frse->GetName(), "'");
                } else {
                    logger_log_debug(logger(), 15, "  [", obj_count, "] Unknown object type");
                }
                obj_count++;
            }
        }
        
        logger_log_debug(logger(), 20,
                       "Verifying structure: ", m_current_structure_name,
                       " with ", m_current_description->size(), " objects");
        
        // Get program description using stream version
        unsigned int version = m_reader.Version();
        const Common::Description* prog_desc = getProgramDescription(m_current_structure_name, version);
        
        if (!prog_desc) {
            logger_log_warning(logger(), 
                             "Unknown structure: ", m_current_structure_name,
                             " - no program definition found");
            m_unknown_structures++;
        } else {
            // Log description summary before comparison
            logger_log_debug(logger(), 25,
                           "COMPARISON: File has " + std::to_string(m_current_description->size()) + 
                           " objects, Program has " + std::to_string(prog_desc->size()) + " objects");
            
            // Compare descriptions
            ValidationResult result = compareDescriptions(*m_current_description, *prog_desc);
            
            if (result.is_valid) {
                logger_log_debug(logger(), 10,
                               "VALIDATION PASSED: ", m_current_structure_name,
                               " (", result.file_object_count, " objects)");
                
                // Show success information based on verbose level
                if (m_verbose_level >= 2) {
                    std::cout << "\nVALIDATION PASSED: " << m_current_structure_name 
                              << " (" << result.file_object_count << " objects match perfectly)\n";
                    
                    // Show detailed comparison only at verbose level 3+
                    if (m_verbose_level >= 3) {
                        std::cout << "Detailed comparison for " << m_current_structure_name << ":\n";
                        displaySideBySide(*m_current_description, *prog_desc);
                        std::cout << std::endl;
                    }
                }
            } else {
                logger_log_error(logger(), 
                                "VALIDATION FAILED: ", m_current_structure_name);
                
                // Log lookup chain context for failed validations
                logger_log_debug(logger(), 25,
                               "FAILED LOOKUP CHAIN: '" + m_current_structure_name + "' -> FSI " + 
                               std::to_string(m_reader.GetFSI(m_current_structure_name)) + 
                               " -> version " + std::to_string(version));
                
                for (const auto& error : result.errors) {
                    logger_log_error(logger(), "  ERROR: ", error);
                }
                
                for (const auto& warning : result.warnings) {
                    logger_log_warning(logger(), "  WARNING: ", warning);
                }
                
                // Show side-by-side comparison in verbose mode
                if (m_verbose_level >= 1) {
                    std::cout << "\nDetailed comparison for " << m_current_structure_name << ":\n";
                    displaySideBySide(*m_current_description, *prog_desc);
                    std::cout << std::endl;
                }
                
                m_verification_failures++;
            }
            
            m_structures_verified++;
        }
        
        // DIAGNOSTIC: Verification completion tracking
        logger_log_debug(logger(), 10,
                       "VERIFICATION END: Completed structure '", m_current_structure_name, "'");
        
        // Reset state
        logger_log_debug(logger(), 15,
                       "STATE RESET: Clearing description and setting state to IDLE");
        m_current_description.reset();
        m_current_structure_name.clear();
        m_state = State::IDLE;
    }
    
    const Common::Description* getProgramDescription(const std::string& name, unsigned int version) {
        logger_log_debug(logger(), 20, 
                       "LOOKUP START: getProgramDescription('" + name + "', version=" + std::to_string(version) + ")");
        
        // Use FrameSpec system to dynamically get object and description
        // First map structure name to FSI type using SequentialFrameReader's mapping
        int fsi_type = m_reader.GetFSI(name);
        logger_log_debug(logger(), 25,
                       "FSI LOOKUP: '" + name + "' -> FSI=" + std::to_string(fsi_type) + 
                       " (" + (fsi_type == Common::FrameSpec::Info::FSI_FR_NULL ? "NULL" : "FOUND") + ")");
        
        if (fsi_type == Common::FrameSpec::Info::FSI_FR_NULL) {
            logger_log_debug(logger(), 20, "LOOKUP FAILED: Unknown structure name '" + name + "'");
            return nullptr;  // Unknown structure name
        }
        
        auto object_type = static_cast<Common::FrameSpec::Info::frame_object_types>(fsi_type);
        logger_log_debug(logger(), 25,
                       "OBJECT TYPE: FSI " + std::to_string(fsi_type) + " -> object_type=" + std::to_string(object_type));
        
        // Get frame specification for version
        auto* spec_info = Common::FrameSpec::SpecInfo(version);
        if (!spec_info) {
            logger_log_debug(logger(), 20, "LOOKUP FAILED: Unsupported version " + std::to_string(version));
            return nullptr;  // Unsupported version
        }
        logger_log_debug(logger(), 30, "SPEC INFO: Found SpecInfo for version " + std::to_string(version));
        
        // Get frame object template
        auto* frame_object = spec_info->FrameObject(object_type, name);
        if (!frame_object) {
            logger_log_debug(logger(), 20, 
                           "LOOKUP FAILED: Object type " + std::to_string(object_type) + 
                           " not available in version " + std::to_string(version));
            return nullptr;  // Object type not available in this version
        }
        logger_log_debug(logger(), 30, "FRAME OBJECT: Found template object for type " + std::to_string(object_type));
        
        // Get description using the same pattern as framecpp_dump_descriptions
        auto* description = frame_object->GetDescription(version);
        if (!description) {
            logger_log_debug(logger(), 20, "LOOKUP FAILED: No description available from template object");
            return nullptr;
        }
        
        // Log description details for validation
        logger_log_debug(logger(), 25, 
                       "DESCRIPTION FOUND: " + std::to_string(description->size()) + " objects");
        
        // Log first few field names for any structure type
        if (description->size() > 0) {
            std::string field_preview = "First fields: ";
            size_t preview_count = std::min(size_t(3), size_t(description->size()));
            size_t field_count = 0;
            for (const auto& element : *description) {
                if (field_count >= preview_count) break;
                if (auto* frse = dynamic_cast<const Universal::FrSE*>(element.get())) {
                    if (field_count > 0) field_preview += ", ";
                    field_preview += "'" + frse->GetName() + "' (" + 
                                   frse->Universal::FrSEImpl::Data::GetClass() + ")";
                    field_count++;
                }
            }
            logger_log_debug(logger(), 25, field_preview);
        }
        
        logger_log_debug(logger(), 20, "LOOKUP SUCCESS: Returning description for '" + name + "'");
        return description;
    }
    
    /// \brief Display side-by-side comparison for verbose mode with field alignment
    void displaySideBySide(const Common::Description& file_desc, 
                          const Common::Description& program_desc) {
        const int TOTAL_WIDTH = 80;
        const int COLUMN_WIDTH = 38;  // Leave 4 chars for " | " separator
        const std::string SEPARATOR = " | ";
        const std::string MISSING_INDICATOR = "[missing]";
        
        // Extract structure name from file Description
        std::string file_structure_name = "UNKNOWN";
        if (file_desc.size() > 0) {
            if (auto* frsh = dynamic_cast<const Universal::FrSH*>(file_desc.begin()->get())) {
                file_structure_name = frsh->GetName();
            }
        }
        
        // Extract structure name from program Description  
        std::string program_structure_name = "UNKNOWN";
        if (program_desc.size() > 0) {
            if (auto* frsh = dynamic_cast<const Universal::FrSH*>(program_desc.begin()->get())) {
                program_structure_name = frsh->GetName();
            }
        }
        
        // Header with actual structure names from each Description
        std::cout << std::string(TOTAL_WIDTH, '=') << std::endl;
        std::string file_header = "FILE: " + file_structure_name;
        std::string program_header = "PROGRAM: " + program_structure_name;
        std::cout << std::left << std::setw(COLUMN_WIDTH) << file_header
                 << SEPARATOR << program_header << std::endl;
        std::cout << std::string(TOTAL_WIDTH, '=') << std::endl;
        std::cout << std::left << std::setw(COLUMN_WIDTH) << "FIELD DESCRIPTIONS" 
                 << SEPARATOR << "FIELD DESCRIPTIONS" << std::endl;
        std::cout << std::string(TOTAL_WIDTH, '-') << std::endl;
        
        // Field alignment structure to track field presence, positions, and types
        struct FieldAlignment {
            std::string name;
            std::string file_type;      // Type from file's FrSE GetClass()
            std::string program_type;   // Type from program's FrSE GetClass()
            bool in_file = false;
            bool in_program = false;
            size_t file_position = 0;
            size_t program_position = 0;
        };
        
        // Extract field names while preserving order
        std::vector<std::string> file_fields, program_fields;
        std::map<std::string, FieldAlignment> field_map;
        
        // Process file description fields (preserving order)
        size_t file_pos = 0;
        for (const auto& element : file_desc) {
            if (auto* frse = dynamic_cast<const Universal::FrSE*>(element.get())) {
                std::string field_name = frse->GetName();
                std::string field_type = frse->Universal::FrSEImpl::Data::GetClass();  // Get type information
                file_fields.push_back(field_name);
                
                auto& alignment = field_map[field_name];
                alignment.name = field_name;
                alignment.file_type = field_type;
                alignment.in_file = true;
                alignment.file_position = file_pos++;
            }
        }
        
        // Process program description fields (preserving order)
        size_t prog_pos = 0;
        for (const auto& element : program_desc) {
            if (auto* frse = dynamic_cast<const Universal::FrSE*>(element.get())) {
                std::string field_name = frse->GetName();
                std::string field_type = frse->Universal::FrSEImpl::Data::GetClass();  // Get type information
                program_fields.push_back(field_name);
                
                auto& alignment = field_map[field_name];
                alignment.name = field_name;
                alignment.program_type = field_type;
                alignment.in_program = true;
                alignment.program_position = prog_pos++;
            }
        }
        
        // Create unified field list preserving order significance
        // Strategy: Walk through both lists and build unified order
        std::vector<std::string> unified_fields;
        std::set<std::string> processed_fields;
        
        // First pass: Add fields that appear in file description order
        for (const auto& field_name : file_fields) {
            if (processed_fields.find(field_name) == processed_fields.end()) {
                unified_fields.push_back(field_name);
                processed_fields.insert(field_name);
            }
        }
        
        // Second pass: Add any program-only fields at positions that make sense
        // Insert program-only fields after the last common field that precedes them
        for (size_t i = 0; i < program_fields.size(); ++i) {
            const auto& prog_field = program_fields[i];
            if (processed_fields.find(prog_field) == processed_fields.end()) {
                // This is a program-only field
                // Find the best insertion position by looking at surrounding context
                size_t insert_pos = unified_fields.size(); // Default: append at end
                
                // Look for preceding context in program description
                for (int j = static_cast<int>(i) - 1; j >= 0; --j) {
                    auto it = std::find(unified_fields.begin(), unified_fields.end(), program_fields[j]);
                    if (it != unified_fields.end()) {
                        insert_pos = std::distance(unified_fields.begin(), it) + 1;
                        break;
                    }
                }
                
                unified_fields.insert(unified_fields.begin() + insert_pos, prog_field);
                processed_fields.insert(prog_field);
            }
        }
        
        // Display aligned fields with type information
        for (const auto& field_name : unified_fields) {
            const auto& alignment = field_map[field_name];
            
            // Format field names with type information
            std::string left_field, right_field;
            bool type_mismatch = false;
            
            if (alignment.in_file) {
                left_field = field_name;
                // Add type information if available
                if (!alignment.file_type.empty()) {
                    left_field += " (" + alignment.file_type + ")";
                }
                if (left_field.length() > COLUMN_WIDTH) {
                    left_field = left_field.substr(0, COLUMN_WIDTH - 3) + "...";
                }
            } else {
                left_field = MISSING_INDICATOR;
            }
            
            if (alignment.in_program) {
                right_field = field_name;
                // Add type information if available
                if (!alignment.program_type.empty()) {
                    right_field += " (" + alignment.program_type + ")";
                }
                if (right_field.length() > COLUMN_WIDTH) {
                    right_field = right_field.substr(0, COLUMN_WIDTH - 3) + "...";
                }
            } else {
                right_field = MISSING_INDICATOR;
            }
            
            // Check for type mismatch on common fields
            if (alignment.in_file && alignment.in_program && 
                !alignment.file_type.empty() && !alignment.program_type.empty() &&
                alignment.file_type != alignment.program_type) {
                type_mismatch = true;
            }
            
            // Display with type mismatch indicator
            std::cout << std::left << std::setw(COLUMN_WIDTH) << left_field 
                     << SEPARATOR << right_field;
            if (type_mismatch) {
                std::cout << " [TYPE MISMATCH]";
            }
            std::cout << std::endl;
        }
        
        std::cout << std::string(TOTAL_WIDTH, '=') << std::endl;
    }
    
    ValidationResult compareDescriptions(const Common::Description& file_desc,
                                        const Common::Description& program_desc) {
        ValidationResult result;
        result.structure_name = m_current_structure_name;
        result.file_object_count = file_desc.size();
        result.program_object_count = program_desc.size();
        
        // Detailed comparison: analyze field names and types
        std::set<std::string> file_fields, program_fields;
        std::map<std::string, std::string> file_types, program_types;
        
        // Extract field names and types from file description
        for (const auto& element : file_desc) {
            if (auto* frse = dynamic_cast<const Universal::FrSE*>(element.get())) {
                std::string field_name = frse->GetName();
                file_fields.insert(field_name);
                file_types[field_name] = frse->Universal::FrSEImpl::Data::GetClass();
            }
        }
        
        // Extract field names and types from program description  
        for (const auto& element : program_desc) {
            if (auto* frse = dynamic_cast<const Universal::FrSE*>(element.get())) {
                std::string field_name = frse->GetName();
                program_fields.insert(field_name);
                program_types[field_name] = frse->Universal::FrSEImpl::Data::GetClass();
            }
        }
        
        // Analyze the relationship between field sets
        std::set<std::string> file_only, program_only, common_fields;
        std::set_difference(file_fields.begin(), file_fields.end(),
                          program_fields.begin(), program_fields.end(),
                          std::inserter(file_only, file_only.begin()));
        std::set_difference(program_fields.begin(), program_fields.end(),
                          file_fields.begin(), file_fields.end(),
                          std::inserter(program_only, program_only.begin()));
        std::set_intersection(file_fields.begin(), file_fields.end(),
                            program_fields.begin(), program_fields.end(),
                            std::inserter(common_fields, common_fields.begin()));
        
        // Compare object counts with detailed analysis
        if (file_desc.size() != program_desc.size()) {
            std::string relationship;
            if (program_only.empty() && !file_only.empty()) {
                relationship = " (file is SUPERSET - has extra fields)";
            } else if (file_only.empty() && !program_only.empty()) {
                relationship = " (file is SUBSET - missing fields)";
            } else if (!file_only.empty() && !program_only.empty()) {
                relationship = " (MIXED differences - some extra, some missing)";
            } else {
                relationship = " (same field names but different structure)";
            }
            
            result.errors.push_back(
                "Object count mismatch: file has " + std::to_string(file_desc.size()) +
                " objects, program expects " + std::to_string(program_desc.size()) + relationship);
            
            // Add details about specific differences
            if (!file_only.empty()) {
                std::string extra_fields = "Extra fields in file: ";
                bool first = true;
                for (const auto& field : file_only) {
                    if (!first) extra_fields += ", ";
                    extra_fields += field;
                    first = false;
                }
                result.errors.push_back(extra_fields);
            }
            
            if (!program_only.empty()) {
                std::string missing_fields = "Missing fields from file: ";
                bool first = true;
                for (const auto& field : program_only) {
                    if (!first) missing_fields += ", ";
                    missing_fields += field;
                    first = false;
                }
                result.errors.push_back(missing_fields);
            }
            
            if (!common_fields.empty()) {
                result.errors.push_back("Common fields: " + std::to_string(common_fields.size()) + 
                                       " (" + std::to_string(common_fields.size() * 100 / 
                                       std::max(file_fields.size(), program_fields.size())) + "% overlap)");
            }
            
            result.is_valid = false;
        }
        
        // Check for type mismatches in common fields
        std::vector<std::string> type_mismatches;
        for (const auto& field : common_fields) {
            auto file_type_it = file_types.find(field);
            auto prog_type_it = program_types.find(field);
            
            if (file_type_it != file_types.end() && prog_type_it != program_types.end()) {
                if (!file_type_it->second.empty() && !prog_type_it->second.empty() &&
                    file_type_it->second != prog_type_it->second) {
                    type_mismatches.push_back(field + ": file has '" + file_type_it->second + 
                                            "', program expects '" + prog_type_it->second + "'");
                }
            }
        }
        
        // Report type mismatches
        if (!type_mismatches.empty()) {
            result.errors.push_back("Type mismatches found in " + 
                                   std::to_string(type_mismatches.size()) + " common field(s)");
            for (const auto& mismatch : type_mismatches) {
                result.errors.push_back("  Type mismatch: " + mismatch);
            }
            result.is_valid = false;
        }
        
        return result;
    }
    
    void reportSummary() {
        auto stats = m_reader.getStatistics();
        
        logger_log_debug(logger(), 10,
                       "Verification complete:");
        logger_log_debug(logger(), 10,
                       "  Structures verified: ", m_structures_verified);
        logger_log_debug(logger(), 10,
                       "  Verification failures: ", m_verification_failures);
        logger_log_debug(logger(), 10,
                       "  Unknown structures: ", m_unknown_structures);
        logger_log_debug(logger(), 10,
                       "  Objects processed: ", stats.objects_read,
                       " (FrSH: ", stats.frsh_count, 
                       ", FrSE: ", stats.frse_count, ")");
        logger_log_debug(logger(), 10,
                       "  Objects skipped: ", stats.objects_skipped,
                       " (", stats.bytes_skipped, " bytes)");
        
        if (m_verification_failures == 0 && m_structures_verified > 0) {
            logger_log_debug(logger(), 10, "All structure descriptions are valid!");
        }
    }
    
    static SimpleLogger* logger() {
        static SimpleLogger* instance = get_channel_logger("framecpp.verify");
        return instance;
    }
};

int main(int argc, char* argv[]) {
    
    FrameCPP::Initialize();
    
    try {
        // Services-based approach for proper dependency management
        auto logger_mgr = std::make_unique<LDASTools::AL::LoggerManager>();
        FrameCPP::Common::FrameCPPServices services(*logger_mgr);
        
        // Initialize debug system
        if (!FrameCPP::Utilities::FrameCPPDebugManager::initialize_with_services(
                argc, argv, services, "framecpp_verify_descriptions")) {
            logger_mgr->shutdown();
            return 0; // Help was requested
        }
        
        // Command-line options
        po::options_description desc(
            "framecpp_verify_descriptions - Verify frame file descriptions against program definitions\n\nOptions");
        desc.add_options()
            ("help,h", "Show this help message")
            ("verbose,v", po::value<int>()->default_value(0)->implicit_value(1),
             "Enable verbose output (0=none, 1=failures only, 2=successes, 3=detailed)")
            ("quiet,q", "Suppress informational messages (errors only)")
            ("output,o", po::value<std::string>(), 
             "Output file for verification results (default: stdout)");
        
        // Add debug options to main description
        po::variables_map vm;
        FrameCPP::Utilities::FrameCPPDebugManager::add_debug_options(desc, vm);
        
        // Hidden options for positional arguments
        po::options_description hidden("Hidden options");
        hidden.add_options()
            ("input-files", po::value<std::vector<std::string>>(), "Input frame files");
        
        po::options_description all;
        all.add(desc).add(hidden);
        
        // Positional options
        po::positional_options_description pos;
        pos.add("input-files", -1);
        
        po::store(po::command_line_parser(argc, argv)
                    .options(all)
                    .positional(pos)
                    .run(), vm);
        
        if (vm.count("help") || argc == 1) {
            std::cout << desc << std::endl;
            std::cout << "\nUsage: framecpp_verify_descriptions [options] file [file ...]" << std::endl;
            std::cout << "\nExamples:" << std::endl;
            std::cout << "  framecpp_verify_descriptions data.gwf                    # Errors only" << std::endl;
            std::cout << "  framecpp_verify_descriptions --verbose data.gwf         # Failures with details" << std::endl;
            std::cout << "  framecpp_verify_descriptions --verbose=2 data.gwf       # Failures AND successes (simple)" << std::endl;
            std::cout << "  framecpp_verify_descriptions --verbose=3 data.gwf       # Failures AND successes with details" << std::endl;
            std::cout << "  framecpp_verify_descriptions --debug-level 30 data.gwf" << std::endl;
            std::cout << "  framecpp_verify_descriptions -o results.txt data.gwf file2.gwf" << std::endl;
            logger_mgr->shutdown();
            return 0;
        }
        
        po::notify(vm);
        
        // Validate input files
        if (!vm.count("input-files")) {
            std::cerr << "Error: No input files specified" << std::endl;
            std::cerr << "Use --help for usage information." << std::endl;
            logger_mgr->shutdown();
            return 1;
        }
        
        // Configure debug manager
        FrameCPP::Utilities::FrameCPPDebugManager::configure_from_options(vm);
        
        // Get input files
        std::vector<std::string> input_files = vm["input-files"].as<std::vector<std::string>>();
        
        // Get verbose level from boost::program_options
        int verbose_level = vm["verbose"].as<int>();
        
        // Process all input files
        size_t total_failures = 0;
        size_t total_structures = 0;
        size_t total_unknown = 0;
        
        for (const auto& filename : input_files) {
            if (input_files.size() > 1) {
                std::cout << "Processing file: " << filename << std::endl;
                std::cout << std::string(60, '=') << std::endl;
            }
            
            try {
                // Create verifier and run for this file
                DescriptionVerifier verifier(filename, services);
                verifier.setVerboseLevel(verbose_level);
                verifier.verifyAllDescriptions();
                
                // Accumulate results
                total_failures += verifier.getFailureCount();
                total_structures += verifier.getStructuresVerified();
                total_unknown += verifier.getUnknownCount();
                
                if (input_files.size() > 1) {
                    std::cout << "File summary: " << filename << std::endl;
                    std::cout << "  Structures verified: " << verifier.getStructuresVerified() << std::endl;
                    std::cout << "  Failures: " << verifier.getFailureCount() << std::endl;
                    std::cout << "  Unknown structures: " << verifier.getUnknownCount() << std::endl;
                    std::cout << std::endl;
                }
                
            } catch (const std::exception& e) {
                std::cerr << "Error processing file '" << filename << "': " << e.what() << std::endl;
                total_failures++;  // Count file processing errors as failures
            }
        }
        
        // Report overall summary for multiple files
        if (input_files.size() > 1) {
            std::cout << std::string(60, '=') << std::endl;
            std::cout << "OVERALL SUMMARY:" << std::endl;
            std::cout << "  Files processed: " << input_files.size() << std::endl;
            std::cout << "  Total structures verified: " << total_structures << std::endl;
            std::cout << "  Total failures: " << total_failures << std::endl;
            std::cout << "  Total unknown structures: " << total_unknown << std::endl;
            
            if (total_failures == 0 && total_structures > 0) {
                std::cout << "  Result: All validations PASSED!" << std::endl;
            } else if (total_failures > 0) {
                std::cout << "  Result: " << total_failures << " validations FAILED" << std::endl;
            }
        }
        
        // Return appropriate exit code
        int exit_code = (total_failures == 0) ? 0 : 1;
        
        logger_mgr->shutdown();
        return exit_code;
        
    } catch (const std::exception& e) {
        std::cerr << "Error: " << e.what() << std::endl;
        return 1;
    }
}