/**
 * Unit tests for GET /api/ivanti/todo-queue/ticket-links endpoint
 * Validates: Requirements 6.3, 6.4
 */
const http = require('http');
const express = require('express');

// Mock auth middleware
jest.mock('../middleware/auth', () => ({
    requireAuth: () => (req, _res, next) => {
        req.user = { id: 7, username: 'testuser' };
        next();
    },
    requireGroup: () => (_req, _res, next) => next(),
}));

// Mock audit log
jest.mock('../helpers/auditLog', () => jest.fn());

// Mock the db pool
jest.mock('../db', () => ({
    query: jest.fn(() => Promise.resolve({ rows: [] })),
    connect: jest.fn(),
}));

const pool = require('../db');
const createIvantiTodoQueueRouter = require('../routes/ivantiTodoQueue');

/**
 * Helper: send an HTTP request and return { statusCode, body }.
 */
function request(server, method, path) {
    return new Promise((resolve, reject) => {
        const addr = server.address();
        const options = {
            hostname: '127.0.0.1',
            port: addr.port,
            path,
            method,
            headers: { 'Content-Type': 'application/json' },
        };

        const req = http.request(options, (res) => {
            const chunks = [];
            res.on('data', (chunk) => chunks.push(chunk));
            res.on('end', () => {
                const raw = Buffer.concat(chunks).toString();
                let body;
                try { body = JSON.parse(raw); } catch { body = raw; }
                resolve({ statusCode: res.statusCode, body });
            });
        });

        req.on('error', reject);
        req.end();
    });
}

describe('GET /api/ivanti/todo-queue/ticket-links', () => {
    let app;
    let server;

    beforeAll((done) => {
        app = express();
        app.use(express.json());
        app.use('/api/ivanti/todo-queue', createIvantiTodoQueueRouter());
        server = app.listen(0, '127.0.0.1', done);
    });

    afterAll((done) => {
        server.close(done);
    });

    beforeEach(() => {
        jest.clearAllMocks();
    });

    it('returns an empty links object when no associations exist', async () => {
        pool.query.mockResolvedValueOnce({ rows: [] });

        const res = await request(server, 'GET', '/api/ivanti/todo-queue/ticket-links');

        expect(res.statusCode).toBe(200);
        expect(res.body).toEqual({ links: {} });
    });

    it('returns a map of queue_item_id to ticket info', async () => {
        pool.query.mockResolvedValueOnce({
            rows: [
                { queue_item_id: 12, ticket_key: 'VULN-789', jira_url: 'https://jira.example.com/browse/VULN-789' },
                { queue_item_id: 15, ticket_key: 'VULN-789', jira_url: 'https://jira.example.com/browse/VULN-789' },
                { queue_item_id: 22, ticket_key: 'VULN-801', jira_url: 'https://jira.example.com/browse/VULN-801' },
            ],
        });

        const res = await request(server, 'GET', '/api/ivanti/todo-queue/ticket-links');

        expect(res.statusCode).toBe(200);
        expect(res.body).toEqual({
            links: {
                '12': { ticket_key: 'VULN-789', jira_url: 'https://jira.example.com/browse/VULN-789' },
                '15': { ticket_key: 'VULN-789', jira_url: 'https://jira.example.com/browse/VULN-789' },
                '22': { ticket_key: 'VULN-801', jira_url: 'https://jira.example.com/browse/VULN-801' },
            },
        });
    });

    it('filters by the authenticated user ID', async () => {
        pool.query.mockResolvedValueOnce({ rows: [] });

        await request(server, 'GET', '/api/ivanti/todo-queue/ticket-links');

        const [sql, params] = pool.query.mock.calls[0];
        expect(sql).toContain('q.user_id = $1');
        expect(params).toEqual([7]);
    });

    it('joins jira_ticket_queue_items with jira_tickets and ivanti_todo_queue', async () => {
        pool.query.mockResolvedValueOnce({ rows: [] });

        await request(server, 'GET', '/api/ivanti/todo-queue/ticket-links');

        const [sql] = pool.query.mock.calls[0];
        expect(sql).toContain('jira_ticket_queue_items');
        expect(sql).toContain('JOIN jira_tickets');
        expect(sql).toContain('JOIN ivanti_todo_queue');
    });

    it('returns 500 on database error', async () => {
        pool.query.mockRejectedValueOnce(new Error('DB connection failed'));

        const res = await request(server, 'GET', '/api/ivanti/todo-queue/ticket-links');

        expect(res.statusCode).toBe(500);
        expect(res.body).toEqual({ error: 'Internal server error.' });
    });
});
