import { AdminPageHeader, adminLayout } from '@/Layouts/AdminLayout';
import { Card, Pill } from '@/Components/ui';
import { cn } from '@/lib/cn';
import { Head, Link } from '@inertiajs/react';
import { type ReactNode } from 'react';
import {
    AlertTriangle,
    ArrowRight,
    CheckCircle2,
    Circle,
    CreditCard,
    FileText,
    FolderKanban,
    Sparkles,
    TrendingUp,
    UserPlus,
    Users,
    Webhook,
} from 'lucide-react';
import { CountUp } from '@/lib/count-up';

type MrrBreakdownRow = {
    currency_code: string;
    currency_symbol: string | null;
    mrr_cents: number;
    subscription_count: number;
};

type Kpis = {
    mrr_breakdown: MrrBreakdownRow[];
    active_subscriptions: number;
    total_users: number;
    total_projects: number;
};

type SignupSeriesPoint = { day: string; count: number };

type Signups = {
    last_30_days: number;
    series: SignupSeriesPoint[];
};

type SubscriptionBreakdown = { status: string; count: number };

type RecentInvoice = {
    id: number;
    user_email: string | null;
    user_id: number | null;
    plan_name: string | null;
    amount_cents: number;
    currency: string;
    status: string;
    paid_at: string | null;
};

type RecentWebhookEvent = {
    id: number;
    provider_key: string;
    event_type: string;
    processed_at: string;
};

type RecentSignup = {
    id: number;
    name: string;
    email: string;
    created_at: string;
};

type SystemHealth = {
    failed_jobs_count: number;
    recent_webhook_errors: number;
};

type OnboardingItem = {
    key: string;
    label: string;
    description: string;
    critical: boolean;
    done: boolean;
    href: string;
};

type Onboarding = {
    should_show: boolean;
    critical_done: number;
    critical_total: number;
    total_done: number;
    total: number;
    items: OnboardingItem[];
};

type Props = {
    kpis: Kpis;
    signups: Signups;
    subscription_breakdown: SubscriptionBreakdown[];
    recent_invoices: RecentInvoice[];
    recent_webhook_events: RecentWebhookEvent[];
    recent_signups: RecentSignup[];
    system_health: SystemHealth;
    onboarding: Onboarding;
};

const RELATIVE_FMT = new Intl.RelativeTimeFormat('en', { numeric: 'auto' });

function relativeTime(iso: string | null): string {
    if (!iso) return '—';
    const diffMs = new Date(iso).getTime() - Date.now();
    const absMin = Math.abs(diffMs) / 60_000;
    if (absMin < 1) return 'just now';
    if (absMin < 60) return RELATIVE_FMT.format(Math.round(diffMs / 60_000), 'minute');
    if (absMin < 60 * 24) return RELATIVE_FMT.format(Math.round(diffMs / 3_600_000), 'hour');
    if (absMin < 60 * 24 * 30) return RELATIVE_FMT.format(Math.round(diffMs / 86_400_000), 'day');
    if (absMin < 60 * 24 * 365) return RELATIVE_FMT.format(Math.round(diffMs / (86_400_000 * 30)), 'month');
    return RELATIVE_FMT.format(Math.round(diffMs / (86_400_000 * 365)), 'year');
}

function formatMoney(cents: number, currency: string): string {
    try {
        return new Intl.NumberFormat('en-US', {
            style: 'currency',
            currency,
            minimumFractionDigits: cents % 100 === 0 ? 0 : 2,
            maximumFractionDigits: 2,
        }).format(cents / 100);
    } catch {
        return `${currency} ${(cents / 100).toFixed(2)}`;
    }
}

function formatNumber(n: number): string {
    return new Intl.NumberFormat('en-US').format(n);
}

const STATUS_LABELS: Record<string, string> = {
    active: 'Active',
    trialing: 'Trialing',
    past_due: 'Past due',
    canceled: 'Canceled',
};

const STATUS_TONES: Record<string, 'accent' | 'success' | 'neutral'> = {
    active: 'success',
    trialing: 'accent',
    past_due: 'neutral',
    canceled: 'neutral',
};

function AdminDashboard({
    kpis,
    signups,
    subscription_breakdown,
    recent_invoices,
    recent_webhook_events,
    recent_signups,
    system_health,
    onboarding,
}: Props) {
    return (
        <>
            <Head title="Admin · Dashboard" />
            <AdminPageHeader title="Dashboard" description="At-a-glance health of the SaaS." />
            <div className="flex flex-col gap-6">
                {onboarding.should_show && (
                    <OnboardingCard onboarding={onboarding} />
                )}

                <KpiRow kpis={kpis} />

                <SystemHealthRow health={system_health} />

                <div className="grid gap-6 lg:grid-cols-3">
                    <SignupsCard signups={signups} />
                    <SubscriptionBreakdownCard rows={subscription_breakdown} />
                </div>

                <div className="grid gap-6 lg:grid-cols-2">
                    <RecentInvoicesCard invoices={recent_invoices} />
                    <RecentWebhookEventsCard events={recent_webhook_events} />
                </div>

                <RecentSignupsCard signups={recent_signups} />
            </div>
        </>
    );
}

AdminDashboard.layout = adminLayout;

export default AdminDashboard;

function OnboardingCard({ onboarding }: { onboarding: Onboarding }) {
    const { items, critical_done, critical_total, total_done, total } =
        onboarding;
    const criticalPct =
        critical_total > 0
            ? Math.round((critical_done / critical_total) * 100)
            : 0;

    return (
        <Card
            padding="md"
            className="flex flex-col gap-4 border-accent/30 bg-accent/[0.03]"
            data-testid="admin-dashboard-onboarding"
        >
            <div className="flex flex-wrap items-start justify-between gap-3">
                <div className="flex items-start gap-3">
                    <span className="flex h-9 w-9 items-center justify-center rounded-md bg-accent/10 text-accent">
                        <Sparkles className="h-4 w-4" strokeWidth={2.5} />
                    </span>
                    <div>
                        <h2 className="text-sm font-semibold text-foreground">
                            Finish setting up your install
                        </h2>
                        <p className="mt-0.5 text-[12px] text-muted-foreground">
                            {critical_done}/{critical_total} critical · {total_done}/{total} total. The card auto-hides once the critical items are done.
                        </p>
                    </div>
                </div>
                <span className="text-[11px] font-medium tabular-nums text-muted-foreground">
                    {criticalPct}% critical
                </span>
            </div>

            <div
                className="h-1.5 w-full overflow-hidden rounded-full bg-muted"
                role="progressbar"
                aria-label="Critical onboarding progress"
                aria-valuenow={critical_done}
                aria-valuemin={0}
                aria-valuemax={critical_total}
            >
                <div
                    className="h-full bg-accent transition-all duration-200 ease-out"
                    style={{ width: `${criticalPct}%` }}
                />
            </div>

            <ul className="flex flex-col divide-y divide-border/60">
                {items.map((item) => (
                    <OnboardingRow key={item.key} item={item} />
                ))}
            </ul>
        </Card>
    );
}

function OnboardingRow({ item }: { item: OnboardingItem }) {
    return (
        <li className="flex items-start gap-3 py-2.5">
            {item.done ? (
                <CheckCircle2
                    className="mt-0.5 h-4 w-4 shrink-0 text-success"
                    strokeWidth={2.5}
                />
            ) : (
                <Circle
                    className="mt-0.5 h-4 w-4 shrink-0 text-muted-foreground/60"
                    strokeWidth={2}
                />
            )}
            <div className="min-w-0 flex-1">
                <div className="flex flex-wrap items-baseline gap-1.5">
                    <span
                        className={cn(
                            'text-[13px] font-medium',
                            item.done
                                ? 'text-muted-foreground line-through decoration-muted-foreground/40'
                                : 'text-foreground',
                        )}
                    >
                        {item.label}
                    </span>
                    {item.critical && !item.done && (
                        <span className="inline-flex items-center rounded-full border border-warning/30 bg-warning/10 px-1.5 py-0.5 text-[10px] font-medium text-warning">
                            Required
                        </span>
                    )}
                </div>
                <p className="mt-0.5 text-[11.5px] text-muted-foreground">
                    {item.description}
                </p>
            </div>
            {!item.done && (
                <Link
                    href={item.href}
                    className="flex shrink-0 items-center gap-1 text-[12px] font-medium text-accent hover:underline"
                >
                    Configure
                    <ArrowRight className="h-3 w-3" strokeWidth={2.5} />
                </Link>
            )}
        </li>
    );
}

function SystemHealthRow({ health }: { health: SystemHealth }) {
    const failed = health.failed_jobs_count;
    const errors = health.recent_webhook_errors;
    const healthy = failed === 0 && errors === 0;

    return (
        <Card
            padding="md"
            className={cn(
                'flex flex-wrap items-center justify-between gap-4',
                healthy
                    ? 'border-border'
                    : 'border-warning/30 bg-warning/10',
            )}
            data-testid="admin-dashboard-system-health"
        >
            <div className="flex items-center gap-3">
                <span
                    className={cn(
                        'flex h-7 w-7 items-center justify-center rounded-md',
                        healthy
                            ? 'bg-accent/10 text-accent'
                            : 'bg-warning/20 text-warning',
                    )}
                >
                    {healthy ? (
                        <CheckCircle2 className="h-4 w-4" strokeWidth={2} />
                    ) : (
                        <AlertTriangle className="h-4 w-4" strokeWidth={2} />
                    )}
                </span>
                <div>
                    <p className="text-[11px] font-medium text-muted-foreground">
                        System health
                    </p>
                    <p className="text-sm font-medium text-foreground">
                        {healthy ? 'All systems normal' : 'Attention needed'}
                    </p>
                </div>
            </div>
            <div className="flex items-center gap-6">
                <HealthMetric
                    label="Failed jobs"
                    count={failed}
                    tone={failed > 0 ? 'warning' : 'ok'}
                />
                <HealthMetric
                    label="Webhook replay errors (24h)"
                    count={errors}
                    tone={errors > 0 ? 'warning' : 'ok'}
                    href="/admin/audit-log?action=webhookevent.replay.failed"
                />
            </div>
        </Card>
    );
}

function HealthMetric({
    label,
    count,
    tone,
    href,
}: {
    label: string;
    count: number;
    tone: 'ok' | 'warning';
    href?: string;
}) {
    const numClass =
        tone === 'warning' ? 'text-warning' : 'text-foreground';
    const body = (
        <div className="flex flex-col items-end">
            <span className={cn('text-base font-semibold tabular-nums', numClass)}>
                {formatNumber(count)}
            </span>
            <span className="text-[10px] text-muted-foreground">{label}</span>
        </div>
    );

    if (href && tone === 'warning') {
        return (
            <Link
                href={href}
                className="rounded transition-colors hover:bg-muted/40"
            >
                {body}
            </Link>
        );
    }

    return body;
}

function KpiRow({ kpis }: { kpis: Kpis }) {
    return (
        <div className="grid gap-4 sm:grid-cols-2 lg:grid-cols-4">
            <MrrCard breakdown={kpis.mrr_breakdown} />
            <KpiCard
                href="/admin/subscriptions?status=active"
                icon={<CreditCard className="h-4 w-4" strokeWidth={2} />}
                label="Active subscriptions"
                value={<CountUp value={kpis.active_subscriptions} format={formatNumber} />}
                hint="Active or trialing"
            />
            <KpiCard
                href="/admin/users"
                icon={<Users className="h-4 w-4" strokeWidth={2} />}
                label="Total users"
                value={<CountUp value={kpis.total_users} format={formatNumber} />}
                hint="All registered accounts"
            />
            <KpiCard
                href="/admin/tenants"
                icon={<FolderKanban className="h-4 w-4" strokeWidth={2} />}
                label="Projects"
                value={<CountUp value={kpis.total_projects} format={formatNumber} />}
                hint="Across all tenants"
            />
        </div>
    );
}

/**
 * MRR card with per-currency rows. Currencies appear and disappear
 * dynamically as subscriptions in those currencies are created or
 * canceled — no hardcoded list. Aggregating across currencies would
 * require an FX rate (intentionally not in v1), so each currency
 * gets its own line.
 */
function MrrCard({ breakdown }: { breakdown: MrrBreakdownRow[] }) {
    return (
        <Link
            href="/admin/subscriptions?status=active"
            className="group flex flex-col gap-2 rounded-xl border border-border bg-card p-4 shadow-sm transition-all hover:border-accent/40 hover:shadow-md"
            data-testid="admin-dashboard-mrr-card"
        >
            <div className="flex items-center justify-between text-[11px] font-medium uppercase tracking-wide text-muted-foreground">
                <span>MRR</span>
                <TrendingUp className="h-4 w-4" strokeWidth={2} />
            </div>
            {breakdown.length === 0 ? (
                <>
                    <div className="text-2xl font-semibold tracking-tight text-foreground">
                        —
                    </div>
                    <p className="text-[11px] text-muted-foreground">
                        No active subscriptions yet
                    </p>
                </>
            ) : (
                <ul
                    className="flex flex-col gap-1"
                    data-testid="admin-dashboard-mrr-breakdown"
                >
                    {breakdown.map((row) => (
                        <li
                            key={row.currency_code}
                            className="flex items-baseline justify-between gap-2"
                            data-testid={`admin-dashboard-mrr-row-${row.currency_code}`}
                        >
                            <span className="text-lg font-semibold tracking-tight text-foreground">
                                <CountUp value={row.mrr_cents} format={(n) => formatMoney(n, row.currency_code)} />
                            </span>
                            <span className="text-[11px] text-muted-foreground">
                                {row.subscription_count}{' '}
                                {row.subscription_count === 1 ? 'sub' : 'subs'}
                            </span>
                        </li>
                    ))}
                </ul>
            )}
        </Link>
    );
}

function KpiCard({
    icon,
    label,
    value,
    hint,
    href,
}: {
    icon: ReactNode;
    label: string;
    value: ReactNode;
    hint?: string;
    href?: string;
}) {
    const body = (
        <>
            <div className="flex items-center gap-2 text-[11px] font-medium text-muted-foreground">
                <span className="flex h-7 w-7 items-center justify-center rounded-md bg-muted text-foreground/70">
                    {icon}
                </span>
                <span>{label}</span>
            </div>
            <div className="text-2xl font-semibold tracking-tight text-foreground">
                {value}
            </div>
            {hint && (
                <p className="text-[11px] text-muted-foreground">{hint}</p>
            )}
        </>
    );

    if (href) {
        return (
            <Link
                href={href}
                className="block rounded-xl transition-colors focus-visible:outline-2 focus-visible:outline-accent"
            >
                <Card
                    variant="interactive"
                    padding="md"
                    className="flex flex-col gap-2"
                >
                    {body}
                </Card>
            </Link>
        );
    }

    return (
        <Card padding="md" className="flex flex-col gap-2">
            {body}
        </Card>
    );
}

function SignupsCard({ signups }: { signups: Signups }) {
    const series = signups.series;
    const max = series.reduce((acc, p) => Math.max(acc, p.count), 0);

    return (
        <Card padding="md" className="lg:col-span-2 flex flex-col gap-4">
            <div className="flex items-start justify-between gap-3">
                <div>
                    <p className="text-[11px] font-medium text-muted-foreground">
                        Signups · last 30 days
                    </p>
                    <p className="mt-1 text-2xl font-semibold tracking-tight text-foreground">
                        {formatNumber(signups.last_30_days)}
                        <span className="ml-2 text-sm font-normal text-muted-foreground">
                            new {signups.last_30_days === 1 ? 'user' : 'users'} this month
                        </span>
                    </p>
                </div>
                <span className="flex h-7 w-7 items-center justify-center rounded-md bg-muted text-foreground/70">
                    <UserPlus className="h-4 w-4" strokeWidth={2} />
                </span>
            </div>

            <div
                className="relative flex h-24 items-end gap-[3px] border-b border-border/50"
                role="img"
                aria-label={`Daily signups for the last 30 days, total ${signups.last_30_days}`}
            >
                {series.map((point) => {
                    // Min height 3% so an empty day still renders a faint
                    // baseline tick — totally-blank columns hide the
                    // chart's date span and feel broken.
                    const pct = max === 0 ? 0 : (point.count / max) * 100;
                    const heightPct = pct === 0 ? 3 : Math.max(pct, 8);
                    return (
                        <div
                            key={point.day}
                            className={cn(
                                'flex-1 rounded-sm transition-colors',
                                point.count > 0
                                    ? 'bg-accent/70 hover:bg-accent'
                                    : 'bg-muted',
                            )}
                            style={{ height: `${heightPct}%` }}
                            title={`${point.day}: ${point.count}`}
                        />
                    );
                })}
            </div>

            <div className="flex justify-between text-[10px] text-muted-foreground">
                <span>{formatDayShort(series[0]?.day)}</span>
                <span>{formatDayShort(series[series.length - 1]?.day)}</span>
            </div>
        </Card>
    );
}

function formatDayShort(iso: string | undefined): string {
    if (!iso) return '';
    const d = new Date(`${iso}T00:00:00Z`);
    return new Intl.DateTimeFormat('en-US', {
        month: 'short',
        day: 'numeric',
        timeZone: 'UTC',
    }).format(d);
}

function SubscriptionBreakdownCard({ rows }: { rows: SubscriptionBreakdown[] }) {
    return (
        <Card padding="md" className="flex flex-col gap-3">
            <p className="text-[11px] font-medium text-muted-foreground">
                Subscriptions
            </p>
            <ul className="flex flex-col gap-2">
                {rows.map((row) => {
                    const href = `/admin/subscriptions?status=${row.status}`;
                    return (
                        <li key={row.status}>
                            <Link
                                href={href}
                                className="-mx-1 flex items-center justify-between gap-3 rounded px-1 py-0.5 transition-colors hover:bg-muted/50"
                            >
                                <Pill
                                    tone={STATUS_TONES[row.status] ?? 'neutral'}
                                    size="sm"
                                >
                                    {STATUS_LABELS[row.status] ?? row.status}
                                </Pill>
                                <span className="text-base font-semibold tabular-nums text-foreground">
                                    {formatNumber(row.count)}
                                </span>
                            </Link>
                        </li>
                    );
                })}
            </ul>
        </Card>
    );
}

function RecentInvoicesCard({ invoices }: { invoices: RecentInvoice[] }) {
    return (
        <Card padding="md" className="flex flex-col gap-3">
            <div className="flex items-center justify-between">
                <p className="flex items-center gap-2 text-[11px] font-medium text-muted-foreground">
                    <FileText className="h-3.5 w-3.5" strokeWidth={2} />
                    Recent invoices
                </p>
                <Link
                    href="/admin/invoices"
                    className="text-[11px] font-medium text-accent hover:underline"
                >
                    View all
                </Link>
            </div>

            {invoices.length === 0 ? (
                <EmptyState message="No invoices yet." />
            ) : (
                <div className="overflow-x-auto">
                    <table className="w-full text-left text-sm">
                        <thead className="text-[11px] font-medium text-muted-foreground">
                            <tr>
                                <th className="py-1.5 pr-3">User</th>
                                <th className="py-1.5 pr-3">Plan</th>
                                <th className="py-1.5 pr-3">Amount</th>
                                <th className="py-1.5 pr-3">Status</th>
                                <th className="py-1.5">Paid at</th>
                            </tr>
                        </thead>
                        <tbody>
                            {invoices.map((inv) => (
                                <tr
                                    key={inv.id}
                                    className="border-t border-border/60 align-middle"
                                >
                                    <td className="py-2 pr-3">
                                        {inv.user_id && inv.user_email ? (
                                            <Link
                                                href={`/admin/users/${inv.user_id}`}
                                                className="text-foreground hover:text-accent hover:underline"
                                            >
                                                {inv.user_email}
                                            </Link>
                                        ) : (
                                            <span className="text-muted-foreground">
                                                {inv.user_email ?? '—'}
                                            </span>
                                        )}
                                    </td>
                                    <td className="py-2 pr-3 text-muted-foreground">
                                        {inv.plan_name ?? '—'}
                                    </td>
                                    <td className="py-2 pr-3 tabular-nums text-foreground">
                                        {formatMoney(inv.amount_cents, inv.currency)}
                                    </td>
                                    <td className="py-2 pr-3">
                                        <span
                                            className={cn(
                                                'rounded-full px-2 py-0.5 text-[10px] font-medium',
                                                inv.status === 'paid'
                                                    ? 'bg-success/10 text-success'
                                                    : 'bg-muted text-muted-foreground',
                                            )}
                                        >
                                            {inv.status}
                                        </span>
                                    </td>
                                    <td className="py-2 text-muted-foreground">
                                        {inv.paid_at ? relativeTime(inv.paid_at) : '—'}
                                    </td>
                                </tr>
                            ))}
                        </tbody>
                    </table>
                </div>
            )}
        </Card>
    );
}

function RecentWebhookEventsCard({ events }: { events: RecentWebhookEvent[] }) {
    return (
        <Card padding="md" className="flex flex-col gap-3">
            <div className="flex items-center justify-between">
                <Link
                    href="/admin/webhook-events"
                    className="flex items-center gap-2 text-[11px] font-medium text-muted-foreground hover:text-foreground"
                >
                    <Webhook className="h-3.5 w-3.5" strokeWidth={2} />
                    Recent webhook events
                </Link>
                <Link
                    href="/admin/webhook-events"
                    className="text-[11px] font-medium text-accent hover:underline"
                >
                    View all
                </Link>
            </div>

            {events.length === 0 ? (
                <EmptyState message="No webhook events yet." />
            ) : (
                <ul className="flex flex-col divide-y divide-border/60">
                    {events.map((event) => (
                        <li key={event.id}>
                            <Link
                                href={`/admin/webhook-events/${event.id}`}
                                className="-mx-1 flex items-center justify-between gap-3 rounded px-1 py-2 text-sm transition-colors hover:bg-muted/50"
                            >
                                <div className="flex min-w-0 items-center gap-2">
                                    <span className="rounded bg-muted px-1.5 py-0.5 text-[10px] font-medium uppercase text-muted-foreground">
                                        {event.provider_key}
                                    </span>
                                    <span className="truncate font-medium text-foreground">
                                        {event.event_type}
                                    </span>
                                </div>
                                <span className="shrink-0 text-[11px] text-muted-foreground">
                                    {relativeTime(event.processed_at)}
                                </span>
                            </Link>
                        </li>
                    ))}
                </ul>
            )}
        </Card>
    );
}

function RecentSignupsCard({ signups }: { signups: RecentSignup[] }) {
    return (
        <Card padding="md" className="flex flex-col gap-3">
            <div className="flex items-center justify-between">
                <p className="flex items-center gap-2 text-[11px] font-medium text-muted-foreground">
                    <UserPlus className="h-3.5 w-3.5" strokeWidth={2} />
                    Recent signups
                </p>
                <Link
                    href="/admin/users"
                    className="text-[11px] font-medium text-accent hover:underline"
                >
                    View all users
                </Link>
            </div>

            {signups.length === 0 ? (
                <EmptyState message="No users yet." />
            ) : (
                <ul className="flex flex-col divide-y divide-border/60">
                    {signups.map((user) => (
                        <li
                            key={user.id}
                            className="flex items-center justify-between gap-3 py-2 text-sm"
                        >
                            <div className="flex min-w-0 flex-col">
                                <Link
                                    href={`/admin/users/${user.id}`}
                                    className="truncate font-medium text-foreground hover:text-accent hover:underline"
                                >
                                    {user.name}
                                </Link>
                                <span className="truncate text-[11px] text-muted-foreground">
                                    {user.email}
                                </span>
                            </div>
                            <span className="shrink-0 text-[11px] text-muted-foreground">
                                {relativeTime(user.created_at)}
                            </span>
                        </li>
                    ))}
                </ul>
            )}
        </Card>
    );
}

function EmptyState({ message }: { message: string }) {
    return (
        <div className="rounded-md border border-dashed border-border/60 p-6 text-center text-[11px] text-muted-foreground">
            {message}
        </div>
    );
}
