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

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

const mockRouterVisit = vi.fn();
const mockFormPost = vi.fn();
const mockFormPut = vi.fn();
const mockSetData = vi.fn();

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: (...args: any[]) => mockRouterVisit(...args),
    },
    usePage: vi.fn(() => ({
        props: {
            auth: { adminRole: 'super_admin', adminPermissions: [] },
            flash: {},
            errors: {},
        },
    })),
    useForm: vi.fn((defaults: any) => ({
        data: defaults ?? {},
        setData: mockSetData,
        post: mockFormPost,
        put: mockFormPut,
        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(() => ({
        data: undefined,
        isLoading: false,
        isError: false,
        refetch: vi.fn(),
    })),
    useQueryClient: vi.fn(() => ({
        invalidateQueries: vi.fn(),
        setQueryData: vi.fn(),
    })),
    keepPreviousData: undefined,
}));

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

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

// Mock complex UI sub-components that are hard to render in jsdom
vi.mock('@/components/ui/phone-input', () => ({
    PhoneInput: ({ value, onChange }: any) => (
        <input
            data-testid="phone-input"
            value={value ?? ''}
            onChange={(e) => onChange(e.target.value)}
        />
    ),
}));

vi.mock('@/components/ui/searchable-select', () => ({
    SearchableSelect: ({ value, onChange, placeholder }: any) => (
        <select
            data-testid="searchable-select"
            value={value}
            onChange={(e) => onChange(e.target.value)}
        >
            <option value="">{placeholder}</option>
            <option value="UTC">UTC</option>
            <option value="Africa/Nairobi">Africa/Nairobi</option>
        </select>
    ),
}));

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

const sampleRoles = [
    { id: 1, name: 'super_admin' },
    { id: 2, name: 'admin' },
];

const sampleTimezones = [
    {
        group: 'Africa',
        options: [{ value: 'Africa/Nairobi', label: 'Africa/Nairobi' }],
    },
    {
        group: 'UTC',
        options: [{ value: 'UTC', label: 'UTC' }],
    },
];

const existingUser = {
    id: '019efe4a-9d05-7265-8fa2-21b7c3d107dd',
    name: 'Alice Kamau',
    email: 'alice@example.com',
    phone: '+254700000001',
    status: 'active' as const,
    job_title: 'Senior Engineer',
    department: 'Engineering',
    timezone: 'Africa/Nairobi',
    force_password_reset: false,
    avatar_url: null,
    role: 'super_admin',
};

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

describe('UsersForm — create mode', () => {
    it('renders inside AdminLayout without crashing', () => {
        render(<UsersForm roles={sampleRoles} timezones={sampleTimezones} />);
        expect(screen.getByTestId('admin-layout')).toBeInTheDocument();
    });

    it('sets the page <title> to "New Admin"', () => {
        render(<UsersForm roles={sampleRoles} timezones={sampleTimezones} />);
        expect(document.querySelector('title')).toHaveTextContent('New Admin');
    });

    it('renders "New Admin" heading', () => {
        render(<UsersForm roles={sampleRoles} timezones={sampleTimezones} />);
        expect(
            screen.getByRole('heading', { name: /new admin/i }),
        ).toBeInTheDocument();
    });

    it('renders Identity section with Full name and Email labels', () => {
        render(<UsersForm roles={sampleRoles} timezones={sampleTimezones} />);
        expect(screen.getByText(/full name/i)).toBeInTheDocument();
        expect(screen.getByText(/email/i)).toBeInTheDocument();
    });

    it('renders Password field (required) in create mode', () => {
        render(<UsersForm roles={sampleRoles} timezones={sampleTimezones} />);
        // Label text is "Password" (not "New password") in create mode
        expect(
            screen.getByText(/^password/i, { selector: 'label' }),
        ).toBeInTheDocument();
    });

    it('renders Organisation section with Job title and Department labels', () => {
        render(<UsersForm roles={sampleRoles} timezones={sampleTimezones} />);
        expect(screen.getByText(/job title/i)).toBeInTheDocument();
        expect(screen.getByText(/department/i)).toBeInTheDocument();
    });

    it('renders Timezone label in Organisation section', () => {
        render(<UsersForm roles={sampleRoles} timezones={sampleTimezones} />);
        expect(
            screen.getByText(/^timezone/i, { selector: 'label' }),
        ).toBeInTheDocument();
    });

    it('renders Access section with Role and Status labels', () => {
        render(<UsersForm roles={sampleRoles} timezones={sampleTimezones} />);
        expect(
            screen.getByText(/^role/i, { selector: 'label' }),
        ).toBeInTheDocument();
        expect(
            screen.getByText(/^status/i, { selector: 'label' }),
        ).toBeInTheDocument();
    });

    it('renders "Force password reset" checkbox label', () => {
        render(<UsersForm roles={sampleRoles} timezones={sampleTimezones} />);
        expect(screen.getByText('Force password reset')).toBeInTheDocument();
    });

    it('renders "Create admin" submit button', () => {
        render(<UsersForm roles={sampleRoles} timezones={sampleTimezones} />);
        expect(
            screen.getByRole('button', { name: 'Create admin' }),
        ).toBeInTheDocument();
    });

    it('renders Cancel button that navigates back to /admin/users', async () => {
        const user = userEvent.setup();
        render(<UsersForm roles={sampleRoles} timezones={sampleTimezones} />);
        await user.click(screen.getByRole('button', { name: /cancel/i }));
        expect(mockRouterVisit).toHaveBeenCalledWith('/admin/users');
    });

    it('does not show the Avatar uploader in create mode', () => {
        render(<UsersForm roles={sampleRoles} timezones={sampleTimezones} />);
        expect(screen.queryByText(/avatar/i)).not.toBeInTheDocument();
    });
});

describe('UsersForm — edit mode', () => {
    it('renders "Edit Admin" heading in edit mode', () => {
        render(
            <UsersForm
                user={existingUser}
                roles={sampleRoles}
                timezones={sampleTimezones}
            />,
        );
        expect(
            screen.getByRole('heading', { name: /edit admin/i }),
        ).toBeInTheDocument();
    });

    it('sets the page <title> to "Edit: Alice Kamau" in edit mode', () => {
        render(
            <UsersForm
                user={existingUser}
                roles={sampleRoles}
                timezones={sampleTimezones}
            />,
        );
        expect(document.querySelector('title')).toHaveTextContent(
            'Edit: Alice Kamau',
        );
    });

    it('renders "New password" label (not "Password") in edit mode', () => {
        render(
            <UsersForm
                user={existingUser}
                roles={sampleRoles}
                timezones={sampleTimezones}
            />,
        );
        expect(
            screen.getByText(/new password/i, { selector: 'label' }),
        ).toBeInTheDocument();
    });

    it('shows the Avatar fieldset in edit mode', () => {
        render(
            <UsersForm
                user={existingUser}
                roles={sampleRoles}
                timezones={sampleTimezones}
            />,
        );
        // The legend "Avatar" is present in edit mode
        expect(screen.getByText(/^avatar$/i)).toBeInTheDocument();
    });

    it('renders "Save changes" submit button in edit mode', () => {
        render(
            <UsersForm
                user={existingUser}
                roles={sampleRoles}
                timezones={sampleTimezones}
            />,
        );
        expect(
            screen.getByRole('button', { name: 'Save changes' }),
        ).toBeInTheDocument();
    });
});
