import assert from 'node:assert/strict';
import { config } from '../src/config/index.js';
import { healthTracker } from '../src/services/healthTracker.js';
import {
    ReconciliationWatchdogAutoResumeService,
    type WatchdogAutoResumeCycleMetrics
} from '../src/services/reconciliationWatchdogAutoResumeService.js';

type MutableConfig = typeof config & Record<string, any>;
const mutableConfig = config as MutableConfig;

const restoreConfig = (snapshot: Record<string, unknown>) => {
    for (const [key, value] of Object.entries(snapshot)) {
        mutableConfig[key] = value;
    }
};

const setTradingControl = (mode: 'RUNNING' | 'PAUSED', lastChangedBy: string, lastChangedAt: number, reason?: string) => {
    healthTracker.recordTradingControl({
        mode,
        lastChangedBy,
        lastChangedAt,
        reason
    });
};

const cleanMetrics = (): WatchdogAutoResumeCycleMetrics => ({
    success: true,
    mismatchCount: 0,
    missingFromExchange: 0,
    missingInDb: 0,
    noGoTrades: 0,
    parityMismatchTrades: 0,
    parityQuarantinedTrades: 0,
    failedProfiles: 0,
    integrityWatchdogTriggered: false
});

const testDoesNotResumeWhenNotPaused = () => {
    const service = new ReconciliationWatchdogAutoResumeService();
    setTradingControl('RUNNING', 'test', Date.now(), 'baseline');
    const decision = service.evaluateCycle(cleanMetrics());
    assert.equal(decision.resumed, false);
    assert.equal(decision.reason, 'not_paused');
};

const testDoesNotResumeManualPause = () => {
    const service = new ReconciliationWatchdogAutoResumeService();
    setTradingControl('PAUSED', 'admin-user', Date.now() - 60_000, 'manual');
    const decision = service.evaluateCycle(cleanMetrics());
    assert.equal(decision.resumed, false);
    assert.equal(decision.reason, 'pause_not_from_parity_watchdog');
    assert.equal(healthTracker.isPaused(), true);
};

const testResumesAfterCleanStreak = () => {
    const service = new ReconciliationWatchdogAutoResumeService();
    const pauseAt = Date.now() - 120_000;
    setTradingControl('PAUSED', 'system:recon_parity_watchdog', pauseAt, 'watchdog');

    const first = service.evaluateCycle(cleanMetrics());
    assert.equal(first.resumed, false);
    assert.equal(first.cleanStreak, 1);

    const second = service.evaluateCycle(cleanMetrics());
    assert.equal(second.resumed, true, 'Second clean cycle should auto-resume when threshold=2.');
    const control = healthTracker.getSnapshot().tradingControl;
    assert.equal(control.mode, 'RUNNING');
    assert.equal(control.lastChangedBy, 'system:recon_parity_auto_resume');
};

const testDirtyCycleResetsStreak = () => {
    const service = new ReconciliationWatchdogAutoResumeService();
    const pauseAt = Date.now() - 120_000;
    setTradingControl('PAUSED', 'system:recon_parity_watchdog', pauseAt, 'watchdog');

    const first = service.evaluateCycle(cleanMetrics());
    assert.equal(first.cleanStreak, 1);

    const dirty = service.evaluateCycle({
        ...cleanMetrics(),
        mismatchCount: 1
    });
    assert.equal(dirty.resumed, false);
    assert.equal(dirty.reason, 'cycle_not_clean');
    assert.equal(dirty.cleanStreak, 0);

    const afterReset = service.evaluateCycle(cleanMetrics());
    assert.equal(afterReset.resumed, false, 'Streak must restart after dirty cycle.');
    assert.equal(afterReset.cleanStreak, 1);
};

const testMinPauseWindowBlocksResume = () => {
    const service = new ReconciliationWatchdogAutoResumeService();
    const pauseAt = Date.now() - 2_000;
    setTradingControl('PAUSED', 'system:recon_parity_watchdog', pauseAt, 'watchdog');
    const decision = service.evaluateCycle(cleanMetrics());
    assert.equal(decision.resumed, false);
    assert.equal(decision.reason, 'min_pause_window');
};

async function main() {
    const configSnapshot: Record<string, unknown> = {
        ENABLE_RECON_WATCHDOG_AUTO_RESUME: mutableConfig.ENABLE_RECON_WATCHDOG_AUTO_RESUME,
        RECON_WATCHDOG_AUTO_RESUME_MIN_PAUSE_MS: mutableConfig.RECON_WATCHDOG_AUTO_RESUME_MIN_PAUSE_MS,
        RECON_WATCHDOG_AUTO_RESUME_CLEAN_CYCLES: mutableConfig.RECON_WATCHDOG_AUTO_RESUME_CLEAN_CYCLES,
        RECON_WATCHDOG_AUTO_RESUME_COOLDOWN_MS: mutableConfig.RECON_WATCHDOG_AUTO_RESUME_COOLDOWN_MS
    };

    try {
        mutableConfig.ENABLE_RECON_WATCHDOG_AUTO_RESUME = true;
        mutableConfig.RECON_WATCHDOG_AUTO_RESUME_MIN_PAUSE_MS = 5_000;
        mutableConfig.RECON_WATCHDOG_AUTO_RESUME_CLEAN_CYCLES = 2;
        mutableConfig.RECON_WATCHDOG_AUTO_RESUME_COOLDOWN_MS = 0;

        testDoesNotResumeWhenNotPaused();
        testDoesNotResumeManualPause();
        testResumesAfterCleanStreak();
        testDirtyCycleResetsStreak();
        testMinPauseWindowBlocksResume();

        console.log('[reconciliation-watchdog-auto-resume] OK: guard, streak, and min-pause behavior validated');
    } finally {
        restoreConfig(configSnapshot);
        setTradingControl('RUNNING', 'test', Date.now(), 'reset');
    }
}

main().catch((error) => {
    console.error('[reconciliation-watchdog-auto-resume] failed', error);
    process.exit(1);
});
