import { describe, it, expect, beforeAll, afterAll } from 'vitest';
import { buildApp } from '../../app.js';
import { parseEnvFile } from '../settings-routes.js';
describe('integration routes', () => {
    let app;
    let cookie;
    beforeAll(async () => {
        app = await buildApp({ config: { jwtSecret: 'test-secret-integrations' } });
        await app.ready();
        const loginRes = await app.inject({
            method: 'POST',
            url: '/api/auth/login',
            payload: { username: 'admin', password: 'admin' },
        });
        const cookies = loginRes.cookies;
        const access = cookies.find((c) => c.name === 'access_token');
        const refresh = cookies.find((c) => c.name === 'refresh_token');
        cookie = `access_token=${access.value}; refresh_token=${refresh.value}`;
        // Clean table from previous runs
        app.db.exec('DELETE FROM integrations');
    });
    afterAll(async () => {
        // Clean up: remove all test integrations so env keys don't persist
        app.db.exec('DELETE FROM integrations');
        // Clean env keys written by tests
        for (const key of Object.keys(process.env)) {
            if (/^(GITHUB|TELEGRAM|BREVO|DISCORD)_/.test(key)) {
                delete process.env[key];
            }
        }
        // Rewrite .env without test keys
        const envPath = process.env.DOTENV_PATH ?? new URL('../../../../.env', import.meta.url).pathname;
        const entries = parseEnvFile(envPath);
        for (const k of [...entries.keys()]) {
            if (/^(GITHUB|TELEGRAM|BREVO|DISCORD)_/.test(k)) {
                entries.delete(k);
            }
        }
        const { writeEnvFile } = await import('../settings-routes.js');
        writeEnvFile(envPath, entries);
        await app.close();
    });
    it('GET /api/integrations/catalog — returns provider catalog', async () => {
        const res = await app.inject({
            method: 'GET',
            url: '/api/integrations/catalog',
            headers: { cookie },
        });
        expect(res.statusCode).toBe(200);
        const body = res.json();
        expect(body.providers).toBeInstanceOf(Array);
        expect(body.providers.length).toBeGreaterThanOrEqual(30);
        const github = body.providers.find((p) => p.key === 'github');
        expect(github).toBeDefined();
        expect(github.name).toBe('GitHub');
        expect(github.category).toBe('dev');
        expect(github.fields.length).toBeGreaterThanOrEqual(1);
    });
    it('GET /api/integrations — returns empty list initially', async () => {
        const res = await app.inject({
            method: 'GET',
            url: '/api/integrations',
            headers: { cookie },
        });
        expect(res.statusCode).toBe(200);
        const body = res.json();
        expect(body.integrations).toEqual([]);
    });
    it('PATCH /api/integrations/:provider — creates a new integration', async () => {
        const res = await app.inject({
            method: 'PATCH',
            url: '/api/integrations/github',
            headers: { cookie },
            payload: {
                enabled: true,
                config: { token: 'ghp_abc123def456ghi789', org: 'my-org' },
            },
        });
        expect(res.statusCode).toBe(200);
        const body = res.json();
        expect(body.integration.provider).toBe('github');
        expect(body.integration.enabled).toBe(true);
        // Token should be masked
        expect(body.integration.config.token).toContain('••••');
        expect(body.integration.config.token).not.toBe('ghp_abc123def456ghi789');
        // Org is plain text, not masked
        expect(body.integration.config.org).toBe('my-org');
    });
    it('PATCH /api/integrations/:provider — updates existing integration', async () => {
        // First create
        await app.inject({
            method: 'PATCH',
            url: '/api/integrations/telegram',
            headers: { cookie },
            payload: {
                enabled: true,
                config: { bot_token: 'secret-bot-token-123', default_chat_id: '-100123' },
            },
        });
        // Update only chat_id, send masked token back
        const res = await app.inject({
            method: 'PATCH',
            url: '/api/integrations/telegram',
            headers: { cookie },
            payload: {
                config: { bot_token: 'secr••••23', default_chat_id: '-100456' },
            },
        });
        expect(res.statusCode).toBe(200);
        const body = res.json();
        expect(body.integration.config.default_chat_id).toBe('-100456');
        // Token should still be masked (preserved original)
        expect(body.integration.config.bot_token).toContain('••••');
    });
    it('PATCH /api/integrations/:provider — rejects unknown provider', async () => {
        const res = await app.inject({
            method: 'PATCH',
            url: '/api/integrations/unknown_service',
            headers: { cookie },
            payload: { enabled: true, config: {} },
        });
        expect(res.statusCode).toBe(400);
        expect(res.json().error).toContain('Unknown provider');
    });
    it('PATCH /api/integrations/:provider — toggles enabled', async () => {
        await app.inject({
            method: 'PATCH',
            url: '/api/integrations/brevo',
            headers: { cookie },
            payload: { enabled: true, config: { api_key: 'xkeysib-test123' } },
        });
        const res = await app.inject({
            method: 'PATCH',
            url: '/api/integrations/brevo',
            headers: { cookie },
            payload: { enabled: false },
        });
        expect(res.statusCode).toBe(200);
        expect(res.json().integration.enabled).toBe(false);
    });
    it('GET /api/integrations — lists configured integrations', async () => {
        const res = await app.inject({
            method: 'GET',
            url: '/api/integrations',
            headers: { cookie },
        });
        expect(res.statusCode).toBe(200);
        const body = res.json();
        expect(body.integrations.length).toBeGreaterThanOrEqual(1);
        // All secrets should be masked
        for (const integ of body.integrations) {
            expect(integ.provider).toBeDefined();
            expect(typeof integ.enabled).toBe('boolean');
        }
    });
    it('DELETE /api/integrations/:provider — deletes an integration', async () => {
        await app.inject({
            method: 'PATCH',
            url: '/api/integrations/discord',
            headers: { cookie },
            payload: { enabled: true, config: { bot_token: 'tok123' } },
        });
        const res = await app.inject({
            method: 'DELETE',
            url: '/api/integrations/discord',
            headers: { cookie },
        });
        expect(res.statusCode).toBe(200);
        expect(res.json().ok).toBe(true);
        // Verify deleted
        const delRes = await app.inject({
            method: 'DELETE',
            url: '/api/integrations/discord',
            headers: { cookie },
        });
        expect(delRes.statusCode).toBe(404);
    });
    it('PATCH syncs enabled integration config to .env', async () => {
        await app.inject({
            method: 'PATCH',
            url: '/api/integrations/github',
            headers: { cookie },
            payload: {
                enabled: true,
                config: { token: 'ghp_testtoken123', org: 'test-org' },
            },
        });
        // Check process.env was updated
        expect(process.env.GITHUB_TOKEN).toBe('ghp_testtoken123');
        expect(process.env.GITHUB_ORG).toBe('test-org');
        // Check .env file was updated
        const envPath = process.env.DOTENV_PATH ?? new URL('../../../../.env', import.meta.url).pathname;
        const entries = parseEnvFile(envPath);
        expect(entries.get('GITHUB_TOKEN')).toBe('ghp_testtoken123');
        expect(entries.get('GITHUB_ORG')).toBe('test-org');
    });
    it('DELETE removes integration keys from .env', async () => {
        // Create first
        await app.inject({
            method: 'PATCH',
            url: '/api/integrations/discord',
            headers: { cookie },
            payload: { enabled: true, config: { bot_token: 'test-discord-tok' } },
        });
        expect(process.env.DISCORD_BOT_TOKEN).toBe('test-discord-tok');
        // Delete
        await app.inject({
            method: 'DELETE',
            url: '/api/integrations/discord',
            headers: { cookie },
        });
        expect(process.env.DISCORD_BOT_TOKEN).toBeUndefined();
        const envPath = process.env.DOTENV_PATH ?? new URL('../../../../.env', import.meta.url).pathname;
        const entries = parseEnvFile(envPath);
        expect(entries.has('DISCORD_BOT_TOKEN')).toBe(false);
    });
    it('disabled integration removes keys from .env', async () => {
        // Create enabled
        await app.inject({
            method: 'PATCH',
            url: '/api/integrations/brevo',
            headers: { cookie },
            payload: { enabled: true, config: { api_key: 'xkeysib-test' } },
        });
        expect(process.env.BREVO_API_KEY).toBe('xkeysib-test');
        // Disable
        await app.inject({
            method: 'PATCH',
            url: '/api/integrations/brevo',
            headers: { cookie },
            payload: { enabled: false },
        });
        expect(process.env.BREVO_API_KEY).toBeUndefined();
    });
    it('rejects unauthenticated requests', async () => {
        const res = await app.inject({
            method: 'GET',
            url: '/api/integrations',
        });
        expect(res.statusCode).toBe(401);
    });
});
//# sourceMappingURL=integration-routes.test.js.map