import assert from 'node:assert/strict';
import fs from 'node:fs';
import path from 'node:path';
import { fileURLToPath } from 'node:url';
import { ApiServer } from './src/services/apiServer.js';

const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);
const repoRoot = __dirname;

async function verifyStaticGuards(): Promise<void> {
    const apiServerSource = fs.readFileSync(path.join(repoRoot, 'src/services/apiServer.ts'), 'utf8');
    const supabaseSource = fs.readFileSync(path.join(repoRoot, 'src/services/SupabaseService.ts'), 'utf8');

    assert(/app\.post\('\/api\/trade',\s*this\.requireAuth/.test(apiServerSource), 'Missing auth guard on /api/trade');
    assert(/app\.post\('\/api\/close',\s*this\.requireAuth/.test(apiServerSource), 'Missing auth guard on /api/close');
    assert(/app\.post\('\/api\/chat',\s*this\.requireAuth/.test(apiServerSource), 'Missing auth guard on /api/chat');
    assert(/this\.io\.use\(async\s*\(socket,\s*next\)/.test(apiServerSource), 'Missing websocket auth middleware');
    assert(/Unauthorized:\s*missing token/.test(apiServerSource), 'Missing explicit websocket unauthorized path');
    assert(/SUPABASE_JWT_ISSUER/.test(supabaseSource), 'Missing JWT issuer check wiring');
    assert(/SUPABASE_JWT_AUDIENCE/.test(supabaseSource), 'Missing JWT audience check wiring');
    assert(/Invalid token issuer/.test(supabaseSource), 'Missing explicit invalid issuer rejection');
    assert(/Invalid token audience/.test(supabaseSource), 'Missing explicit invalid audience rejection');
}

async function verifyRuntimeGuards(): Promise<void> {
    const originalStartServer = (ApiServer.prototype as any).startServer;
    (ApiServer.prototype as any).startServer = () => undefined;

    try {
        const server = new ApiServer(0);
        const req = {
            headers: {},
            method: 'POST',
            path: '/api/trade'
        } as any;

        let statusCode = 200;
        let responseBody: any = null;
        let nextCalled = false;
        const res = {
            status(code: number) {
                statusCode = code;
                return this;
            },
            json(payload: unknown) {
                responseBody = payload;
                return this;
            }
        } as any;

        await (server as any).requireAuth(req, res, () => {
            nextCalled = true;
        });

        assert.equal(statusCode, 401, `Expected 401 for unauthorized /api/trade, got ${statusCode}`);
        assert.equal(nextCalled, false, 'Unauthorized /api/trade should not call next()');
        assert.equal(responseBody?.error, 'Unauthorized: missing bearer token');
    } finally {
        (ApiServer.prototype as any).startServer = originalStartServer;
    }
}

await verifyStaticGuards();
await verifyRuntimeGuards();
console.log('[security-guards] OK: static + unauthorized REST checks passed');
