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

// ── 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: {},
        },
    })),
    useForm: vi.fn((defaults: any) => ({
        data: defaults ?? {},
        setData: vi.fn(),
        post: vi.fn(),
        put: vi.fn(),
        patch: vi.fn(),
        delete: vi.fn(),
        processing: false,
        errors: {},
        reset: vi.fn(),
        transform: vi.fn().mockReturnThis(),
    })),
}));

vi.mock('@/Layouts/AdminLayout', () => ({
    default: ({ children, title }: any) => (
        <div data-testid="admin-layout" data-title={title}>
            {children}
        </div>
    ),
}));

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

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

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

vi.mock('@/components/admin/DataTable', () => ({
    DataTable: ({ columns, data }: any) => (
        <table data-testid="trash-table">
            <tbody>
                {(data ?? []).map((row: any, i: number) => (
                    <tr key={i} data-testid="trash-row">
                        {columns.map((col: any, j: number) => (
                            <td key={j}>
                                {col.accessorKey
                                    ? String(row[col.accessorKey] ?? '')
                                    : ''}
                            </td>
                        ))}
                    </tr>
                ))}
            </tbody>
        </table>
    ),
}));

vi.mock('@/components/admin/PageHeader', () => ({
    default: ({ title, description, action }: any) => (
        <div data-testid="page-header">
            <h1>{title}</h1>
            <p>{description}</p>
            <div>{action}</div>
        </div>
    ),
}));

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

// ConfirmDialog is rendered inline — mock it so we can control it
vi.mock('@/components/ui/confirm-dialog', () => ({
    ConfirmDialog: ({
        open,
        title,
        onConfirm,
        onOpenChange,
        confirmLabel,
    }: any) =>
        open ? (
            <div data-testid="confirm-dialog">
                <p data-testid="confirm-title">{title}</p>
                <button data-testid="confirm-btn" onClick={onConfirm}>
                    {confirmLabel}
                </button>
                <button
                    data-testid="cancel-btn"
                    onClick={() => onOpenChange(false)}
                >
                    Cancel
                </button>
            </div>
        ) : null,
}));

// ── Fixtures ──────────────────────────────────────────────────────────────────

const trashedRoles = [
    {
        id: 10,
        name: 'old_manager',
        description: 'Former manager role',
        permissions_count: 6,
        users_count: 1,
        deleted_at: '2024-05-01T09:00:00Z',
    },
    {
        id: 11,
        name: 'legacy_reporter',
        description: null,
        permissions_count: 2,
        users_count: 0,
        deleted_at: '2024-04-15T12:00:00Z',
    },
];

const emptyResult = {
    data: {
        data: [],
        meta: {
            current_page: 1,
            last_page: 1,
            total: 0,
            per_page: 25,
            from: 0,
            to: 0,
        },
        filter_counts: { all: 0 },
    },
    isLoading: false,
    isFetching: false,
};

const populatedResult = {
    data: {
        data: trashedRoles,
        meta: {
            current_page: 1,
            last_page: 1,
            total: 2,
            per_page: 25,
            from: 1,
            to: 2,
        },
        filter_counts: { all: 2 },
    },
    isLoading: false,
    isFetching: false,
};

// ── Tests ─────────────────────────────────────────────────────────────────────

describe('Roles/Trash', () => {
    beforeEach(() => {
        vi.mocked(useQuery).mockReturnValue(emptyResult as any);
    });

    it('renders inside AdminLayout with trash title', () => {
        render(<RolesTrash />);
        expect(screen.getByTestId('admin-layout')).toBeInTheDocument();
        expect(screen.getByTestId('admin-layout')).toHaveAttribute(
            'data-title',
            'Roles — Trash',
        );
    });

    it('renders page header with "Roles Trash" title', () => {
        render(<RolesTrash />);
        expect(
            screen.getByRole('heading', { name: /Roles Trash/i }),
        ).toBeInTheDocument();
    });

    it('renders description about restoring or permanently deleting', () => {
        render(<RolesTrash />);
        expect(
            screen.getByText(/Restore or permanently delete/i),
        ).toBeInTheDocument();
    });

    it('renders a Back to Roles link pointing to /admin/roles', () => {
        render(<RolesTrash />);
        const backLink = screen.getByRole('link', { name: /Back to Roles/i });
        expect(backLink).toHaveAttribute('href', '/admin/roles');
    });

    it('renders the trash table', () => {
        render(<RolesTrash />);
        expect(screen.getByTestId('trash-table')).toBeInTheDocument();
    });

    it('renders a row for each trashed role', () => {
        vi.mocked(useQuery).mockReturnValue(populatedResult as any);
        render(<RolesTrash />);
        expect(screen.getAllByTestId('trash-row')).toHaveLength(2);
    });

    it('displays trashed role names', () => {
        vi.mocked(useQuery).mockReturnValue(populatedResult as any);
        render(<RolesTrash />);
        expect(screen.getByText('old_manager')).toBeInTheDocument();
        expect(screen.getByText('legacy_reporter')).toBeInTheDocument();
    });

    it('displays permissions_count for trashed roles', () => {
        vi.mocked(useQuery).mockReturnValue(populatedResult as any);
        render(<RolesTrash />);
        expect(screen.getByText('6')).toBeInTheDocument();
        expect(screen.getByText('2')).toBeInTheDocument();
    });

    it('does not show confirm dialog initially', () => {
        render(<RolesTrash />);
        expect(screen.queryByTestId('confirm-dialog')).not.toBeInTheDocument();
    });

    it('renders without crashing when query returns undefined data', () => {
        vi.mocked(useQuery).mockReturnValue({
            data: undefined,
            isLoading: true,
            isFetching: true,
        } as any);
        render(<RolesTrash />);
        expect(screen.getByTestId('admin-layout')).toBeInTheDocument();
        expect(screen.queryAllByTestId('trash-row')).toHaveLength(0);
    });
});
