"use strict";
/**
 * Cycle Monitoring Routes for SyncV2
 * These endpoints enable monitoring of cycle consistency across the network
 */
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
    if (k2 === undefined) k2 = k;
    var desc = Object.getOwnPropertyDescriptor(m, k);
    if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
      desc = { enumerable: true, get: function() { return m[k]; } };
    }
    Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
    if (k2 === undefined) k2 = k;
    o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
    Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
    o["default"] = v;
});
var __importStar = (this && this.__importStar) || (function () {
    var ownKeys = function(o) {
        ownKeys = Object.getOwnPropertyNames || function (o) {
            var ar = [];
            for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
            return ar;
        };
        return ownKeys(o);
    };
    return function (mod) {
        if (mod && mod.__esModule) return mod;
        var result = {};
        if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
        __setModuleDefault(result, mod);
        return result;
    };
})();
Object.defineProperty(exports, "__esModule", { value: true });
exports.registerCycleMonitoringRoutes = registerCycleMonitoringRoutes;
const CycleChain = __importStar(require("../CycleChain"));
const CycleCreator_1 = require("../CycleCreator");
const crypto = __importStar(require("@shardeum-foundation/lib-crypto-utils"));
const nestedCounters_1 = require("../../utils/nestedCounters");
const debugMiddleware_1 = require("../../network/debugMiddleware");
/**
 * Find missing cycles in the current cycle chain
 */
function findMissingCycles() {
    const missing = [];
    if (!CycleChain.oldest || !CycleChain.newest)
        return missing;
    const expectedStart = Math.max(1, CycleChain.newest.counter - CycleCreator_1.MAX_CYCLES_TO_KEEP + 1);
    const start = Math.max(expectedStart, CycleChain.oldest.counter);
    for (let i = start; i <= CycleChain.newest.counter; i++) {
        if (!CycleChain.cycles.find((c) => c.counter === i)) {
            missing.push(i);
        }
    }
    return missing;
}
/**
 * Calculate hash of the entire cycle chain for quick comparison
 */
function calculateCycleChainHash() {
    if (CycleChain.cycles.length === 0)
        return '';
    // Concatenate all cycle markers in order
    const markers = CycleChain.cycles.map((c) => CycleChain.computeCycleMarker(c)).join('');
    return crypto.hash(markers);
}
/**
 * Check if cycle storage is healthy
 */
function checkCycleStorageHealth() {
    const missing = findMissingCycles();
    const gaps = [];
    // Convert missing array to gap ranges
    if (missing.length > 0) {
        let gapStart = missing[0];
        let gapEnd = missing[0];
        for (let i = 1; i < missing.length; i++) {
            if (missing[i] === gapEnd + 1) {
                gapEnd = missing[i];
            }
            else {
                gaps.push({ start: gapStart, end: gapEnd });
                gapStart = missing[i];
                gapEnd = missing[i];
            }
        }
        gaps.push({ start: gapStart, end: gapEnd });
    }
    const hasRequiredHistory = CycleChain.cycles.length >= Math.min(CycleCreator_1.MAX_CYCLES_TO_KEEP, CycleChain.newest?.counter || 0);
    const isHealthy = gaps.length === 0 && hasRequiredHistory;
    return {
        isHealthy,
        hasRequiredHistory,
        consecutiveCycles: CycleChain.cycles.length - gaps.length,
        gaps,
    };
}
/**
 * Register cycle monitoring routes with debug middleware
 * All routes require high security level (DevSecurityLevel.High)
 */
function registerCycleMonitoringRoutes(network) {
    /**
     * Get comprehensive cycle inventory
     */
    network.registerExternalGet('cycle-inventory', debugMiddleware_1.isDebugModeMiddlewareHigh, (_req, res) => {
        nestedCounters_1.nestedCountersInstance.countEvent('sync2', 'cycle-inventory');
        try {
            const missing = findMissingCycles();
            const inventory = {
                currentCycle: CycleChain.newest?.counter || 0,
                oldestStoredCycle: CycleChain.oldest?.counter || 0,
                newestStoredCycle: CycleChain.newest?.counter || 0,
                totalCyclesStored: CycleChain.cycles.length,
                maxCyclesToKeep: CycleCreator_1.MAX_CYCLES_TO_KEEP,
                cycleMarkers: CycleChain.cycles.map((c) => CycleChain.computeCycleMarker(c)),
                missingCycles: missing,
                pruneHistory: {
                    // These would need to be tracked in CycleChain module
                    lastPruneTime: null,
                    lastPrunedCycle: null,
                },
            };
            res.json(inventory);
        }
        catch (error) {
            res.status(500).json({
                error: 'Failed to get cycle inventory',
                message: error.message,
            });
        }
    });
    /**
     * Get hash of cycle chain for quick comparison
     */
    network.registerExternalGet('cycle-chain-hash', debugMiddleware_1.isDebugModeMiddlewareHigh, (_req, res) => {
        nestedCounters_1.nestedCountersInstance.countEvent('sync2', 'cycle-chain-hash');
        try {
            const chainHash = calculateCycleChainHash();
            const response = {
                chainHash,
                cycleRange: {
                    start: CycleChain.oldest?.counter || 0,
                    end: CycleChain.newest?.counter || 0,
                },
                cycleCount: CycleChain.cycles.length,
                timestamp: Date.now(),
            };
            res.json(response);
        }
        catch (error) {
            res.status(500).json({
                error: 'Failed to calculate chain hash',
                message: error.message,
            });
        }
    });
    /**
     * Get cycle storage health status
     */
    network.registerExternalGet('cycle-storage-health', debugMiddleware_1.isDebugModeMiddlewareHigh, (_req, res) => {
        nestedCounters_1.nestedCountersInstance.countEvent('sync2', 'cycle-storage-health');
        try {
            const health = checkCycleStorageHealth();
            const validationStatus = {
                allCyclesValid: true, // Would need actual validation
                invalidCycles: [],
                chainIntegrity: 'intact',
            };
            // Validate chain integrity
            for (let i = 1; i < CycleChain.cycles.length; i++) {
                const current = CycleChain.cycles[i];
                const previous = CycleChain.cycles[i - 1];
                const previousMarker = CycleChain.computeCycleMarker(previous);
                if (current.previous !== previousMarker) {
                    validationStatus.allCyclesValid = false;
                    validationStatus.invalidCycles.push(current.counter);
                    validationStatus.chainIntegrity = 'broken';
                }
            }
            const response = {
                isHealthy: health.isHealthy,
                hasRequiredHistory: health.hasRequiredHistory,
                consecutiveCycles: health.consecutiveCycles,
                gaps: health.gaps,
                validationStatus,
                storageStats: {
                    cyclesInMemory: CycleChain.cycles.length,
                    oldestCycle: CycleChain.oldest?.counter || 0,
                    newestCycle: CycleChain.newest?.counter || 0,
                    memoryUsageBytes: null, // Would need to calculate actual memory usage
                },
            };
            res.json(response);
        }
        catch (error) {
            res.status(500).json({
                error: 'Failed to check storage health',
                message: error.message,
            });
        }
    });
    /**
     * Get multiple cycle markers in batch
     */
    network.registerExternalGet('cycle-markers-batch', debugMiddleware_1.isDebugModeMiddlewareHigh, (req, res) => {
        nestedCounters_1.nestedCountersInstance.countEvent('sync2', 'cycle-markers-batch');
        try {
            const start = parseInt(req.query.start) || 1;
            const end = parseInt(req.query.end) || start + 10;
            const maxRange = 100;
            // Validate range
            if (end < start) {
                return res.status(400).json({ error: 'Invalid range: end must be >= start' });
            }
            if (end - start > maxRange) {
                return res.status(400).json({
                    error: `Range too large. Maximum ${maxRange} cycles allowed`,
                });
            }
            const markers = {};
            const missing = [];
            for (let i = start; i <= end; i++) {
                const cycle = CycleChain.cycles.find((c) => c.counter === i);
                if (cycle) {
                    markers[i.toString()] = CycleChain.computeCycleMarker(cycle);
                }
                else {
                    missing.push(i);
                }
            }
            res.json({ markers, missing });
        }
        catch (error) {
            res.status(500).json({
                error: 'Failed to get cycle markers',
                message: error.message,
            });
        }
    });
}
//# sourceMappingURL=cycle-monitoring-routes.js.map