import { describe, it, expect, vi, afterEach } from 'vitest';
import { render, screen, cleanup, waitFor } from '@testing-library/svelte';
import AuditTable from './AuditTable.svelte';
import * as adminApi from '$lib/api/admin';

afterEach(() => {
    cleanup();
    vi.restoreAllMocks();
});

function entry(over: Partial<adminApi.AuditEntry> = {}): adminApi.AuditEntry {
    return {
        id: 'a-1',
        actor_user_id: 'u-1',
        actor_username: 'alice',
        action: 'crawler_run',
        target_kind: 'crawler',
        target_id: null,
        payload: { started: true },
        at: '2026-06-01T00:00:00Z',
        ...over
    };
}

describe('AuditTable', () => {
    it('renders rows with actor + action and expands the payload on click', async () => {
        vi.spyOn(adminApi, 'listAuditLog').mockResolvedValue({
            items: [entry()],
            page: { limit: 25, offset: 0, total: 1 }
        });
        render(AuditTable);

        await waitFor(() => expect(screen.getByText('crawler_run')).toBeTruthy());
        expect(screen.getByText('alice')).toBeTruthy();
        // Payload hidden until the row is clicked.
        expect(screen.queryByText(/"started": true/)).toBeNull();
        screen.getByTestId('audit-row-a-1').click();
        await waitFor(() => expect(screen.getByText(/"started": true/)).toBeTruthy());
    });

    it('shows "system" actor when there is no actor, and "(deleted user)" when the id has no username', async () => {
        vi.spyOn(adminApi, 'listAuditLog').mockResolvedValue({
            items: [
                entry({ id: 'a-sys', actor_user_id: null, actor_username: null }),
                entry({ id: 'a-del', actor_user_id: 'u-x', actor_username: null })
            ],
            page: { limit: 25, offset: 0, total: 2 }
        });
        render(AuditTable);
        await waitFor(() => expect(screen.getByText('system')).toBeTruthy());
        expect(screen.getByText('(deleted user)')).toBeTruthy();
    });

    it('renders an empty state when there are no entries', async () => {
        vi.spyOn(adminApi, 'listAuditLog').mockResolvedValue({
            items: [],
            page: { limit: 25, offset: 0, total: 0 }
        });
        render(AuditTable);
        await waitFor(() => expect(screen.getByTestId('audit-empty')).toBeTruthy());
    });
});
