/* 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 ModulesIndex from '../Index';

// ── 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('@/components/admin/PageHeader', () => ({
    default: ({ title, description }: any) => (
        <div data-testid="page-header">
            <h1>{title}</h1>
            <p>{description}</p>
        </div>
    ),
}));

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

const starterPlanRef = { id: 'plan-1', name: 'Starter', slug: 'starter' };
const proPlanRef = { id: 'plan-2', name: 'Professional', slug: 'professional' };

const lendingModule = {
    id: '019efe5c-2f8e-7038-9c63-25c49a749457',
    slug: 'lending',
    name: 'Lending',
    icon: 'CreditCard',
    sort_order: 1,
    sub_modules: [
        {
            id: 'sm-1',
            slug: 'lending.core',
            name: 'Lending Core',
            description: 'Core lending functionality',
            is_core: true,
            plans: [starterPlanRef, proPlanRef],
            tenant_overrides: 0,
            tenant_enabled: 12,
        },
        {
            id: 'sm-2',
            slug: 'lending.products',
            name: 'Loan Products',
            description: 'Manage loan product catalogue',
            is_core: false,
            plans: [proPlanRef],
            tenant_overrides: 2,
            tenant_enabled: 7,
        },
        {
            id: 'sm-3',
            slug: 'lending.reports',
            name: 'Loan Reports',
            description: null,
            is_core: false,
            plans: [],
            tenant_overrides: 0,
            tenant_enabled: 0,
        },
    ],
};

const savingsModule = {
    id: '019efe5c-2f8e-7038-9c63-25c49a749458',
    slug: 'savings',
    name: 'Savings',
    icon: null,
    sort_order: 2,
    sub_modules: [
        {
            id: 'sm-4',
            slug: 'savings.core',
            name: 'Savings Core',
            description: null,
            is_core: true,
            plans: [starterPlanRef],
            tenant_overrides: 0,
            tenant_enabled: 5,
        },
    ],
};

const emptyModule = {
    id: '019efe5c-2f8e-7038-9c63-25c49a749459',
    slug: 'reporting',
    name: 'Reporting',
    icon: 'BarChart2',
    sort_order: 3,
    sub_modules: [],
};

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

describe('Modules/Index', () => {
    it('renders inside AdminLayout with Modules title', () => {
        render(<ModulesIndex modules={[]} />);
        expect(screen.getByTestId('admin-layout')).toBeInTheDocument();
        expect(screen.getByTestId('admin-layout')).toHaveAttribute(
            'data-title',
            'Modules',
        );
    });

    it('renders page header with Modules title', () => {
        render(<ModulesIndex modules={[lendingModule]} />);
        expect(
            screen.getByRole('heading', { name: /Modules/i }),
        ).toBeInTheDocument();
    });

    it('shows module count and sub-module count in header description', () => {
        render(<ModulesIndex modules={[lendingModule, savingsModule]} />);
        // 2 modules, 4 sub-modules total
        expect(screen.getByText(/2 modules/i)).toBeInTheDocument();
        expect(screen.getByText(/4 sub-modules/i)).toBeInTheDocument();
    });

    it('renders empty state when no modules', () => {
        render(<ModulesIndex modules={[]} />);
        expect(screen.getByText(/No modules configured/i)).toBeInTheDocument();
    });

    it('renders a module card for each module', () => {
        render(<ModulesIndex modules={[lendingModule, savingsModule]} />);
        expect(screen.getByText('Lending')).toBeInTheDocument();
        expect(screen.getByText('Savings')).toBeInTheDocument();
    });

    it('displays module slug in the accordion header', () => {
        render(<ModulesIndex modules={[lendingModule]} />);
        expect(screen.getByText('lending')).toBeInTheDocument();
    });

    it('shows sub-module count in module card header', () => {
        render(<ModulesIndex modules={[lendingModule]} />);
        expect(screen.getByText('3 sub-modules')).toBeInTheDocument();
    });

    it('shows core count in module card header', () => {
        render(<ModulesIndex modules={[lendingModule]} />);
        expect(screen.getByText('1 core')).toBeInTheDocument();
    });

    it('renders sub-module rows when module is open (default)', () => {
        render(<ModulesIndex modules={[lendingModule]} />);
        expect(screen.getByText('Lending Core')).toBeInTheDocument();
        expect(screen.getByText('Loan Products')).toBeInTheDocument();
        expect(screen.getByText('Loan Reports')).toBeInTheDocument();
    });

    it('renders Core badge for is_core sub-modules', () => {
        render(<ModulesIndex modules={[lendingModule]} />);
        // Both lending.core and savings.core — only lending is shown
        expect(screen.getByText('Core')).toBeInTheDocument();
    });

    it('renders sub-module slug in monospace', () => {
        render(<ModulesIndex modules={[lendingModule]} />);
        expect(screen.getByText('lending.core')).toBeInTheDocument();
        expect(screen.getByText('lending.products')).toBeInTheDocument();
    });

    it('renders plan badges on sub-modules', () => {
        render(<ModulesIndex modules={[lendingModule]} />);
        // "Professional" appears for lending.products, "Starter" appears for lending.core
        expect(screen.getAllByText('Starter').length).toBeGreaterThan(0);
        expect(screen.getAllByText('Professional').length).toBeGreaterThan(0);
    });

    it('shows "No plans" label for sub-modules with empty plans array', () => {
        render(<ModulesIndex modules={[lendingModule]} />);
        expect(screen.getByText('No plans')).toBeInTheDocument();
    });

    it('collapses sub-modules when module header button is clicked', async () => {
        render(<ModulesIndex modules={[lendingModule]} />);

        // Initially expanded — sub-modules are visible
        expect(screen.getByText('Lending Core')).toBeInTheDocument();

        // Click the toggle button (the module card header button)
        const toggleBtn = screen.getByRole('button', {
            name: (name) =>
                name.includes('Lending') || name.includes('sub-module'),
        });
        await userEvent.click(toggleBtn);

        // Sub-modules should now be hidden
        expect(screen.queryByText('Lending Core')).not.toBeInTheDocument();
    });

    it('shows "No sub-modules defined" for an empty module when open', () => {
        render(<ModulesIndex modules={[emptyModule]} />);
        expect(screen.getByText(/No sub-modules defined/i)).toBeInTheDocument();
    });

    it('renders tenant_enabled count when greater than zero', () => {
        render(<ModulesIndex modules={[lendingModule]} />);
        // lending.core has tenant_enabled: 12, lending.products has 7
        expect(screen.getByText('12')).toBeInTheDocument();
        expect(screen.getByText('7')).toBeInTheDocument();
    });

    it('renders module without an icon using fallback Layers icon gracefully', () => {
        render(<ModulesIndex modules={[savingsModule]} />);
        // icon is null — should still render without crashing
        expect(screen.getByText('Savings')).toBeInTheDocument();
    });

    it('uses singular "sub-module" for a module with 1 sub-module', () => {
        render(<ModulesIndex modules={[savingsModule]} />);
        expect(screen.getByText('1 sub-module')).toBeInTheDocument();
    });
});
