// Migration Idempotency Integration Test
// This test requires a running PostgreSQL instance with DATABASE_URL configured in backend/.env.
// It runs ALL Postgres migrations twice (via run-all.js) to verify they are idempotent (safe to re-run),
// then checks that key tables and columns exist.
//
// SKIPS AUTOMATICALLY when DATABASE_URL is not set (e.g., in CI environments without DB access).
//
// Run separately: npx jest backend/__tests__/migrations-idempotency.integration.test.js --forceExit

const { execSync } = require('child_process');
const path = require('path');
const fs = require('fs');

const BACKEND_DIR = path.join(__dirname, '..');

// Load .env manually to check for DATABASE_URL without triggering db.js process.exit
function loadEnvFile() {
    const envPath = path.join(BACKEND_DIR, '.env');
    if (!fs.existsSync(envPath)) return {};
    const content = fs.readFileSync(envPath, 'utf8');
    const vars = {};
    for (const line of content.split('\n')) {
        const trimmed = line.trim();
        if (!trimmed || trimmed.startsWith('#')) continue;
        const eqIdx = trimmed.indexOf('=');
        if (eqIdx === -1) continue;
        vars[trimmed.slice(0, eqIdx)] = trimmed.slice(eqIdx + 1);
    }
    return vars;
}

const envVars = loadEnvFile();
const hasDatabase = !!(process.env.DATABASE_URL || envVars.DATABASE_URL);

// Skip entire suite if no database is available
const describeIfDb = hasDatabase ? describe : describe.skip;

let pool;

if (hasDatabase) {
    // Set DATABASE_URL in process.env so db.js picks it up
    if (!process.env.DATABASE_URL && envVars.DATABASE_URL) {
        process.env.DATABASE_URL = envVars.DATABASE_URL;
    }
    pool = require('../db');
}

function runAllMigrations() {
    execSync('node migrations/run-all.js', {
        cwd: BACKEND_DIR,
        stdio: 'pipe',
        timeout: 30000,
    });
}

afterAll(async () => {
    if (pool) await pool.end();
});

describeIfDb('Migration Idempotency', () => {
    it('runs all migrations twice without errors (idempotent)', () => {
        // First run
        runAllMigrations();
        // Second run — should not throw if migrations are truly idempotent
        runAllMigrations();
    }, 30000);

    it('key tables exist after migrations', async () => {
        const expectedTables = [
            'compliance_items',
            'compliance_item_history',
            'compliance_notes',
            'jira_tickets',
            'ivanti_fp_submissions',
        ];

        const { rows } = await pool.query(`
            SELECT table_name
            FROM information_schema.tables
            WHERE table_schema = 'public'
              AND table_name = ANY($1)
        `, [expectedTables]);

        const foundTables = rows.map(r => r.table_name);
        for (const table of expectedTables) {
            expect(foundTables).toContain(table);
        }
    }, 30000);

    it('compliance_item_history has expected columns', async () => {
        const expectedColumns = [
            'id',
            'hostname',
            'field_name',
            'old_value',
            'new_value',
            'change_reason',
            'changed_by',
            'changed_at',
            'metric_id',
        ];

        const { rows } = await pool.query(`
            SELECT column_name
            FROM information_schema.columns
            WHERE table_schema = 'public'
              AND table_name = 'compliance_item_history'
        `);

        const foundColumns = rows.map(r => r.column_name);
        for (const col of expectedColumns) {
            expect(foundColumns).toContain(col);
        }
    }, 30000);
});
