/* eslint-disable @typescript-eslint/no-explicit-any */
import { render, screen } from '@testing-library/react';
import { describe, expect, it, vi } from 'vitest';
import AnalyticsIndex 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('@/hooks/useIsDark', () => ({
    useIsDark: vi.fn(() => false),
}));

vi.mock('@/components/admin/chart-theme', () => ({
    getChartTheme: vi.fn(() => ({
        grid: '#e5e7eb',
        tick: { fill: '#6b7280', fontSize: 11 },
        tooltip: {
            contentStyle: { background: '#fff', border: '1px solid #e5e7eb' },
            cursor: { fill: 'rgba(0,0,0,0.04)' },
        },
    })),
}));

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

vi.mock('@/components/admin/StatCard', () => ({
    default: ({ label, value, sub }: any) => (
        <div data-testid="stat-card">
            <span data-testid="stat-label">{label}</span>
            <span data-testid="stat-value">{value}</span>
            {sub && <span data-testid="stat-sub">{sub}</span>}
        </div>
    ),
}));

vi.mock('recharts', () => ({
    ResponsiveContainer: ({ children }: any) => (
        <div data-testid="responsive-container">{children}</div>
    ),
    BarChart: ({ children }: any) => (
        <div data-testid="bar-chart">{children}</div>
    ),
    PieChart: ({ children }: any) => (
        <div data-testid="pie-chart">{children}</div>
    ),
    ComposedChart: ({ children }: any) => (
        <div data-testid="composed-chart">{children}</div>
    ),
    Bar: () => null,
    Pie: () => null,
    Cell: () => null,
    Line: () => null,
    XAxis: () => null,
    YAxis: () => null,
    CartesianGrid: () => null,
    Tooltip: () => null,
    Legend: () => null,
    ReferenceLine: () => null,
}));

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

const revenue = {
    mrr: 'USD 2.4M',
    arr: 'USD 28.8M',
    arpa: 'USD 2,443',
    collection_rate: '94.2%',
    yearly_pct: 38,
    billing_split: [
        { name: 'Monthly', value: 612, color: '#3b82f6' },
        { name: 'Yearly', value: 371, color: '#f97316' },
    ],
    by_plan: [
        { plan: 'Enterprise', mrr: 980000 },
        { plan: 'Professional', mrr: 1200000 },
        { plan: 'Starter', mrr: 220000 },
    ],
    mrr_trend: Array.from({ length: 12 }, (_, i) => ({
        month: `M${i + 1}`,
        mrr: 150 + i * 15,
    })),
    mrr_movement: Array.from({ length: 12 }, (_, i) => ({
        month: `M${i + 1}`,
        new: 12000,
        expansion: 3000,
        reactivation: 500,
        contraction: -1500,
        churn: -4000,
        net: 10000,
    })),
};

const cohorts = [
    { month: "Aug '25", size: 40, retention: [100, 92.5, 90, 85] },
    { month: "Sep '25", size: 55, retention: [100, 94.5, 91] },
    { month: "Oct '25", size: 61, retention: [100, 96.7] },
];

const tenants = {
    total: 1247,
    new_in_window: 48,
    growth_pct: 4.0,
    churn_count: 7,
    churn_rate: '0.56%',
    churned_mrr: 'USD 34,500',
    status_breakdown: [
        { name: 'Active', value: 983, color: '#10b981' },
        { name: 'Trial', value: 187, color: '#f59e0b' },
        { name: 'Suspended', value: 44, color: '#ef4444' },
        { name: 'Pending', value: 33, color: '#6b7280' },
    ],
    countries: [
        { country: 'Kenya', count: 820 },
        { country: 'Nigeria', count: 210 },
        { country: 'Ghana', count: 95 },
    ],
    signup_trend: Array.from({ length: 12 }, (_, i) => ({
        month: `M${i + 1}`,
        signups: 30 + i * 2,
    })),
};

const support = {
    open_count: 23,
    total: 412,
    avg_replies: 3.7,
    by_status: [
        { name: 'Open', value: 23 },
        { name: 'Pending', value: 41 },
        { name: 'Resolved', value: 348 },
    ],
    by_category: [
        { name: 'Billing', count: 120 },
        { name: 'Technical', count: 88 },
        { name: 'Account', count: 64 },
    ],
    by_priority: [
        { name: 'Urgent', count: 5 },
        { name: 'High', count: 18 },
        { name: 'Medium', count: 92 },
        { name: 'Low', count: 297 },
    ],
};

const health = {
    summary: {
        at_risk_count: 2,
        mrr_at_risk: 'USD 24,500',
        trials_ending: 2,
        past_due_count: 1,
    },
    at_risk: [
        {
            tenant_id: 'abc-123',
            name: 'Kilima SACCO',
            plan: 'Professional',
            status: 'past_due',
            mrr: 19500,
            mrr_display: 'USD 19,500',
            score: 5,
            signals: ['Payment past due', 'Urgent ticket open'],
        },
        {
            tenant_id: 'def-456',
            name: 'Upendo MFI',
            plan: 'Starter',
            status: 'trialing',
            mrr: 0,
            mrr_display: '—',
            score: 5,
            signals: ['Trial ends in 3d', 'Never engaged'],
        },
    ],
};

const defaultProps = {
    revenue,
    tenants,
    support,
    cohorts,
    health,
    filters: { days: 30 },
};

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

describe('Analytics/Index', () => {
    it('renders inside AdminLayout', () => {
        render(<AnalyticsIndex {...defaultProps} />);
        expect(screen.getByTestId('admin-layout')).toBeInTheDocument();
    });

    it('sets the page title to "Analytics"', () => {
        render(<AnalyticsIndex {...defaultProps} />);
        expect(document.title).toBe('Analytics');
    });

    it('renders the PageHeader with title "Analytics"', () => {
        render(<AnalyticsIndex {...defaultProps} />);
        expect(screen.getByTestId('page-header')).toBeInTheDocument();
        expect(
            screen.getByRole('heading', { name: 'Analytics' }),
        ).toBeInTheDocument();
    });

    it('renders the Revenue section heading', () => {
        render(<AnalyticsIndex {...defaultProps} />);
        expect(
            screen.getByRole('heading', { name: 'Revenue' }),
        ).toBeInTheDocument();
    });

    it('renders the Tenants section heading', () => {
        render(<AnalyticsIndex {...defaultProps} />);
        expect(
            screen.getByRole('heading', { name: 'Tenants' }),
        ).toBeInTheDocument();
    });

    it('renders the Support section heading', () => {
        render(<AnalyticsIndex {...defaultProps} />);
        expect(
            screen.getByRole('heading', { name: 'Support' }),
        ).toBeInTheDocument();
    });

    it('renders 16 stat cards across the four sections', () => {
        render(<AnalyticsIndex {...defaultProps} />);
        // 4 revenue + 4 tenants + 4 health + 4 support = 16
        expect(screen.getAllByTestId('stat-card')).toHaveLength(16);
    });

    it('displays the ARR value from revenue props', () => {
        render(<AnalyticsIndex {...defaultProps} />);
        expect(screen.getByText('USD 28.8M')).toBeInTheDocument();
    });

    it('displays the ARPA value from revenue props', () => {
        render(<AnalyticsIndex {...defaultProps} />);
        expect(screen.getByText('USD 2,443')).toBeInTheDocument();
    });

    it('displays the invoice collection rate from revenue props', () => {
        render(<AnalyticsIndex {...defaultProps} />);
        expect(screen.getByText('94.2%')).toBeInTheDocument();
    });

    it('displays the yearly billing percentage from revenue props', () => {
        render(<AnalyticsIndex {...defaultProps} />);
        expect(screen.getByText('38%')).toBeInTheDocument();
    });

    it('displays total tenants from tenant props', () => {
        render(<AnalyticsIndex {...defaultProps} />);
        expect(screen.getByText('1,247')).toBeInTheDocument();
    });

    it('displays churn rate from tenant props', () => {
        render(<AnalyticsIndex {...defaultProps} />);
        expect(screen.getByText(/0\.56%/)).toBeInTheDocument();
    });

    it('displays open ticket count from support props', () => {
        render(<AnalyticsIndex {...defaultProps} />);
        expect(screen.getByText('23')).toBeInTheDocument();
    });

    it('displays the number of unique countries', () => {
        render(<AnalyticsIndex {...defaultProps} />);
        // tenants.countries.length = 3
        expect(screen.getByText('3')).toBeInTheDocument();
    });

    it('renders "MRR Trend" chart card title', () => {
        render(<AnalyticsIndex {...defaultProps} />);
        expect(screen.getByText('MRR Trend')).toBeInTheDocument();
    });

    it('renders "Billing Cycle Split" chart card title', () => {
        render(<AnalyticsIndex {...defaultProps} />);
        expect(screen.getByText('Billing Cycle Split')).toBeInTheDocument();
    });

    it('renders the MRR Movement chart card', () => {
        render(<AnalyticsIndex {...defaultProps} />);
        expect(screen.getByText('MRR Movement')).toBeInTheDocument();
    });

    it('renders the cohort retention table with cohort rows', () => {
        render(<AnalyticsIndex {...defaultProps} />);
        expect(screen.getByText('Cohort Retention')).toBeInTheDocument();
        expect(screen.getByText("Aug '25")).toBeInTheDocument();
        expect(screen.getByText('92.5%')).toBeInTheDocument();
    });

    it('shows an empty state when there are no cohorts', () => {
        render(<AnalyticsIndex {...defaultProps} cohorts={[]} />);
        expect(screen.getByText('No cohort data yet')).toBeInTheDocument();
    });

    it('renders the Tenant Health section with at-risk tenants', () => {
        render(<AnalyticsIndex {...defaultProps} />);
        expect(
            screen.getByRole('heading', { name: 'Tenant Health' }),
        ).toBeInTheDocument();
        expect(screen.getByText('Kilima SACCO')).toBeInTheDocument();
        expect(screen.getByText('Payment past due')).toBeInTheDocument();
        expect(screen.getByText('Never engaged')).toBeInTheDocument();
    });

    it('links at-risk tenant names to the tenant detail page', () => {
        render(<AnalyticsIndex {...defaultProps} />);
        expect(
            screen.getByRole('link', { name: 'Kilima SACCO' }),
        ).toBeInTheDocument();
    });

    it('shows an empty state when no tenants are at risk', () => {
        render(
            <AnalyticsIndex
                {...defaultProps}
                health={{ ...health, at_risk: [] }}
            />,
        );
        expect(
            screen.getByText('No at-risk tenants — everyone looks healthy'),
        ).toBeInTheDocument();
    });

    it('renders country bars for each country', () => {
        render(<AnalyticsIndex {...defaultProps} />);
        expect(screen.getByText('Kenya')).toBeInTheDocument();
        expect(screen.getByText('Nigeria')).toBeInTheDocument();
        expect(screen.getByText('Ghana')).toBeInTheDocument();
    });

    it('renders support category bars', () => {
        render(<AnalyticsIndex {...defaultProps} />);
        expect(screen.getByText('Billing')).toBeInTheDocument();
        expect(screen.getByText('Technical')).toBeInTheDocument();
    });

    it('renders support priority bars', () => {
        render(<AnalyticsIndex {...defaultProps} />);
        expect(screen.getByText('Urgent')).toBeInTheDocument();
        expect(screen.getByText('High')).toBeInTheDocument();
        expect(screen.getByText('Medium')).toBeInTheDocument();
        expect(screen.getByText('Low')).toBeInTheDocument();
    });

    it('shows "No active subscriptions" when by_plan is empty', () => {
        const props = {
            ...defaultProps,
            revenue: { ...revenue, by_plan: [] },
        };
        render(<AnalyticsIndex {...props} />);
        expect(screen.getByText('No active subscriptions')).toBeInTheDocument();
    });

    it('shows "No tickets yet" for support status when by_status is empty', () => {
        const props = {
            ...defaultProps,
            support: { ...support, by_status: [] },
        };
        render(<AnalyticsIndex {...props} />);
        expect(screen.getByText('No tickets yet')).toBeInTheDocument();
    });
});
