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

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

vi.mock('@/components/ui/tooltip', () => ({
    Tooltip: ({ children }: any) => <>{children}</>,
    TooltipTrigger: ({ children, asChild }: any) =>
        asChild ? children : <span>{children}</span>,
    TooltipContent: ({ children }: any) => <span>{children}</span>,
    TooltipProvider: ({ children }: any) => <>{children}</>,
}));

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('@/Layouts/AdminLayout', () => ({
    default: ({ children, title }: any) => (
        <div data-testid="admin-layout" data-title={title}>
            {children}
        </div>
    ),
}));

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() } }));

vi.mock('../components/QuickView', () => ({
    default: ({ logId, onClose }: any) =>
        logId ? (
            <div data-testid="quick-view" data-log-id={logId}>
                <button onClick={onClose}>Close</button>
            </div>
        ) : null,
}));

vi.mock('@/components/admin/DataTable', () => ({
    DataTable: ({
        columns,
        data,
        isLoading,
        quickFilters,
        searchPlaceholder,
        noun,
    }: any) => (
        <div data-testid="data-table">
            {quickFilters && (
                <div data-testid="quick-filters">
                    {quickFilters.map((f: any) => (
                        <button key={f.value} data-value={f.value}>
                            {f.label}
                            {f.count !== undefined && <span>{f.count}</span>}
                        </button>
                    ))}
                </div>
            )}
            {searchPlaceholder && <input placeholder={searchPlaceholder} />}
            {isLoading && <div data-testid="loading-skeleton" />}
            {data?.length === 0 && noun && <div>No {noun} found</div>}
            <table>
                <thead>
                    <tr>
                        {columns.map((col: any, i: number) => (
                            <th key={i}>{col.header ?? col.id}</th>
                        ))}
                    </tr>
                </thead>
                <tbody>
                    {(data ?? []).map((row: any, i: number) => (
                        <tr key={i} data-testid="audit-row">
                            {columns.map((col: any, j: number) => (
                                <td key={j}>
                                    {col.cell
                                        ? col.cell({
                                              row: {
                                                  original: row,
                                                  getValue: () =>
                                                      row[col.accessorKey],
                                              },
                                          })
                                        : String(row[col.accessorKey] ?? '')}
                                </td>
                            ))}
                        </tr>
                    ))}
                </tbody>
            </table>
        </div>
    ),
}));

vi.mock('@/hooks/useDataTable', () => ({
    useDataTable: () => ({
        params: {
            page: 1,
            sort: 'created_at',
            dir: 'desc',
            search: '',
            filter: 'all',
        },
        setParams: vi.fn(),
    }),
}));

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

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

import AuditLogsIndex from '../Index';

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

function makeRow(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',
        ip_address: '192.168.1.1',
        review_status: null,
        reviewed_at: null,
        reviewed_by_name: null,
        created_at: '2025-01-01T10:00:00Z',
        ...overrides,
    };
}

const FILTER_COUNTS = {
    all: 120,
    unreviewed: 45,
    critical: 8,
    warning: 22,
    failed: 12,
};

const EMPTY_META = {
    current_page: 1,
    last_page: 1,
    total: 0,
    per_page: 50,
    from: 0,
    to: 0,
};

describe('AuditLogsIndex', () => {
    beforeEach(() => {
        vi.clearAllMocks();
        mockUseQueryClient.mockReturnValue({
            invalidateQueries: vi.fn(),
            setQueryData: vi.fn(),
        });
        mockUseQuery.mockReturnValue({
            data: undefined,
            isLoading: false,
            isFetching: false,
        });
    });

    it('renders inside the AdminLayout with title "Audit Logs"', () => {
        render(<AuditLogsIndex filterCounts={FILTER_COUNTS} />);
        const layout = screen.getByTestId('admin-layout');
        expect(layout).toHaveAttribute('data-title', 'Audit Logs');
    });

    it('renders the page heading "Audit Logs"', () => {
        render(<AuditLogsIndex filterCounts={FILTER_COUNTS} />);
        // PageHeader renders an h2
        expect(
            screen.getByRole('heading', { name: /audit logs/i }),
        ).toBeInTheDocument();
    });

    it('renders all five quick filter tabs with their counts', () => {
        render(<AuditLogsIndex filterCounts={FILTER_COUNTS} />);
        expect(screen.getByText('All')).toBeInTheDocument();
        expect(screen.getByText('Unreviewed')).toBeInTheDocument();
        expect(screen.getByText('Critical')).toBeInTheDocument();
        expect(screen.getByText('Warning')).toBeInTheDocument();
        expect(screen.getByText('Failed')).toBeInTheDocument();
        // Filter counts
        expect(screen.getByText('120')).toBeInTheDocument();
        expect(screen.getByText('45')).toBeInTheDocument();
        expect(screen.getByText('8')).toBeInTheDocument();
    });

    it('renders the search input with correct placeholder', () => {
        render(<AuditLogsIndex filterCounts={FILTER_COUNTS} />);
        expect(
            screen.getByPlaceholderText('Search events, actors, IPs…'),
        ).toBeInTheDocument();
    });

    it('renders the Export CSV link', () => {
        render(<AuditLogsIndex filterCounts={FILTER_COUNTS} />);
        expect(screen.getByText('Export CSV')).toBeInTheDocument();
    });

    it('renders the Filters button', () => {
        render(<AuditLogsIndex filterCounts={FILTER_COUNTS} />);
        expect(
            screen.getByRole('button', { name: /filters/i }),
        ).toBeInTheDocument();
    });

    it('shows the filters panel when the Filters button is clicked', async () => {
        render(<AuditLogsIndex filterCounts={FILTER_COUNTS} />);
        await userEvent.click(screen.getByRole('button', { name: /filters/i }));
        // FiltersPanel renders Severity and Status filter buttons
        expect(
            screen.getByRole('button', { name: /severity/i }),
        ).toBeInTheDocument();
        expect(
            screen.getByRole('button', { name: /status/i }),
        ).toBeInTheDocument();
    });

    it('renders table rows for data returned by useQuery', () => {
        mockUseQuery.mockReturnValue({
            data: {
                data: [makeRow()],
                meta: { ...EMPTY_META, total: 1, from: 1, to: 1 },
            },
            isLoading: false,
            isFetching: false,
        });

        render(<AuditLogsIndex filterCounts={FILTER_COUNTS} />);
        expect(screen.getByText('user.login')).toBeInTheDocument();
        expect(screen.getByText('Alice Admin')).toBeInTheDocument();
    });

    it('renders the severity badge for each row', () => {
        mockUseQuery.mockReturnValue({
            data: {
                data: [makeRow({ severity: 'critical' })],
                meta: EMPTY_META,
            },
            isLoading: false,
            isFetching: false,
        });

        render(<AuditLogsIndex filterCounts={FILTER_COUNTS} />);
        expect(screen.getAllByText('Critical').length).toBeGreaterThan(0);
    });

    it('renders the status badge for each row', () => {
        mockUseQuery.mockReturnValue({
            data: { data: [makeRow({ status: 'failed' })], meta: EMPTY_META },
            isLoading: false,
            isFetching: false,
        });

        render(<AuditLogsIndex filterCounts={FILTER_COUNTS} />);
        expect(screen.getAllByText('Failed').length).toBeGreaterThan(0);
    });

    it('shows "No events found" when the data array is empty', () => {
        mockUseQuery.mockReturnValue({
            data: { data: [], meta: EMPTY_META },
            isLoading: false,
            isFetching: false,
        });

        render(<AuditLogsIndex filterCounts={FILTER_COUNTS} />);
        expect(screen.getByText('No events found')).toBeInTheDocument();
    });

    it('shows skeleton rows while data is loading', () => {
        mockUseQuery.mockReturnValue({
            data: undefined,
            isLoading: true,
            isFetching: false,
        });

        render(<AuditLogsIndex filterCounts={FILTER_COUNTS} />);
        // DataTable mock renders a loading-skeleton element when isLoading=true
        expect(screen.getByTestId('loading-skeleton')).toBeInTheDocument();
    });
});
