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

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

const mockPost = vi.fn();
const mockSetData = vi.fn();
const mockReset = vi.fn();

// useForm state is module-level so tests can override it per-test
let formData = { email: '', password: '', remember: false };
let formErrors: Record<string, string> = {};
let formProcessing = false;

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: {},
            flash: {},
            errors: {},
        },
    })),
    useForm: vi.fn(() => ({
        data: formData,
        setData: mockSetData,
        post: mockPost,
        put: vi.fn(),
        patch: vi.fn(),
        delete: vi.fn(),
        processing: formProcessing,
        errors: formErrors,
        reset: mockReset,
        transform: vi.fn().mockReturnThis(),
    })),
}));

// The login page uses @/components/Field (capital C, as it lives in resources/js/Components/)
vi.mock('@/components/Field', () => ({
    default: ({
        label,
        id,
        name,
        type,
        value,
        onChange,
        error,
        placeholder,
        autoComplete,
        autoFocus,
    }: any) => (
        <div>
            <label htmlFor={id}>{label}</label>
            <input
                id={id}
                name={name}
                type={type ?? 'text'}
                value={value ?? ''}
                onChange={onChange}
                placeholder={placeholder}
                autoComplete={autoComplete}
                autoFocus={autoFocus}
                aria-invalid={!!error}
            />
            {error && (
                <p role="alert" id={`${id}-error`}>
                    {error}
                </p>
            )}
        </div>
    ),
}));

// Ziggy route helper — Login calls route('admin.login')
vi.stubGlobal('route', () => `/admin/login`);

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

describe('Admin Auth/Login', () => {
    beforeEach(() => {
        formData = { email: '', password: '', remember: false };
        formErrors = {};
        formProcessing = false;
        mockPost.mockReset();
        mockSetData.mockReset();
        mockReset.mockReset();
        vi.stubGlobal('route', () => '/admin/login');
    });

    it('renders the page title "Admin — Sign In" via Head', () => {
        render(<AdminLogin />);
        expect(document.title).toBe('Admin — Sign In');
    });

    it('renders the email input', () => {
        render(<AdminLogin />);
        expect(screen.getByLabelText(/admin email/i)).toBeInTheDocument();
    });

    it('renders the password input with type="password"', () => {
        render(<AdminLogin />);
        const passwordInput = screen.getByLabelText(/^password$/i);
        expect(passwordInput).toBeInTheDocument();
        expect(passwordInput).toHaveAttribute('type', 'password');
    });

    it('renders the "Keep me signed in" remember checkbox', () => {
        render(<AdminLogin />);
        expect(
            screen.getByRole('checkbox', { name: /keep me signed in/i }),
        ).toBeInTheDocument();
    });

    it('renders the "Sign In to Admin" submit button', () => {
        render(<AdminLogin />);
        expect(
            screen.getByRole('button', { name: /sign in to admin/i }),
        ).toBeInTheDocument();
    });

    it('renders the "← Back to upepofinance.com" link', () => {
        render(<AdminLogin />);
        expect(
            screen.getByRole('link', { name: /back to upepofinance\.com/i }),
        ).toBeInTheDocument();
    });

    it('renders the "Platform Administration" security badge', () => {
        render(<AdminLogin />);
        expect(
            screen.getByText(/platform administration/i),
        ).toBeInTheDocument();
    });

    it('renders the "Admin sign in" heading', () => {
        render(<AdminLogin />);
        expect(
            screen.getByRole('heading', { name: /admin sign in/i }),
        ).toBeInTheDocument();
    });

    it('renders the "Authorized personnel only" sub-heading', () => {
        render(<AdminLogin />);
        expect(
            screen.getByText(/authorized personnel only/i),
        ).toBeInTheDocument();
    });

    it('submits the form by calling router.post when the form is submitted', () => {
        render(<AdminLogin />);
        const form = screen
            .getByRole('button', { name: /sign in to admin/i })
            .closest('form')!;
        fireEvent.submit(form);
        expect(mockPost).toHaveBeenCalledWith(
            '/admin/login',
            expect.objectContaining({ onFinish: expect.any(Function) }),
        );
    });

    it('displays an email validation error when errors.email is set', () => {
        formErrors = { email: 'The email field is required.' };
        render(<AdminLogin />);
        expect(
            screen.getByText('The email field is required.'),
        ).toBeInTheDocument();
    });

    it('displays a password validation error when errors.password is set', () => {
        formErrors = {
            password: 'These credentials do not match our records.',
        };
        render(<AdminLogin />);
        expect(
            screen.getByText('These credentials do not match our records.'),
        ).toBeInTheDocument();
    });

    it('marks the email input as aria-invalid when there is an email error', () => {
        formErrors = { email: 'Invalid email.' };
        render(<AdminLogin />);
        const emailInput = screen.getByLabelText(/admin email/i);
        expect(emailInput).toHaveAttribute('aria-invalid', 'true');
    });

    it('disables the submit button while processing', () => {
        formProcessing = true;
        render(<AdminLogin />);
        const button = screen.getByRole('button', { name: /signing in/i });
        expect(button).toBeDisabled();
    });

    it('shows "Signing in…" text on the button while processing', () => {
        formProcessing = true;
        render(<AdminLogin />);
        expect(screen.getByText(/signing in…/i)).toBeInTheDocument();
    });

    it('adds the dark class to documentElement on mount', () => {
        render(<AdminLogin />);
        expect(document.documentElement.classList.contains('dark')).toBe(true);
    });

    it('removes the dark class from documentElement on unmount', () => {
        const { unmount } = render(<AdminLogin />);
        unmount();
        expect(document.documentElement.classList.contains('dark')).toBe(false);
    });

    it('renders the Upepo Finance brand link pointing to "/"', () => {
        render(<AdminLogin />);
        const brandLink = screen.getByRole('link', { name: /upepo finance/i });
        expect(brandLink).toHaveAttribute('href', '/');
    });

    it('renders the back-to-site link pointing to "/"', () => {
        render(<AdminLogin />);
        const backLink = screen.getByRole('link', {
            name: /back to upepofinance\.com/i,
        });
        expect(backLink).toHaveAttribute('href', '/');
    });
});
