/**
 * /api/search authz regression test.
 *
 * Auditor finding (2026-06-01): the search route's monitor + incident
 * queries had no scoping for non-ADMIN roles — directly contradicting
 * the MonitorAuthorization policy enforced everywhere else. A VIEWER or
 * EDITOR could surface the names/URLs of monitors owned by other users
 * and the titles of incidents in regions they don't manage.
 *
 * These tests assert:
 *   - ADMIN: queries are unscoped (legacy behavior preserved).
 *   - non-ADMIN: monitors are scoped to `userId === session.user.id`.
 *   - non-ADMIN: incidents are scoped to the user's assigned countries
 *     (or 'Global' fallback when the user has no countries).
 *   - Templates / Settings continue to be admin-gated (regression cover).
 */
process.env.NEXTAUTH_SECRET = process.env.NEXTAUTH_SECRET || 'this-is-a-long-enough-secret-1';

jest.mock('@/lib/prisma', () => ({
    prisma: {
        user: { findUnique: jest.fn() },
        monitor: { findMany: jest.fn() },
        statusIncident: { findMany: jest.fn() },
        emailTemplate: { findMany: jest.fn() },
        systemSetting: { findMany: jest.fn() },
    },
}));

jest.mock('next-auth', () => ({
    getServerSession: jest.fn(),
}));

import { GET } from '../route';
import { prisma } from '@/lib/prisma';
import { getServerSession } from 'next-auth';

const mockSession = getServerSession as jest.Mock;
const mockMonitorFindMany = prisma.monitor.findMany as jest.Mock;
const mockIncidentFindMany = prisma.statusIncident.findMany as jest.Mock;
const mockUserFindUnique = prisma.user.findUnique as jest.Mock;
const mockTemplateFindMany = prisma.emailTemplate.findMany as jest.Mock;
const mockSettingFindMany = prisma.systemSetting.findMany as jest.Mock;

function makeRequest(): Request {
    return new Request('http://localhost/api/search?q=test');
}

describe('GET /api/search — non-ADMIN scoping (auditor 2026-06-01 IDOR fix)', () => {
    beforeEach(() => {
        jest.clearAllMocks();
        mockMonitorFindMany.mockResolvedValue([]);
        mockIncidentFindMany.mockResolvedValue([]);
        mockTemplateFindMany.mockResolvedValue([]);
        mockSettingFindMany.mockResolvedValue([]);
    });

    it('VIEWER: monitors query scopes by userId === session.user.id', async () => {
        mockSession.mockResolvedValue({ user: { id: '42', role: 'VIEWER' } });
        mockUserFindUnique.mockResolvedValue({ id: 42, countries: [] });

        await GET(makeRequest());

        const monitorCall = mockMonitorFindMany.mock.calls[0]?.[0];
        expect(monitorCall).toBeDefined();
        expect(monitorCall.where.userId).toBe(42);
    });

    it('EDITOR: monitors query scopes by userId === session.user.id', async () => {
        mockSession.mockResolvedValue({ user: { id: '7', role: 'EDITOR' } });
        mockUserFindUnique.mockResolvedValue({ id: 7, countries: [] });

        await GET(makeRequest());

        const monitorCall = mockMonitorFindMany.mock.calls[0]?.[0];
        expect(monitorCall.where.userId).toBe(7);
    });

    it('ADMIN: monitors query is unscoped (no userId restriction)', async () => {
        mockSession.mockResolvedValue({ user: { id: '1', role: 'ADMIN' } });

        await GET(makeRequest());

        const monitorCall = mockMonitorFindMany.mock.calls[0]?.[0];
        expect(monitorCall.where.userId).toBeUndefined();
    });

    it('ADMIN_READ_ONLY: monitors query is unscoped', async () => {
        mockSession.mockResolvedValue({ user: { id: '2', role: 'ADMIN_READ_ONLY' } });

        await GET(makeRequest());

        const monitorCall = mockMonitorFindMany.mock.calls[0]?.[0];
        expect(monitorCall.where.userId).toBeUndefined();
    });

    it('VIEWER with assigned countries: incidents scoped to those country ids', async () => {
        mockSession.mockResolvedValue({ user: { id: '42', role: 'VIEWER' } });
        mockUserFindUnique.mockResolvedValue({
            id: 42,
            countries: [{ id: 10 }, { id: 20 }],
        });

        await GET(makeRequest());

        const incidentCall = mockIncidentFindMany.mock.calls[0]?.[0];
        expect(incidentCall.where.countries).toEqual({
            some: { id: { in: [10, 20] } },
        });
    });

    it('VIEWER with NO assigned countries: incidents fall back to Global', async () => {
        mockSession.mockResolvedValue({ user: { id: '42', role: 'VIEWER' } });
        mockUserFindUnique.mockResolvedValue({ id: 42, countries: [] });

        await GET(makeRequest());

        const incidentCall = mockIncidentFindMany.mock.calls[0]?.[0];
        expect(incidentCall.where.countries).toEqual({
            some: { name: 'Global' },
        });
    });

    it('ADMIN: incidents query is unscoped', async () => {
        mockSession.mockResolvedValue({ user: { id: '1', role: 'ADMIN' } });

        await GET(makeRequest());

        const incidentCall = mockIncidentFindMany.mock.calls[0]?.[0];
        expect(incidentCall.where.countries).toBeUndefined();
    });

    it('VIEWER: emailTemplate + systemSetting queries are NOT executed (admin-gated)', async () => {
        mockSession.mockResolvedValue({ user: { id: '42', role: 'VIEWER' } });
        mockUserFindUnique.mockResolvedValue({ id: 42, countries: [] });

        await GET(makeRequest());

        expect(mockTemplateFindMany).not.toHaveBeenCalled();
        expect(mockSettingFindMany).not.toHaveBeenCalled();
    });

    it('Unauthenticated: returns 401 without hitting Prisma', async () => {
        mockSession.mockResolvedValue(null);

        const res = await GET(makeRequest());

        expect(res.status).toBe(401);
        expect(mockMonitorFindMany).not.toHaveBeenCalled();
        expect(mockIncidentFindMany).not.toHaveBeenCalled();
    });
});
