/* eslint-disable @typescript-eslint/no-explicit-any */
import { render, screen } from '@testing-library/react';
import { beforeEach, describe, expect, it, vi } from 'vitest';

// ── Mocks ─────────────────────────────────────────────────────────────────────

vi.mock('@inertiajs/react', () => ({
    Head: ({ title }: { title: string }) => <title>{title}</title>,
    Link: ({ href, children, ...rest }: any) => (
        <a href={href} {...rest}>
            {children}
        </a>
    ),
    router: {
        get: vi.fn(),
        post: vi.fn(),
        put: vi.fn(),
        patch: vi.fn(),
        delete: vi.fn(),
        visit: vi.fn(),
    },
    usePage: vi.fn(() => ({
        props: {
            auth: { adminRole: 'super_admin', adminPermissions: [] },
            flash: {},
            errors: {},
        },
    })),
}));

vi.mock('@/lib/api', () => ({
    api: {
        get: vi.fn(),
        post: vi.fn(),
        put: vi.fn(),
        patch: vi.fn(),
        delete: vi.fn(),
    },
}));

vi.mock('sonner', () => ({ toast: { success: vi.fn(), error: vi.fn() } }));

// Mock Radix Sheet to avoid portal + jsdom issues
vi.mock('@/components/ui/sheet', () => ({
    Sheet: ({ children, open }: any) =>
        open ? (
            <div data-testid="sheet-open">{children}</div>
        ) : (
            <div data-state="closed" />
        ),
    SheetContent: ({ children }: any) => (
        <div data-testid="sheet-content">{children}</div>
    ),
    SheetHeader: ({ children }: any) => (
        <div data-testid="sheet-header">{children}</div>
    ),
    SheetTitle: ({ children, className }: any) => (
        <div data-testid="sheet-title" className={className}>
            {children}
        </div>
    ),
}));

const mockUseQuery = vi.fn();
vi.mock('@tanstack/react-query', () => ({
    useQuery: (...args: any[]) => mockUseQuery(...args),
    useQueryClient: vi.fn(() => ({
        invalidateQueries: vi.fn(),
        setQueryData: vi.fn(),
    })),
    keepPreviousData: undefined,
}));

// ── Imports (after mocks) ─────────────────────────────────────────────────────

import QuickView from '../QuickView';

const LOG_ID = '019efe5c-2f8e-7038-9c63-25c49a749457';

function makeLog(overrides = {}) {
    return {
        id: LOG_ID,
        scope: 'admin',
        event: 'user.login',
        category: 'auth',
        action: 'login',
        status: 'success',
        severity: 'info',
        actor_type: 'admin',
        actor_name: 'Alice Admin',
        actor_role: 'super_admin',
        auditable_type: null,
        auditable_id: null,
        ip_address: '192.168.1.1',
        user_agent: 'Mozilla/5.0',
        url: '/admin/dashboard',
        http_method: 'GET',
        review_status: null,
        reviewed_at: null,
        reviewed_by_name: null,
        created_at: '2025-01-01T10:00:00Z',
        changes: [],
        tags: [],
        notes: [],
        ...overrides,
    };
}

describe('QuickView', () => {
    const mockOnClose = vi.fn();
    const mockOnReviewUpdate = vi.fn();

    beforeEach(() => {
        vi.clearAllMocks();
        // Default: not loading, no data
        mockUseQuery.mockReturnValue({
            data: undefined,
            isLoading: false,
            isError: false,
            refetch: vi.fn(),
        });
    });

    it('does not render sheet content when logId is null', () => {
        // logId=null → Sheet open=false → our mock renders the closed placeholder only
        render(
            <QuickView
                logId={null}
                onClose={mockOnClose}
                onReviewUpdate={mockOnReviewUpdate}
            />,
        );
        // Sheet is closed — no SheetContent rendered
        expect(screen.queryByTestId('sheet-content')).not.toBeInTheDocument();
        // No event data rendered
        expect(screen.queryByText('user.login')).not.toBeInTheDocument();
    });

    it('shows the loading skeleton when logId is set and isLoading=true', () => {
        mockUseQuery.mockReturnValue({
            data: undefined,
            isLoading: true,
            isError: false,
            refetch: vi.fn(),
        });

        render(
            <QuickView
                logId={LOG_ID}
                onClose={mockOnClose}
                onReviewUpdate={mockOnReviewUpdate}
            />,
        );

        // Skeletons are rendered as elements with animate-pulse
        const skeletons = document.querySelectorAll('.animate-pulse');
        expect(skeletons.length).toBeGreaterThan(0);
    });

    it('shows the sr-only "Loading audit log…" title while loading', () => {
        mockUseQuery.mockReturnValue({
            data: undefined,
            isLoading: true,
            isError: false,
            refetch: vi.fn(),
        });

        render(
            <QuickView
                logId={LOG_ID}
                onClose={mockOnClose}
                onReviewUpdate={mockOnReviewUpdate}
            />,
        );

        expect(screen.getByText('Loading audit log…')).toBeInTheDocument();
    });

    it('renders the event name in the sheet title once data is loaded', () => {
        mockUseQuery.mockReturnValue({
            data: makeLog(),
            isLoading: false,
            isError: false,
            refetch: vi.fn(),
        });

        render(
            <QuickView
                logId={LOG_ID}
                onClose={mockOnClose}
                onReviewUpdate={mockOnReviewUpdate}
            />,
        );

        expect(screen.getByText('user.login')).toBeInTheDocument();
    });

    it('renders the actor name and IP address once data is loaded', () => {
        mockUseQuery.mockReturnValue({
            data: makeLog(),
            isLoading: false,
            isError: false,
            refetch: vi.fn(),
        });

        render(
            <QuickView
                logId={LOG_ID}
                onClose={mockOnClose}
                onReviewUpdate={mockOnReviewUpdate}
            />,
        );

        expect(screen.getByText('Alice Admin')).toBeInTheDocument();
        expect(screen.getByText('192.168.1.1')).toBeInTheDocument();
    });

    it('renders a link to the full details page', () => {
        mockUseQuery.mockReturnValue({
            data: makeLog(),
            isLoading: false,
            isError: false,
            refetch: vi.fn(),
        });

        render(
            <QuickView
                logId={LOG_ID}
                onClose={mockOnClose}
                onReviewUpdate={mockOnReviewUpdate}
            />,
        );

        const link = screen.getByText('View full details').closest('a');
        expect(link).toHaveAttribute('href', `/admin/audit/${LOG_ID}`);
    });

    it('renders field changes table when log has changes', () => {
        mockUseQuery.mockReturnValue({
            data: makeLog({
                changes: [
                    {
                        field: 'email',
                        old_value: 'a@b.com',
                        new_value: 'c@d.com',
                    },
                ],
            }),
            isLoading: false,
            isError: false,
            refetch: vi.fn(),
        });

        render(
            <QuickView
                logId={LOG_ID}
                onClose={mockOnClose}
                onReviewUpdate={mockOnReviewUpdate}
            />,
        );

        expect(screen.getByText('email')).toBeInTheDocument();
        expect(screen.getByText('a@b.com')).toBeInTheDocument();
        expect(screen.getByText('c@d.com')).toBeInTheDocument();
    });

    it('renders tags section when log has tags', () => {
        mockUseQuery.mockReturnValue({
            data: makeLog({
                tags: [{ key: 'tenant', value: 'acme' }],
            }),
            isLoading: false,
            isError: false,
            refetch: vi.fn(),
        });

        render(
            <QuickView
                logId={LOG_ID}
                onClose={mockOnClose}
                onReviewUpdate={mockOnReviewUpdate}
            />,
        );

        expect(screen.getByText('tenant=')).toBeInTheDocument();
        expect(screen.getByText('acme')).toBeInTheDocument();
    });

    it('renders notes in the history section', () => {
        mockUseQuery.mockReturnValue({
            data: makeLog({
                notes: [
                    {
                        id: 'n-1',
                        type: 'note',
                        body: 'Looks suspicious',
                        admin_name: 'Bob',
                        created_at: '2025-01-02T09:00:00Z',
                    },
                ],
            }),
            isLoading: false,
            isError: false,
            refetch: vi.fn(),
        });

        render(
            <QuickView
                logId={LOG_ID}
                onClose={mockOnClose}
                onReviewUpdate={mockOnReviewUpdate}
            />,
        );

        expect(screen.getByText('Looks suspicious')).toBeInTheDocument();
        expect(screen.getByText('Bob')).toBeInTheDocument();
    });

    it('renders the NoteForm (compact) when data is loaded', () => {
        mockUseQuery.mockReturnValue({
            data: makeLog(),
            isLoading: false,
            isError: false,
            refetch: vi.fn(),
        });

        render(
            <QuickView
                logId={LOG_ID}
                onClose={mockOnClose}
                onReviewUpdate={mockOnReviewUpdate}
            />,
        );

        // NoteForm renders these type buttons (Add Note appears in both selector and submit)
        expect(screen.getAllByText('Add Note').length).toBeGreaterThan(0);
        expect(screen.getByText('Escalate')).toBeInTheDocument();
    });
});
