-- =====================================================================================
-- Script: 10_MARS_826_verify_record_counts.sql
-- Purpose: Compare source table record counts with archive table counts in ODS
-- Author: Grzegorz Michalski
-- Created: 2025-12-02
-- Updated: 2025-12-15
-- MARS Issue: MARS-826
-- Note: Validates export process by comparing source vs archive record counts
-- =====================================================================================

SET SERVEROUTPUT ON SIZE UNLIMITED;
SET FEEDBACK ON;
SET VERIFY OFF;
SET LINESIZE 200;

PROMPT =====================================================================================
PROMPT MARS-826 Record Count Verification: Source vs Archive Tables
PROMPT =====================================================================================

DECLARE
    vSourceCount NUMBER;
    vArchiveCount NUMBER;
    vTotalSourceRecords NUMBER := 0;
    vTotalArchiveRecords NUMBER := 0;
    vTableName VARCHAR2(100);
    vSchemaName VARCHAR2(30);
    vArchiveTableName VARCHAR2(100);
    
    TYPE t_table_rec IS RECORD (
        schema_name VARCHAR2(30),
        table_name VARCHAR2(100),
        display_name VARCHAR2(100),
        archive_table_name VARCHAR2(100)
    );
    TYPE t_table_list IS TABLE OF t_table_rec;
    vTables t_table_list;
BEGIN
    DBMS_OUTPUT.PUT_LINE('VERIFICATION TIME: ' || TO_CHAR(SYSTIMESTAMP, 'YYYY-MM-DD HH24:MI:SS.FF3'));
    DBMS_OUTPUT.PUT_LINE('');
    DBMS_OUTPUT.PUT_LINE(RPAD('TABLE NAME', 40) || RPAD('SCHEMA', 12) || LPAD('SOURCE COUNT', 15) || LPAD('ARCHIVE COUNT', 15) || LPAD('DIFF', 10) || ' STATUS');
    DBMS_OUTPUT.PUT_LINE(RPAD('-', 40, '-') || RPAD('-', 12, '-') || LPAD('-', 15, '-') || LPAD('-', 15, '-') || LPAD('-', 10, '-') || ' ------');
    
    -- Initialize table list with schema, table names, and corresponding archive tables
    vTables := t_table_list(
        t_table_rec('OU_LM', 'LEGACY_ADHOC_ADJ_HEADER', 'LEGACY_ADHOC_ADJ_HEADER', 'LM_ADHOC_ADJUSTMENTS_HEADER_ARCHIVE'),
        t_table_rec('OU_LM', 'LEGACY_ADHOC_ADJ_ITEM', 'LEGACY_ADHOC_ADJ_ITEM', 'LM_ADHOC_ADJUSTMENTS_ITEM_ARCHIVE'),
        t_table_rec('OU_LM', 'LEGACY_ADHOC_ADJ_ITEM_HEADER', 'LEGACY_ADHOC_ADJ_ITEM_HEADER', 'LM_ADHOC_ADJUSTMENTS_ITEM_HEADER_ARCHIVE'),
        t_table_rec('OU_LM', 'LEGACY_BALANCESHEET_HEADER', 'LEGACY_BALANCESHEET_HEADER', 'LM_BALANCESHEET_HEADER_ARCHIVE'),
        t_table_rec('OU_LM', 'LEGACY_BALANCESHEET_ITEM', 'LEGACY_BALANCESHEET_ITEM', 'LM_BALANCESHEET_ITEM_ARCHIVE'),
        t_table_rec('OU_LM', 'LEGACY_CSM_ADJ_HEADER', 'LEGACY_CSM_ADJ_HEADER', 'LM_CSM_ADJUSTMENTS_HEADER_ARCHIVE'),
        t_table_rec('OU_LM', 'LEGACY_CSM_ADJ_ITEM', 'LEGACY_CSM_ADJ_ITEM', 'LM_CSM_ADJUSTMENTS_ITEM_ARCHIVE'),
        t_table_rec('OU_LM', 'LEGACY_CSM_ADJ_ITEM_HEADER', 'LEGACY_CSM_ADJ_ITEM_HEADER', 'LM_CSM_ADJUSTMENTS_ITEM_HEADER_ARCHIVE'),
        t_table_rec('OU_LM', 'LEGACY_STANDING_FACILITY', 'LEGACY_STANDING_FACILITY', 'LM_STANDING_FACILITIES_ARCHIVE'),
        t_table_rec('OU_LM', 'LEGACY_STANDING_FACILITY_HEADER', 'LEGACY_STANDING_FACILITY_HEADER', 'LM_STANDING_FACILITIES_HEADER_ARCHIVE'),
        t_table_rec('OU_MRR', 'LEGACY_MRR_IND_CURRENT_ACCOUNT_HEADER', 'LEGACY_MRR_IND_CURRENT_ACCOUNT_HEADER', 'LM_CURRENT_ACCOUNTS_HEADER_ARCHIVE'),
        t_table_rec('OU_MRR', 'LEGACY_MRR_IND_CURRENT_ACCOUNT_ITEM', 'LEGACY_MRR_IND_CURRENT_ACCOUNT_ITEM', 'LM_CURRENT_ACCOUNTS_ITEM_ARCHIVE'),
        t_table_rec('OU_LM', 'LEGACY_FORECAST_HEADER', 'LEGACY_FORECAST_HEADER', 'LM_FORECAST_HEADER_ARCHIVE'),
        t_table_rec('OU_LM', 'LEGACY_FORECAST_ITEM', 'LEGACY_FORECAST_ITEM', 'LM_FORECAST_ITEM_ARCHIVE'),
        t_table_rec('OU_LM', 'LEGACY_QR_ADJ_HEADER', 'LEGACY_QR_ADJ_HEADER', 'LM_QRE_ADJUSTMENTS_HEADER_ARCHIVE'),
        t_table_rec('OU_LM', 'LEGACY_QR_ADJ_ITEM', 'LEGACY_QR_ADJ_ITEM', 'LM_QRE_ADJUSTMENTS_ITEM_ARCHIVE'),
        t_table_rec('OU_LM', 'LEGACY_QR_ADJ_ITEM_HEADER', 'LEGACY_QR_ADJ_ITEM_HEADER', 'LM_QRE_ADJUSTMENTS_ITEM_HEADER_ARCHIVE'),
        t_table_rec('OU_LM', 'LEGACY_TTS_HEADER', 'LEGACY_TTS_HEADER', 'LM_TTS_HEADER_ARCHIVE'),
        t_table_rec('OU_LM', 'LEGACY_TTS_ITEM', 'LEGACY_TTS_ITEM', 'LM_TTS_ITEM_ARCHIVE')
    );
    
    -- Query each table for record count comparison
    FOR i IN 1..vTables.COUNT LOOP
        BEGIN
            -- Get source table count
            EXECUTE IMMEDIATE 'SELECT COUNT(*) FROM ' || vTables(i).schema_name || '.' || vTables(i).table_name
                INTO vSourceCount;
            
            -- Get archive table count
            BEGIN
                EXECUTE IMMEDIATE 'SELECT COUNT(*) FROM ODS.' || vTables(i).archive_table_name
                    INTO vArchiveCount;
            EXCEPTION
                WHEN OTHERS THEN
                    vArchiveCount := -1; -- Mark as archive error
            END;
            
            -- Display comparison
            DBMS_OUTPUT.PUT_LINE(
                RPAD(vTables(i).display_name, 40) || 
                RPAD(vTables(i).schema_name, 12) || 
                LPAD(TO_CHAR(vSourceCount), 15) ||
                LPAD(CASE WHEN vArchiveCount = -1 THEN 'ERROR' ELSE TO_CHAR(vArchiveCount) END, 15) ||
                LPAD(CASE WHEN vArchiveCount = -1 THEN 'N/A' ELSE TO_CHAR(vSourceCount - vArchiveCount) END, 10) ||
                ' ' || CASE 
                    WHEN vArchiveCount = -1 THEN 'ARCH_ERROR'
                    WHEN vSourceCount = vArchiveCount THEN 'MATCH'
                    WHEN vSourceCount > vArchiveCount THEN 'SOURCE_HIGHER'
                    ELSE 'ARCHIVE_HIGHER'
                END
            );
            
            vTotalSourceRecords := vTotalSourceRecords + vSourceCount;
            IF vArchiveCount > 0 THEN
                vTotalArchiveRecords := vTotalArchiveRecords + vArchiveCount;
            END IF;
            
        EXCEPTION
            WHEN OTHERS THEN
                DBMS_OUTPUT.PUT_LINE(
                    RPAD(vTables(i).display_name, 40) || 
                    RPAD(vTables(i).schema_name, 12) || 
                    LPAD('ERROR', 15) ||
                    LPAD('ERROR', 15) ||
                    LPAD('N/A', 10) ||
                    ' SOURCE_ERROR'
                );
        END;
    END LOOP;
    
    DBMS_OUTPUT.PUT_LINE('');
    DBMS_OUTPUT.PUT_LINE('=====================================================================================');
    DBMS_OUTPUT.PUT_LINE('RECORD COUNT SUMMARY:');
    DBMS_OUTPUT.PUT_LINE('  Total tables compared: ' || vTables.COUNT);
    DBMS_OUTPUT.PUT_LINE('  Total source records: ' || TO_CHAR(vTotalSourceRecords));
    DBMS_OUTPUT.PUT_LINE('  Total archive records: ' || TO_CHAR(vTotalArchiveRecords));
    DBMS_OUTPUT.PUT_LINE('  Total difference: ' || TO_CHAR(vTotalSourceRecords - vTotalArchiveRecords));
    DBMS_OUTPUT.PUT_LINE('');
    IF vTotalSourceRecords = vTotalArchiveRecords THEN
        DBMS_OUTPUT.PUT_LINE('VALIDATION RESULT: PASS - Source and Archive record counts match perfectly');
    ELSE
        DBMS_OUTPUT.PUT_LINE('VALIDATION RESULT: REVIEW - Source and Archive record counts differ');
        DBMS_OUTPUT.PUT_LINE('  Check individual table statuses above for detailed analysis');
    END IF;
    DBMS_OUTPUT.PUT_LINE('');
    DBMS_OUTPUT.PUT_LINE('LEGEND:');
    DBMS_OUTPUT.PUT_LINE('  MATCH - Source and Archive counts are identical');
    DBMS_OUTPUT.PUT_LINE('  SOURCE_HIGHER - Source has more records than Archive');
    DBMS_OUTPUT.PUT_LINE('  ARCHIVE_HIGHER - Archive has more records than Source');
    DBMS_OUTPUT.PUT_LINE('  ARCH_ERROR - Archive table access error');
    DBMS_OUTPUT.PUT_LINE('  SOURCE_ERROR - Source table access error');
    DBMS_OUTPUT.PUT_LINE('=====================================================================================');
    
EXCEPTION
    WHEN OTHERS THEN
        DBMS_OUTPUT.PUT_LINE('');
        DBMS_OUTPUT.PUT_LINE('VERIFICATION ERROR: ' || SQLERRM);
        RAISE;
END;
/
