#include <iostream>
#include <vector>
#include <fstream>
#include <sstream>
#include <cstdint>
#include <algorithm>

using namespace std;

// Force the compiler to pack this struct exactly to 12 bytes with no padding
#pragma pack(push, 1)
struct FatIndexEntry {
    uint64_t blob_offset; // 8 Bytes
    uint16_t length;      // 2 Bytes (This is the step count)
    uint16_t flags;       // 2 Bytes
};
#pragma pack(pop)

const string FILE_INDEX = "chain_index.bin";
const string OEIS_FILE = "b003313.txt";

int main() {
    cout << "=========================================" << endl;
    cout << " FAT INDEX DATABASE VERIFIER (v6.0)      " << endl;
    cout << "=========================================" << endl;

    // 1. Load the OEIS Gold Standard Database
    vector<uint8_t> oeis_cache(100005, 0); 
    ifstream gold_file(OEIS_FILE);
    int max_oeis = 0;
    
    if (gold_file.is_open()) {
        string line;
        while (getline(gold_file, line)) {
            if (line.empty() || line[0] == '#') continue;
            stringstream ss(line);
            int n, steps;
            if (ss >> n >> steps && n <= 100000) {
                oeis_cache[n] = steps;
                if (n > max_oeis) max_oeis = n;
            }
        }
        cout << "[System] Loaded OEIS A003313 up to N=" << max_oeis << endl;
    } else {
        cout << "[ERROR] Could not find " << OEIS_FILE << "!" << endl;
        return 1;
    }

    // 2. Load the New Fat Index Ledger
    ifstream index_file(FILE_INDEX, ios::binary | ios::ate);
    if (!index_file.is_open()) {
        cout << "[ERROR] Could not open " << FILE_INDEX << "!" << endl;
        return 1;
    }

    // Calculate how many numbers are actually mapped
    streampos file_size = index_file.tellg();
    int computed_count = file_size / sizeof(FatIndexEntry); // Divide by 12 bytes
    
    cout << "[System] Loaded Fat Index: " << computed_count << " records found." << endl;

    // Read the entire index into RAM (it's only ~1.2MB for 100k records, very fast)
    index_file.seekg(0, ios::beg);
    vector<FatIndexEntry> ledger(computed_count);
    index_file.read(reinterpret_cast<char*>(ledger.data()), file_size);
    index_file.close();

    if (computed_count <= 2) {
        cout << "[WARNING] Database only contains padding. No records found." << endl;
        return 0;
    }

    // 3. The Cross-Check
    int errors = 0;
    int verified = 0;
    
    // We check up to the smaller of the two databases
    int limit = min(max_oeis, computed_count - 1);

    cout << "\nVerifying N=2 to " << limit << "..." << endl;

    for (int n = 2; n <= limit; ++n) {
        if (oeis_cache[n] > 0) {
            // Read the step length directly from the Fat Index struct
            uint16_t engine_steps = ledger[n].length; 
            
            if (engine_steps != oeis_cache[n]) {
                if (errors < 15) { 
                    cout << " MISMATCH at N=" << n << " | OEIS: " << (int)oeis_cache[n] << " | Engine: " << (int)engine_steps << endl;
                }
                errors++;
            }
            verified++;
        }
    }

    // 4. The Verdict
    cout << "=========================================" << endl;
    if (errors == 0 && verified > 0) {
        cout << " [SUCCESS] 100% PARITY ACHIEVED! " << endl;
        cout << " All " << verified << " records perfectly match mathematical ground-truth." << endl;
    } else if (errors > 0) {
        cout << " [FAILED] " << errors << " Errors detected in the dataset." << endl;
        cout << " Check topological calculations." << endl;
    } else {
        cout << " [SKIPPED] No overlapping records to verify." << endl;
    }
    cout << "=========================================" << endl;

    return 0;
}
