jest.mock('@/lib/network-security/safe-fetch', () => ({
    safeOutboundFetch: jest.fn(),
}));

import { PagerDutyChannel } from '../pagerduty.channel';
import { safeOutboundFetch } from '@/lib/network-security/safe-fetch';

const fetchMock = safeOutboundFetch as jest.Mock;

const okResponse = () => ({ ok: true, status: 202, text: async () => '' });

describe('PagerDutyChannel', () => {
    beforeEach(() => fetchMock.mockReset());

    it('refuses without a routingKey', async () => {
        const ch = new PagerDutyChannel();
        await expect(ch.sendOrThrow('hi', {} as never)).rejects.toThrow(/routingKey/);
        expect(fetchMock).not.toHaveBeenCalled();
    });

    it('refuses a too-short routingKey', async () => {
        const ch = new PagerDutyChannel();
        await expect(ch.sendOrThrow('hi', { routingKey: 'abc' } as never)).rejects.toThrow(/routingKey/);
    });

    it('refuses an invalid severity', async () => {
        const ch = new PagerDutyChannel();
        await expect(
            ch.sendOrThrow('hi', { routingKey: 'r1234567890abcdef', severity: 'bogus' } as never),
        ).rejects.toThrow(/severity/);
    });

    it('POSTs to events.pagerduty.com with routing_key + trigger', async () => {
        fetchMock.mockResolvedValueOnce(okResponse());
        const ch = new PagerDutyChannel();
        await ch.sendOrThrow('Monitor X is DOWN', {
            routingKey: 'r1234567890abcdef',
            severity: 'critical',
        } as never);

        const [url, init, opts] = fetchMock.mock.calls[0];
        expect(url).toBe('https://events.pagerduty.com/v2/enqueue');
        const body = JSON.parse(init.body);
        expect(body.routing_key).toBe('r1234567890abcdef');
        expect(body.event_action).toBe('trigger');
        expect(body.payload.summary).toBe('Monitor X is DOWN');
        expect(body.payload.severity).toBe('critical');
        expect(opts.allowedHosts).toContain('events.pagerduty.com');
    });

    it('throws on non-2xx with the body excerpt', async () => {
        fetchMock.mockResolvedValueOnce({
            ok: false,
            status: 400,
            text: async () => 'invalid event',
        });
        const ch = new PagerDutyChannel();
        await expect(
            ch.sendOrThrow('hi', { routingKey: 'r1234567890abcdef' } as never),
        ).rejects.toThrow(/PagerDuty 400.*invalid event/);
    });

    it('truncates summaries longer than 1024 chars', async () => {
        fetchMock.mockResolvedValueOnce(okResponse());
        const ch = new PagerDutyChannel();
        await ch.sendOrThrow('x'.repeat(2000), {
            routingKey: 'r1234567890abcdef',
        } as never);
        const body = JSON.parse(fetchMock.mock.calls[0][1].body);
        expect(body.payload.summary.length).toBe(1024);
        expect(body.payload.summary.endsWith('...')).toBe(true);
    });
});
