//
// LDASTools frameCPP - Sequential Frame Reader implementation
//
// 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 "framecpp/Common/SequentialFrameReader.hh"
#include "framecpp/FrSH.hh"
#include "framecpp/FrSE.hh"
#include "framecpp/FrAdcData.hh"
#include "framecpp/FrProcData.hh"
#include "framecpp/FrSimData.hh"
#include "framecpp/FrVect.hh"
#include <cxxabi.h>
#include <typeinfo>

namespace FrameCPP
{
    namespace Common
    {

        /// \brief Demangle C++ type names for logging
        static std::string
        demangle( const char* name )
        {
            int   status = 0;
            char* demangled =
                abi::__cxa_demangle( name, nullptr, nullptr, &status );
            if ( status == 0 && demangled )
            {
                std::string result( demangled );
                std::free( demangled );
                return result;
            }
            return std::string( name );
        }

        // Static logger method (moved from header to avoid ODR violations)
        SimpleLogger* SequentialFrameReader::static_logger() {
            static SimpleLogger* instance = get_channel_logger("framecpp.sequentialframereader");
            return instance;
        }

        SequentialFrameReader::SequentialFrameReader(
            const std::string& filename, const FrameCPPServices& services )
            : IFrameStream( true, createFrameBuffer( filename ), 0 ),
              m_services( services )
        {
            // Phase 1: Debug logging for sequential vs non-sequential comparison
            if ( logger( ) )
            {
                logger_log_debug( logger( ), 15,
                    "SequentialFrameReader constructor ENTRY - filename: ", filename );
                
                // Check stream state after IFrameStream constructor
                std::streampos pos = tellg();
                logger_log_debug( logger( ), 15,
                    "SequentialFrameReader after IFrameStream constructor - position: ", pos,
                    ", good(): ", good(), ", fail(): ", fail(),
                    ", bad(): ", bad(), ", eof(): ", eof() );
                
                // Check if IFrameStream::init() was called successfully
                try {
                    auto header = getFileHeader();
                    if ( header )
                    {
                        logger_log_debug( logger( ), 15,
                            "SequentialFrameReader constructor - IFrameStream::init() SUCCESS, header version: ", header->GetVersion() );
                    }
                    else
                    {
                        logger_log_debug( logger( ), 15,
                            "SequentialFrameReader constructor - WARNING: No header available after IFrameStream::init()" );
                    }
                }
                catch ( const std::exception& e )
                {
                    logger_log_debug( logger( ), 15,
                        "SequentialFrameReader constructor - IFrameStream::init() FAILED: ", e.what() );
                }
            }
            
            initializeMappings( );
            
            if ( logger( ) )
            {
                logger_log_debug( logger( ), 15,
                    "SequentialFrameReader constructor COMPLETE - initialization successful" );
            }
        }

        SequentialFrameReader::SequentialFrameReader(
            FrameBuffer< std::filebuf >* buffer,
            const FrameCPPServices&      services,
            INT_2U                       frame_version )
            : IFrameStream( true, buffer, frame_version ),
              m_services( services )
        {
            initializeMappings( );
        }

        SequentialFrameReader::SequentialFrameReader(
            MemoryBuffer*           buffer,
            const FrameCPPServices& services,
            INT_2U                  frame_version )
            : IFrameStream( true, buffer, frame_version ),
              m_services( services )
        {
            initializeMappings( );
        }

        FrameBuffer< std::filebuf >*
        SequentialFrameReader::createFrameBuffer( const std::string& filename )
        {
            // Debug logging for buffer creation
            logger_log_debug(static_logger(), 20, "SequentialFrameReader::createFrameBuffer ENTRY - filename: ", filename);
            
            // FrameBuffer constructor needs mode and binary flag
            auto buffer = std::make_unique< FrameBuffer< std::filebuf > >(
                std::ios::in | std::ios::binary, false );
                
            logger_log_debug(static_logger(), 30, "SequentialFrameReader::createFrameBuffer FrameBuffer created with (std::ios::in | std::ios::binary, false)");
            
            buffer->open( filename.c_str( ), std::ios::in | std::ios::binary );

            if ( !buffer->is_open( ) )
            {
                logger_log_debug(static_logger(), 10, "SequentialFrameReader::createFrameBuffer FAILED to open file: ", filename);
                throw std::runtime_error( "Failed to open frame file: " +
                                          filename );
            }
            
            logger_log_debug(static_logger(), 20, "SequentialFrameReader::createFrameBuffer File opened successfully, transferring ownership to IFrameStream");

            return buffer.release( ); // Transfer ownership to IFrameStream
        }

        void
        SequentialFrameReader::setMode( Mode mode )
        {
            m_mode = mode;

            if ( mode == Mode::DESCRIPTION_ONLY )
            {
                m_allowed_class_ids = { 1, 2 }; // FrSH and FrSE
                logger_log_debug( logger( ),
                                  20,
                                  "Description-only mode enabled - will only "
                                  "process FrSH/FrSE" );
            }
        }

        boost::shared_ptr< FrameSpec::Object >
        SequentialFrameReader::readNextObject( )
        {
            // Phase 1: Debug logging for readNextObject initialization
            if ( logger( ) )
            {
                logger_log_debug( logger( ), 15,
                    "SequentialFrameReader::readNextObject() ENTRY - m_initialized: ", m_initialized );
                
                // Track stream state at start of readNextObject
                std::streampos pos = tellg();
                logger_log_debug( logger( ), 15,
                    "SequentialFrameReader::readNextObject() stream state - position: ", pos,
                    ", good(): ", good(), ", fail(): ", fail(),
                    ", bad(): ", bad(), ", eof(): ", eof() );
            }
            
            // Ensure we're positioned correctly for sequential reading
            // IFrameStream::init() already loaded header and set byte swapping
            if ( !m_initialized )
            {
                if ( logger( ) )
                {
                    logger_log_debug( logger( ), 15,
                        "SequentialFrameReader::readNextObject() - FIRST CALL, initializing..." );
                }
                
                // Get the header that was already loaded by
                // IFrameStream::init()
                auto header_obj = getFileHeader( );
                if ( !header_obj )
                {
                    if ( logger( ) )
                    {
                        logger_log_debug( logger( ), 10,
                            "SequentialFrameReader::readNextObject() - CRITICAL: No FrHeader available from parent stream!" );
                    }
                    throw std::runtime_error(
                        "No FrHeader available from parent stream" );
                }
                
                if ( logger( ) )
                {
                    logger_log_debug( logger( ), 15,
                        "SequentialFrameReader::readNextObject() - Got header successfully, version: ", header_obj->GetVersion() );
                }

                // Position after header (unconditionally - no-op if already
                // there)
                streamsize_type header_size = header_obj->Bytes( *this );
                
                if ( logger( ) )
                {
                    logger_log_debug( logger( ), 15,
                        "SequentialFrameReader::readNextObject() - header size: ", header_size,
                        " bytes, seeking to position after header..." );
                }
                
                seekg( header_size, std::ios::beg );
                
                if ( logger( ) )
                {
                    std::streampos post_seek_pos = tellg();
                    logger_log_debug( logger( ), 15,
                        "SequentialFrameReader::readNextObject() - after seekg() - position: ", post_seek_pos,
                        ", good(): ", good(), ", fail(): ", fail(),
                        ", bad(): ", bad(), ", eof(): ", eof() );
                }

                m_initialized = true;
                
                if ( logger( ) )
                {
                    logger_log_debug( logger( ), 15,
                        "SequentialFrameReader::readNextObject() - initialization COMPLETE, ready for sequential reading" );
                }

                logger_log_debug( logger( ),
                                  20,
                                  "Positioned for sequential reading at: ",
                                  tellg( ),
                                  ", header size: ",
                                  header_size,
                                  ", byte swapping: ",
                                  ( ByteSwapping( ) ? 1 : 0 ) );
            }

            // Declare class_id in broader scope so it's available in catch
            // blocks
            int class_id = -1; // Initialize to invalid value

            try
            {
                // Read StreamRef to get class ID and length
                auto streamref = readStreamRef( );
                if ( !streamref )
                {
                    logger_log_debug(
                        logger( ), 30, "End of stream or no more objects" );
                    return nullptr;
                }

                class_id = streamref->GetClass( );
                int             instance = streamref->GetInstance( );
                streamsize_type total_length = streamref->GetLength( );

                // CRITICAL DEBUG: Enhanced class_id diagnostic logging
                if ( logger( ) )
                {
                    std::string class_name = "Unknown";
                    if ( class_id == 1 )
                        class_name = "FrSH";
                    else if ( class_id == 2 )
                        class_name = "FrSE";
                    else if ( class_id == 5 )
                        class_name = "FrDetector";
                    else if ( class_id == 16 )
                        class_name = "FrStatData";
                    else if ( class_id == 20 )
                        class_name = "FrVect";

                    logger_log_debug( logger( ),
                                      10,
                                      "STREAM SEQUENCE: Read object class_id=",
                                      class_id,
                                      " (",
                                      class_name,
                                      ")",
                                      ", instance=",
                                      instance,
                                      ", length=",
                                      total_length,
                                      ", position=",
                                      tellg( ) );

                    // CRITICAL: Log raw StreamRef data for class_id
                    // verification
                    logger_log_debug( logger( ),
                                      5,
                                      "RAW STREAMREF DATA: class_id=",
                                      class_id,
                                      " (0x",
                                      std::hex,
                                      class_id,
                                      std::dec,
                                      ")",
                                      ", instance=",
                                      instance,
                                      " (0x",
                                      std::hex,
                                      instance,
                                      std::dec,
                                      ")",
                                      ", total_length=",
                                      total_length,
                                      " (0x",
                                      std::hex,
                                      total_length,
                                      std::dec,
                                      ")" );
                }

                logger_log_debug( logger( ),
                                  60,
                                  "StreamRef: class_id=",
                                  class_id,
                                  ", instance=",
                                  instance,
                                  ", total_length=",
                                  total_length );

                // Check if we should process this object based on mode and
                // filters
                if ( !shouldProcessStreamRef(
                         class_id, instance, total_length ) )
                {
                    // CRITICAL DEBUG: Log skip path execution
                    if ( logger( ) )
                    {
                        logger_log_debug(
                            logger( ),
                            5,
                            "SKIP PATH: Skipping object class_id=",
                            class_id,
                            ", calling skipObjectData()" );
                    }

                    // Skip the object data without deserializing
                    skipObjectData( streamref );
                    m_stats.objects_skipped++;
                    m_stats.bytes_skipped += total_length;

                    logger_log_debug( logger( ),
                                      50,
                                      "Skipped object with class_id=",
                                      class_id,
                                      " (",
                                      total_length,
                                      " total bytes)" );

                    return nullptr; // Signal to continue reading
                }

                // CRITICAL DEBUG: Log processing path execution
                if ( logger( ) )
                {
                    logger_log_debug(
                        logger( ),
                        5,
                        "PROCESS PATH: Processing object class_id=",
                        class_id,
                        ", calling readObject()" );
                }

                // CRITICAL FIX: Check if this is an FrSH (class_id == 1)
                // If it is, we need to signal state transition even if
                // deserialization fails
                bool is_frsh = ( class_id == 1 );

                // Deserialize the object using IFrameStream's readObject method
                boost::shared_ptr< FrameSpec::Object > object;
                try
                {
                    // CRITICAL DEBUG: Log class_id before deserialization
                    // attempt
                    if ( logger( ) )
                    {
                        logger_log_debug(
                            logger( ),
                            5,
                            "DESERIALIZATION ATTEMPT: class_id=",
                            class_id,
                            " (0x",
                            std::hex,
                            class_id,
                            std::dec,
                            ")",
                            ", attempting to deserialize object type" );
                    }

                    object = readObject( streamref.get( ) );

                    // CRITICAL DEBUG: Log successful deserialization
                    if ( logger( ) && object )
                    {
                        auto const& obj = *object;
                        logger_log_debug(
                            logger( ),
                            5,
                            "DESERIALIZATION SUCCESS: class_id=",
                            class_id,
                            ", object type: ",
                            demangle( typeid( obj ).name( ) ) );
                    }
                }
                catch ( const std::exception& e )
                {
                    // CRITICAL DEBUG: Log deserialization failure with class_id
                    // details
                    logger_log_error( logger( ),
                                      "DESERIALIZATION FAILED: class_id=",
                                      class_id,
                                      " (0x",
                                      std::hex,
                                      class_id,
                                      std::dec,
                                      ")",
                                      ", Error: ",
                                      e.what( ) );

                    // CRITICAL DEBUG: Check callback triggering logic
                    if ( logger( ) )
                    {
                        logger_log_debug(
                            logger( ),
                            5,
                            "CALLBACK DEBUG: is_frsh=",
                            is_frsh,
                            ", callback_set=",
                            ( m_frsh_state_callback ? "true" : "false" ) );
                    }

                    // CRITICAL FIX: If this was an FrSH that failed to load,
                    // we need to signal the state management callback
                    if ( is_frsh && m_frsh_state_callback )
                    {
                        logger_log_warning( logger( ),
                                            "FrSH failed to load - triggering "
                                            "state reset callback" );
                        // Call the callback to handle state transition for
                        // failed FrSH
                        m_frsh_state_callback( true ); // true = failed FrSH
                    }
                    else if ( is_frsh && !m_frsh_state_callback )
                    {
                        logger_log_warning( logger( ),
                                            "FrSH failed but no callback set - "
                                            "state may be inconsistent" );
                    }
                    else if ( !is_frsh )
                    {
                        logger_log_debug(
                            logger( ),
                            5,
                            "Non-FrSH object failed - no callback needed" );
                    }

                    // Handle unknown object based on mode
                    if ( m_mode == Mode::SKIP_UNKNOWN ||
                         m_mode == Mode::UNKNOWN_ONLY )
                    {
                        // Get object information for unknown object reporting
                        std::string object_name = "Unknown";
                        auto        class_name_it =
                            m_class_id_to_name.find( class_id );
                        if ( class_name_it != m_class_id_to_name.end( ) )
                        {
                            object_name = class_name_it->second;
                        }

                        // Call callback if provided
                        if ( m_unknown_object_callback )
                        {
                            m_unknown_object_callback(
                                class_id, instance, object_name, e.what( ) );
                        }

                        // Log unknown object encounter
                        logger_log_warning(
                            logger( ),
                            "Unknown object encountered: class_id=",
                            class_id,
                            " (",
                            object_name,
                            "), error: ",
                            e.what( ),
                            ", action: ",
                            ( m_mode == Mode::SKIP_UNKNOWN ? "skipping"
                                                           : "reporting" ) );

                        // Skip object data
                        skipObjectData( streamref );
                        m_stats.objects_skipped++;
                        m_stats.bytes_skipped += total_length;

                        return nullptr; // Continue processing
                    }

                    // Traditional behavior - re-throw for other modes
                    throw;
                }

                if ( object )
                {
                    m_stats.objects_read++;

                    // Track specific types for statistics
                    if ( class_id == 1 )
                    {
                        m_stats.frsh_count++;
                        if ( auto* frsh = dynamic_cast< Common::FrSH* >(
                                 object.get( ) ) )
                        {
                            processFrSH( frsh );
                            logger_log_debug( logger( ),
                                              30,
                                              "Read FrSH for structure: ",
                                              frsh->name( ) );
                        }
                    }
                    else if ( class_id == 2 )
                    {
                        m_stats.frse_count++;
                        logger_log_debug( logger( ), 40, "Read FrSE" );
                    }

                    auto const& obj = *object;
                    logger_log_debug( logger( ),
                                      40,
                                      "Read object type: ",
                                      demangle( typeid( obj ).name( ) ) );
                }
                else
                {
                    logger_log_warning(
                        logger( ),
                        "Failed to deserialize object with class_id=",
                        class_id );
                }

                return object;
            }
            catch ( const std::exception& e )
            {
                logger_log_error( logger( ),
                                  "Unexpected error in readNextObject: ",
                                  e.what( ) );

                // CRITICAL DEBUG: Check if this was an FrSH-related error that
                // needs callback
                if ( logger( ) )
                {
                    logger_log_debug(
                        logger( ),
                        5,
                        "OUTER CATCH: Unexpected error caught, class_id=",
                        class_id,
                        ", checking for FrSH failure handling" );
                }

                // CRITICAL FIX: This outer catch bypasses our inner FrSH error
                // handling If we get here for an FrSH, we should also trigger
                // the callback
                bool is_frsh = ( class_id == 1 );
                if ( is_frsh && m_frsh_state_callback )
                {
                    logger_log_warning( logger( ),
                                        "OUTER CATCH: FrSH failed to load - "
                                        "triggering state reset callback" );
                    // Call the callback to handle state transition for failed
                    // FrSH
                    m_frsh_state_callback( true ); // true = failed FrSH
                }
                else if ( is_frsh && !m_frsh_state_callback )
                {
                    logger_log_warning(
                        logger( ),
                        "OUTER CATCH: FrSH failed but no callback set - state "
                        "may be inconsistent" );
                }

                return nullptr;
            }
        }

        bool
        SequentialFrameReader::shouldProcessStreamRef( int             class_id,
                                                       int             instance,
                                                       streamsize_type length )
        {
            bool should_process = false;

            switch ( m_mode )
            {
            case Mode::FULL_PROCESSING:
                // Process everything
                should_process = true;
                break;

            case Mode::DESCRIPTION_ONLY:
                // Only process FrSH (1) and FrSE (2)
                should_process = ( class_id == 1 || class_id == 2 );
                break;

            case Mode::FILTERED_PROCESSING:
                // Use custom filter if provided
                if ( m_streamref_filter )
                {
                    should_process =
                        m_streamref_filter( class_id, instance, length );
                }
                else
                {
                    should_process = true; // Default to processing if no filter
                }
                break;

            case Mode::SKIP_UNKNOWN:
            case Mode::UNKNOWN_ONLY:
                // Process everything - filtering happens during deserialization
                should_process = true;
                break;

            default:
                should_process = true;
                break;
            }

            // CRITICAL DEBUG: Log filtering decisions
            if ( logger( ) )
            {
                std::string decision = should_process ? "PROCESS" : "SKIP";
                std::string class_name = "Unknown";
                if ( class_id == 1 )
                    class_name = "FrSH";
                else if ( class_id == 2 )
                    class_name = "FrSE";
                else if ( class_id == 5 )
                    class_name = "FrDetector";
                else if ( class_id == 16 )
                    class_name = "FrStatData";
                else if ( class_id == 20 )
                    class_name = "FrVect";

                logger_log_debug( logger( ),
                                  5,
                                  "FILTER DECISION: class_id=",
                                  class_id,
                                  " (",
                                  class_name,
                                  ")",
                                  ", mode=",
                                  static_cast< int >( m_mode ),
                                  " -> ",
                                  decision );
            }

            return should_process;
        }

        void
        SequentialFrameReader::skipObjectData(
            boost::shared_ptr< StreamRefInterface > streamref )
        {
            // Calculate how much data to skip
            // We've already read the StreamRef header, so skip the remaining
            // data
            streamsize_type total_length = streamref->GetLength( );
            streamsize_type streamref_header_size = streamref->Bytes( *this );
            streamsize_type data_to_skip = total_length - streamref_header_size;
            streamsize_type position_before = tellg( );

            // CRITICAL DEBUG: Enhanced skip logging
            if ( logger( ) )
            {
                logger_log_debug( logger( ),
                                  5,
                                  "SKIP DATA: class_id=",
                                  streamref->GetClass( ),
                                  ", total_length=",
                                  total_length,
                                  ", streamref_header=",
                                  streamref_header_size,
                                  ", data_to_skip=",
                                  data_to_skip,
                                  ", position_before=",
                                  position_before );
            }

            if ( data_to_skip > 0 )
            {
                seekg( data_to_skip, std::ios::cur );

                // CRITICAL DEBUG: Verify skip was successful
                if ( logger( ) )
                {
                    streamsize_type position_after = tellg( );
                    logger_log_debug( logger( ),
                                      5,
                                      "SKIP COMPLETE: position_after=",
                                      position_after,
                                      ", actual_skipped=",
                                      ( position_after - position_before ) );
                }
            }
            else if ( data_to_skip < 0 )
            {
                logger_log_warning( logger( ),
                                    "Negative skip distance calculated: ",
                                    data_to_skip,
                                    " for StreamRef with class_id=",
                                    streamref->GetClass( ) );
            }
        }

        void
        SequentialFrameReader::processAllObjects( ObjectProcessor processor )
        {
            while ( !eof( ) )
            {
                auto object = readNextObject( );

                // nullptr can mean either skipped object or end of stream
                if ( !object )
                {
                    if ( eof( ) )
                    {
                        logger_log_debug(
                            logger( ), 20, "Reached end of file" );
                        break;
                    }
                    continue; // Object was skipped, continue reading
                }

                if ( processor )
                {
                    if ( !processor( object ) )
                    {
                        logger_log_debug(
                            logger( ), 20, "Processing stopped by callback" );
                        break;
                    }
                }
            }

            // Report statistics
            logger_log_debug( logger( ),
                              20,
                              "Processing complete:",
                              " Objects read: ",
                              m_stats.objects_read,
                              " (FrSH: ",
                              m_stats.frsh_count,
                              ", FrSE: ",
                              m_stats.frse_count,
                              ")",
                              ", Skipped: ",
                              m_stats.objects_skipped,
                              " (",
                              m_stats.bytes_skipped,
                              " bytes)" );
        }

        void
        SequentialFrameReader::initializeMappings( )
        {
            // Fixed by frame specification - class IDs 1 and 2
            m_class_id_to_name[ 1 ] = "FrSH";
            m_class_id_to_name[ 2 ] = "FrSE";

            // Seed FSI mapping with constants defined by frame specification
            m_name_to_fsi[ "FrSH" ] = 1; // Always FSI 1
            m_name_to_fsi[ "FrSE" ] = 2; // Always FSI 2

            // All other FSI mappings will be built dynamically as we encounter
            // FrSH objects This ensures we use the actual FrameSpec system
            // values instead of assumptions

            if ( logger( ) )
            {
                logger_log_debug(
                    logger( ),
                    20,
                    "FSI mapping initialized with constants: FrSH=1, FrSE=2" );
                logger_log_debug(
                    logger( ),
                    20,
                    "Dynamic FSI mapping enabled - will build other mappings "
                    "from file content + FrameSpec lookup" );
            }
        }

        int
        SequentialFrameReader::lookupFSIFromFrameSpec(
            const std::string& structureName, unsigned int version )
        {
            if ( logger( ) )
            {
                logger_log_debug( logger( ),
                                  15,
                                  "FSI LOOKUP START: structure='",
                                  structureName,
                                  "', version=",
                                  version );
                // Log expected FSI values for reference
                logger_log_debug( logger( ), 15, "Expected FSI values:" );
                logger_log_debug(
                    logger( ),
                    15,
                    "  FSI_FR_STAT_DATA=",
                    static_cast< int >(
                        Common::FrameSpec::Info::FSI_FR_STAT_DATA ) );
                logger_log_debug( logger( ),
                                  15,
                                  "  FSI_FR_VECT=",
                                  static_cast< int >(
                                      Common::FrameSpec::Info::FSI_FR_VECT ) );
                logger_log_debug(
                    logger( ),
                    15,
                    "  FSI_FR_SUMMARY=",
                    static_cast< int >(
                        Common::FrameSpec::Info::FSI_FR_SUMMARY ) );
                logger_log_debug(
                    logger( ),
                    15,
                    "  FSI_FR_SIM_EVENT=",
                    static_cast< int >(
                        Common::FrameSpec::Info::FSI_FR_SIM_EVENT ) );
            }

            // Use the same FrameSpec system that getProgramDescription() uses
            auto* spec_info = Common::FrameSpec::SpecInfo( version );
            if ( !spec_info )
            {
                if ( logger( ) )
                {
                    logger_log_warning(
                        logger( ), "No SpecInfo for version ", version );
                }
                return Common::FrameSpec::Info::FSI_FR_NULL;
            }

            // Try to find the structure by iterating through available object
            // types This is similar to how framecpp_dump_descriptions works
            for ( int fsi = 1; fsi <= 20; ++fsi )
            {
                if ( logger( ) )
                {
                    logger_log_debug( logger( ),
                                      5,
                                      "TESTING FSI ",
                                      fsi,
                                      " for '",
                                      structureName,
                                      "'" );
                }

                auto object_type =
                    static_cast< Common::FrameSpec::Info::frame_object_types >(
                        fsi );
                auto* frame_object =
                    spec_info->FrameObject( object_type, structureName );

                if ( logger( ) )
                {
                    logger_log_debug( logger( ),
                                      5,
                                      "  FrameObject result: ",
                                      ( frame_object ? "FOUND" : "NULL" ) );
                }

                if ( frame_object )
                {
                    // Get the description and check if first element matches
                    // our structure name
                    auto* description = frame_object->GetDescription( version );
                    if ( logger( ) )
                    {
                        logger_log_debug( logger( ),
                                          5,
                                          "  Description: ",
                                          ( description ? "FOUND" : "NULL" ) );
                        if ( description )
                        {
                            logger_log_debug( logger( ),
                                              5,
                                              "  Description size: ",
                                              description->size( ) );
                        }
                    }

                    if ( description && description->size( ) > 0 )
                    {
                        auto* frsh = dynamic_cast< const Common::FrSH* >(
                            description->begin( )->get( ) );
                        if ( logger( ) )
                        {
                            logger_log_debug( logger( ),
                                              5,
                                              "  FrSH cast: ",
                                              ( frsh ? "SUCCESS" : "FAILED" ) );
                        }

                        if ( frsh )
                        {
                            std::string frsh_name = frsh->name( );
                            bool name_match = ( frsh_name == structureName );

                            if ( logger( ) )
                            {
                                logger_log_debug(
                                    logger( ),
                                    5,
                                    "  FrSH name: '",
                                    frsh_name,
                                    "' vs target: '",
                                    structureName,
                                    "' -> ",
                                    ( name_match ? "MATCH" : "NO_MATCH" ) );
                            }

                            if ( name_match )
                            {
                                if ( logger( ) )
                                {
                                    logger_log_debug( logger( ),
                                                      15,
                                                      "FSI LOOKUP SUCCESS: '",
                                                      structureName,
                                                      "' found at FSI ",
                                                      fsi );
                                }
                                return fsi;
                            }
                        }
                    }
                }
            }

            if ( logger( ) )
            {
                logger_log_warning( logger( ),
                                    "FSI LOOKUP FAILED: structure '",
                                    structureName,
                                    "' not found" );
            }
            return Common::FrameSpec::Info::FSI_FR_NULL;
        }

        int
        SequentialFrameReader::GetFSI( const std::string& name ) const
        {
            auto it = m_name_to_fsi.find( name );
            int  result = ( it != m_name_to_fsi.end( ) )
                ? it->second
                : Common::FrameSpec::Info::FSI_FR_NULL;

            // Enhanced logging for FSI lookup
            if ( logger( ) )
            {
                if ( result != Common::FrameSpec::Info::FSI_FR_NULL )
                {
                    logger_log_debug( logger( ),
                                      30,
                                      "FSI MAPPING: '" + name + "' -> " +
                                          std::to_string( result ) +
                                          " (SUCCESS)" );
                }
                else
                {
                    logger_log_warning(
                        logger( ),
                        "FSI MAPPING: '" + name +
                            "' -> NOT_FOUND (returning FSI_FR_NULL)" );

                    // Log available mappings when lookup fails
                    logger_log_debug(
                        logger( ), 40, "Available FSI mappings:" );
                    for ( const auto& mapping : m_name_to_fsi )
                    {
                        logger_log_debug(
                            logger( ),
                            40,
                            "  '" + mapping.first + "' -> " +
                                std::to_string( mapping.second ) );
                    }
                }
            }

            return result;
        }

        void
        SequentialFrameReader::processFrSH( const Common::FrSH* frsh )
        {
            if ( !frsh )
                return;

            int         fileClassId = frsh->classId( );
            std::string structureName = frsh->name( );

            // CRITICAL DEBUG: Log FrSH class_id processing
            if ( logger( ) )
            {
                logger_log_debug( logger( ),
                                  5,
                                  "FRSH PROCESSING: Structure='",
                                  structureName,
                                  "'",
                                  ", FrSH.GetClass()=",
                                  fileClassId,
                                  " (0x",
                                  std::hex,
                                  fileClassId,
                                  std::dec,
                                  ")" );
            }

            // Update class ID mapping
            m_class_id_to_name[ fileClassId ] = structureName;

            // Build FSI mapping using FrameSpec::Info::GetDirectFSI
            if ( m_name_to_fsi.find( structureName ) == m_name_to_fsi.end( ) )
            {
                auto actual_fsi =
                    Common::FrameSpec::Info::GetDirectFSI( structureName );

                if ( actual_fsi != Common::FrameSpec::Info::FSI_FR_NULL )
                {
                    m_name_to_fsi[ structureName ] =
                        static_cast< int >( actual_fsi );

                    if ( logger( ) )
                    {
                        logger_log_debug(
                            logger( ),
                            20,
                            "DIRECT FSI MAPPING: '" + structureName +
                                "' (file classId=" +
                                std::to_string( fileClassId ) + ") -> FSI " +
                                std::to_string( actual_fsi ) );
                    }
                }
                else
                {
                    if ( logger( ) )
                    {
                        logger_log_warning( logger( ),
                                            "Failed to find direct FSI mapping "
                                            "for structure: " +
                                                structureName );
                    }
                }
            }
            else
            {
                if ( logger( ) )
                {
                    logger_log_debug(
                        logger( ),
                        30,
                        "Structure '" + structureName +
                            "' already mapped to FSI " +
                            std::to_string( m_name_to_fsi[ structureName ] ) );
                }
            }
        }

    } // namespace Common
} // namespace FrameCPP
