import { AdminPageHeader, adminLayout } from '@/Layouts/AdminLayout';
import { Button, Card, Checkbox, Input, Modal, Pill } from '@/Components/ui';
import { cn } from '@/lib/cn';
import type { SharedProps } from '@/types/inertia';
import { Head, Link, router, usePage } from '@inertiajs/react';
import { AlertCircle, CheckCircle2, Loader2 } from 'lucide-react';
import { useState, type SubmitEvent as ReactSubmitEvent } from 'react';

type UserDetail = {
    id: number;
    name: string;
    email: string;
    is_admin: boolean;
    email_verified_at: string | null;
    disabled_at: string | null;
    tenant: { id: number; name: string } | null;
    created_at: string | null;
};

type SubscriptionRow = {
    id: number;
    status: string;
    period: string;
    plan: { id: number; key: string; name: string } | null;
    provider_key: string;
    current_period_starts_at: string | null;
    current_period_ends_at: string | null;
    cancels_at_period_end: boolean;
    canceled_at: string | null;
};

type InvoiceRow = {
    id: number;
    amount_cents: number;
    currency: string;
    status: string;
    paid_at: string | null;
    provider_key: string;
    hosted_url: string | null;
};

type ProjectRow = {
    id: number;
    name: string;
    screens_count: number;
    updated_at: string | null;
};

type ProviderCustomerRow = {
    id: number;
    provider_key: string;
    provider_customer_id: string;
};

type AuditRow = {
    id: number;
    action: string;
    summary: string | null;
    actor: { id: number; name: string; email: string } | null;
    created_at: string | null;
};

type Props = {
    user: UserDetail;
    subscriptions: SubscriptionRow[];
    subscriptionsTotal: number;
    invoices: InvoiceRow[];
    invoicesTotal: number;
    projects: ProjectRow[];
    projectsTotal: number;
    providerCustomers: ProviderCustomerRow[];
    auditLog: AuditRow[];
    auditLogTotal: number;
};

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 {
    if (cents === 0) return '—';
    const major = cents / 100;
    const symbol = currency === 'INR' ? '₹' : '$';
    return `${symbol}${major.toLocaleString('en-US', {
        minimumFractionDigits: major % 1 === 0 ? 0 : 2,
        maximumFractionDigits: 2,
    })} ${currency}`;
}

function csrfHeaders(): Record<string, string> {
    const xsrf = document
        .querySelector('meta[name="csrf-token"]')
        ?.getAttribute('content');
    const cookieMatch = document.cookie.match(/(?:^|;\s*)XSRF-TOKEN=([^;]+)/);
    const cookieToken = cookieMatch ? decodeURIComponent(cookieMatch[1]) : null;
    const headers: Record<string, string> = {
        'Content-Type': 'application/json',
        Accept: 'application/json',
        'X-Requested-With': 'XMLHttpRequest',
    };
    if (xsrf) headers['X-CSRF-TOKEN'] = xsrf;
    if (cookieToken) headers['X-XSRF-TOKEN'] = cookieToken;
    return headers;
}

function AdminUsersShow({
    user,
    subscriptions,
    subscriptionsTotal,
    invoices,
    invoicesTotal,
    projects,
    projectsTotal,
    providerCustomers,
    auditLog,
    auditLogTotal,
}: Props) {
    const { auth, appMode } = usePage<SharedProps>().props;
    const isSaas = appMode === 'saas';
    const isSelf = auth.user?.id === user.id;
    const isDisabled = user.disabled_at !== null;
    const [confirmDelete, setConfirmDelete] = useState(false);

    const toggleDisabled = () => {
        // Routed through the bulk endpoint with a single id so we get the
        // same last-active-admin guard the index uses.
        router.post(
            '/admin/users/bulk',
            {
                ids: [user.id],
                action: isDisabled ? 'enable' : 'disable',
            },
            { preserveScroll: true },
        );
    };

    return (
        <>
            <Head title={`Admin · ${user.name}`} />
            <AdminPageHeader
                title={user.name}
                description={user.email}
                actions={
                    <div className="flex items-center gap-2">
                        {isSaas && !user.is_admin && !isSelf && !isDisabled && (
                            <Button
                                variant="secondary"
                                size="sm"
                                data-testid="admin-user-show-impersonate"
                                onClick={() =>
                                    router.post(
                                        `/admin/users/${user.id}/impersonate`,
                                    )
                                }
                            >
                                Impersonate
                            </Button>
                        )}
                        {!isSelf && (
                            <Button
                                variant={isDisabled ? 'primary' : 'secondary'}
                                size="sm"
                                data-testid="admin-user-show-toggle-disabled"
                                onClick={toggleDisabled}
                            >
                                {isDisabled ? 'Enable account' : 'Disable account'}
                            </Button>
                        )}
                        {!isSelf && (
                            <Button
                                variant="danger"
                                size="sm"
                                data-testid="admin-user-show-delete"
                                onClick={() => setConfirmDelete(true)}
                            >
                                Delete
                            </Button>
                        )}
                    </div>
                }
            />
                <div className="grid gap-6 lg:grid-cols-3">
                    <div className="lg:col-span-2 space-y-6">
                        <ProfileCard user={user} isSelf={isSelf} />
                        {isSaas && (
                            <>
                                <SubscriptionsSection
                                    subscriptions={subscriptions}
                                    total={subscriptionsTotal}
                                    userEmail={user.email}
                                />
                                <InvoicesSection
                                    invoices={invoices}
                                    total={invoicesTotal}
                                    userEmail={user.email}
                                />
                            </>
                        )}
                        <ProjectsSection
                            projects={projects}
                            total={projectsTotal}
                            tenantId={user.tenant?.id ?? null}
                        />
                    </div>
                    <div className="space-y-6">
                        {isSaas && (
                            <ProviderCustomersSection
                                providerCustomers={providerCustomers}
                            />
                        )}
                        <AuditSection
                            log={auditLog}
                            total={auditLogTotal}
                            userId={user.id}
                        />
                    </div>
                </div>

            {confirmDelete && (
                <DeleteConfirm
                    user={user}
                    onCancel={() => setConfirmDelete(false)}
                />
            )}
        </>
    );
}

AdminUsersShow.layout = adminLayout;

export default AdminUsersShow;

function DeleteConfirm({
    user,
    onCancel,
}: {
    user: UserDetail;
    onCancel: () => void;
}) {
    const isSaas = usePage<SharedProps>().props.appMode === 'saas';
    const [submitting, setSubmitting] = useState(false);
    const [error, setError] = useState<string | null>(null);

    const confirm = () => {
        setSubmitting(true);
        setError(null);
        // Successful delete redirects to the index via flash; no onSuccess
        // close needed because this whole page unmounts.
        router.delete(`/admin/users/${user.id}`, {
            onError: (errs) => {
                setError(errs.user ?? 'Delete failed.');
                setSubmitting(false);
            },
        });
    };

    return (
        <Modal
            open
            onClose={onCancel}
            size="md"
            closeOnBackdrop={false}
            closeOnEsc={!submitting}
            data-testid="admin-user-show-delete-modal"
        >
            <Modal.Header
                eyebrow="Delete user"
                eyebrowClassName="text-destructive"
                title={user.name}
            />
            <Modal.Body fade={false}>
                <p className="text-sm text-muted-foreground">
                    {isSaas ? (
                        <>
                            Hard-removes {user.email} and the tenant they
                            own — projects, screens, uploaded media, and
                            past exports all go with it.{' '}
                            <strong>Subscriptions and invoices are kept</strong>{' '}
                            for accounting (the email is snapshot onto each).
                            This can't be undone.
                        </>
                    ) : (
                        <>
                            Hard-removes {user.email} — their projects,
                            screens, uploaded media, and past exports all go
                            with it. This can't be undone.
                        </>
                    )}
                </p>
                {error && (
                    <p
                        className="text-xs text-destructive"
                        data-testid="admin-user-show-delete-error"
                    >
                        {error}
                    </p>
                )}
            </Modal.Body>
            <Modal.Footer>
                <Button
                    type="button"
                    variant="ghost"
                    onClick={onCancel}
                    disabled={submitting}
                    data-testid="admin-user-show-delete-cancel"
                >
                    Cancel
                </Button>
                <Button
                    type="button"
                    variant="danger"
                    onClick={confirm}
                    disabled={submitting}
                    data-testid="admin-user-show-delete-confirm"
                >
                    {submitting ? 'Deleting…' : 'Delete'}
                </Button>
            </Modal.Footer>
        </Modal>
    );
}

function SectionHeader({
    title,
    total,
    drillHref,
    more,
}: {
    title: string;
    total: number;
    drillHref: string | null;
    more: number;
}) {
    return (
        <div className="flex items-center justify-between gap-3">
            <h2 className="flex items-baseline gap-2 text-base font-semibold tracking-tight text-foreground">
                {title}
                {total > 0 && (
                    <span className="text-[11px] font-medium text-muted-foreground">
                        {total}
                    </span>
                )}
            </h2>
            {drillHref && more > 0 && (
                <Link
                    href={drillHref}
                    className="text-[11px] font-medium text-accent hover:underline"
                    data-testid={`admin-user-section-view-all-${title.toLowerCase().replace(/\s+/g, '-')}`}
                >
                    View all ({total}) →
                </Link>
            )}
            {drillHref && more === 0 && total > 0 && (
                <Link
                    href={drillHref}
                    className="text-[11px] font-medium text-muted-foreground hover:text-accent"
                    data-testid={`admin-user-section-view-all-${title.toLowerCase().replace(/\s+/g, '-')}`}
                >
                    View all
                </Link>
            )}
        </div>
    );
}

function ProfileCard({ user, isSelf }: { user: UserDetail; isSelf: boolean }) {
    const [name, setName] = useState(user.name);
    const [email, setEmail] = useState(user.email);
    const [isAdmin, setIsAdmin] = useState(user.is_admin);
    const [saving, setSaving] = useState(false);
    const [error, setError] = useState<string | null>(null);
    const [savedAt, setSavedAt] = useState<number | null>(null);

    const onSave = async (e: ReactSubmitEvent) => {
        e.preventDefault();
        setSaving(true);
        setError(null);
        const payload: Record<string, unknown> = {};
        if (name.trim() !== user.name) payload.name = name.trim();
        if (email.trim() !== user.email) payload.email = email.trim();
        if (isAdmin !== user.is_admin) payload.is_admin = isAdmin;

        if (Object.keys(payload).length === 0) {
            setSaving(false);
            return;
        }

        try {
            const res = await fetch(`/admin/users/${user.id}`, {
                method: 'PATCH',
                credentials: 'same-origin',
                headers: csrfHeaders(),
                body: JSON.stringify(payload),
            });
            if (!res.ok) {
                const body = await res.json().catch(() => null);
                const msg =
                    body?.message ??
                    body?.errors?.[Object.keys(body?.errors ?? {})[0]]?.[0] ??
                    `Save failed (${res.status}).`;
                setError(typeof msg === 'string' ? msg : 'Save failed.');
                return;
            }
            setSavedAt(Date.now());
            router.reload();
        } catch {
            setError('Network error. Try again.');
        } finally {
            setSaving(false);
        }
    };

    return (
        <Card padding="lg" data-testid="admin-user-profile">
            <div className="flex items-baseline justify-between gap-4">
                <div className="flex items-baseline gap-2">
                    <h2 className="text-base font-semibold tracking-tight text-foreground">
                        Profile
                    </h2>
                    {user.disabled_at !== null && (
                        <Pill tone="neutral" size="sm">
                            Disabled
                        </Pill>
                    )}
                </div>
                {savedAt && !error && (
                    <span className="inline-flex items-center gap-1.5 text-[11px] font-medium text-accent">
                        <CheckCircle2 className="h-3.5 w-3.5" strokeWidth={2.5} />
                        Saved
                    </span>
                )}
            </div>

            <form onSubmit={onSave} className="mt-4 space-y-4">
                <div className="grid gap-3 sm:grid-cols-2">
                    <div className="space-y-1.5">
                        <label
                            htmlFor="user-name"
                            className="text-[11px] font-medium text-muted-foreground"
                        >
                            Name
                        </label>
                        <Input
                            id="user-name"
                            value={name}
                            onChange={(e) => setName(e.target.value)}
                            data-testid="admin-user-name-input"
                        />
                    </div>
                    <div className="space-y-1.5">
                        <label
                            htmlFor="user-email"
                            className="text-[11px] font-medium text-muted-foreground"
                        >
                            Email
                        </label>
                        <Input
                            id="user-email"
                            type="email"
                            value={email}
                            onChange={(e) => setEmail(e.target.value)}
                            data-testid="admin-user-email-input"
                        />
                    </div>
                </div>

                <div className="grid gap-3 sm:grid-cols-2 text-[11px] text-muted-foreground">
                    <div>
                        <dt className="font-medium">Verified</dt>
                        <dd className="mt-0.5 text-foreground/80">
                            {user.email_verified_at ? 'Yes' : 'No'}
                        </dd>
                    </div>
                    <div>
                        <dt className="font-medium">Tenant</dt>
                        <dd className="mt-0.5 text-foreground/80">
                            {user.tenant ? (
                                <Link
                                    href={`/admin/tenants/${user.tenant.id}`}
                                    className="hover:text-accent"
                                >
                                    {user.tenant.name}
                                </Link>
                            ) : (
                                '—'
                            )}
                        </dd>
                    </div>
                    <div>
                        <dt className="font-medium">Joined</dt>
                        <dd className="mt-0.5 text-foreground/80">
                            {relativeTime(user.created_at)}
                        </dd>
                    </div>
                </div>

                <label className="flex items-center gap-2 text-[11px] font-medium text-foreground">
                    <Checkbox
                        checked={isAdmin}
                        onChange={(e) => setIsAdmin(e.target.checked)}
                        disabled={isSelf}
                        data-testid="admin-user-is-admin-toggle"
                    />
                    Admin
                    {isSelf && (
                        <span className="text-muted-foreground">
                            (self — can't change)
                        </span>
                    )}
                </label>

                {error && (
                    <div
                        className="flex items-start gap-2 rounded-lg border border-destructive/30 bg-destructive/5 px-3 py-2 text-[11px] font-medium text-destructive"
                        role="alert"
                        data-testid="admin-user-profile-error"
                    >
                        <AlertCircle
                            className="mt-0.5 h-3.5 w-3.5"
                            strokeWidth={2.5}
                        />
                        <span>{error}</span>
                    </div>
                )}

                <div className="flex items-center gap-3">
                    <Button
                        type="submit"
                        variant="primary"
                        size="sm"
                        disabled={saving}
                        data-testid="admin-user-profile-save"
                    >
                        {saving ? (
                            <Loader2
                                className="h-3.5 w-3.5 animate-spin"
                                strokeWidth={2}
                            />
                        ) : null}
                        Save changes
                    </Button>
                </div>
            </form>
        </Card>
    );
}

function SubscriptionsSection({
    subscriptions,
    total,
    userEmail,
}: {
    subscriptions: SubscriptionRow[];
    total: number;
    userEmail: string;
}) {
    const more = total - subscriptions.length;
    return (
        <Card padding="lg" data-testid="admin-user-subscriptions">
            <SectionHeader
                title="Subscriptions"
                total={total}
                drillHref={
                    total > 0
                        ? `/admin/subscriptions?q=${encodeURIComponent(userEmail)}`
                        : null
                }
                more={more}
            />
            {subscriptions.length === 0 ? (
                <p className="mt-3 text-[12px] text-muted-foreground">
                    No subscription rows.
                </p>
            ) : (
                <ul className="mt-4 max-h-[420px] space-y-2 overflow-y-auto">
                    {subscriptions.map((s) => (
                        <li
                            key={s.id}
                            className="flex items-center justify-between rounded-lg border border-border bg-card/50 px-3 py-2.5"
                        >
                            <div className="flex flex-col">
                                <Link
                                    href={`/admin/subscriptions/${s.id}`}
                                    className="text-sm font-medium text-foreground hover:text-accent"
                                >
                                    {s.plan?.name ?? 'Unknown plan'}
                                </Link>
                                <span className="text-[11px] text-muted-foreground">
                                    {s.period} · {s.provider_key}
                                </span>
                            </div>
                            <div className="flex flex-col items-end">
                                <Pill
                                    tone={
                                        s.status === 'active'
                                            ? 'success'
                                            : s.status === 'trialing'
                                              ? 'accent'
                                              : 'neutral'
                                    }
                                    size="sm"
                                >
                                    {s.status}
                                </Pill>
                                <span className="mt-1 text-[10px] text-muted-foreground">
                                    {s.cancels_at_period_end
                                        ? `cancels ${relativeTime(s.current_period_ends_at)}`
                                        : s.canceled_at
                                          ? `canceled ${relativeTime(s.canceled_at)}`
                                          : `renews ${relativeTime(s.current_period_ends_at)}`}
                                </span>
                            </div>
                        </li>
                    ))}
                </ul>
            )}
        </Card>
    );
}

function InvoicesSection({
    invoices,
    total,
    userEmail,
}: {
    invoices: InvoiceRow[];
    total: number;
    userEmail: string;
}) {
    const more = total - invoices.length;
    return (
        <Card padding="lg" data-testid="admin-user-invoices">
            <SectionHeader
                title="Invoices"
                total={total}
                drillHref={
                    total > 0
                        ? `/admin/invoices?q=${encodeURIComponent(userEmail)}`
                        : null
                }
                more={more}
            />
            {invoices.length === 0 ? (
                <p className="mt-3 text-[12px] text-muted-foreground">
                    No invoices.
                </p>
            ) : (
                <table className="mt-3 w-full text-sm">
                    <thead className="text-left text-[11px] font-medium text-muted-foreground">
                        <tr>
                            <th className="py-1.5">Amount</th>
                            <th className="py-1.5">Status</th>
                            <th className="py-1.5">Paid</th>
                            <th className="py-1.5">Provider</th>
                        </tr>
                    </thead>
                    <tbody>
                        {invoices.map((inv) => (
                            <tr
                                key={inv.id}
                                className="border-t border-border/60 text-[12px]"
                            >
                                <td className="py-2 tabular-nums text-foreground/90">
                                    {formatMoney(inv.amount_cents, inv.currency)}
                                </td>
                                <td className="py-2">
                                    <span
                                        className={cn(
                                            'rounded-full px-2 py-0.5 text-[10px] font-medium',
                                            inv.status === 'paid'
                                                ? 'border border-success/30 bg-success/10 text-success'
                                                : 'border border-border bg-muted text-muted-foreground',
                                        )}
                                    >
                                        {inv.status}
                                    </span>
                                </td>
                                <td className="py-2 text-muted-foreground">
                                    {relativeTime(inv.paid_at)}
                                </td>
                                <td className="py-2 font-mono text-[11px] text-muted-foreground">
                                    {inv.provider_key}
                                </td>
                            </tr>
                        ))}
                    </tbody>
                </table>
            )}
        </Card>
    );
}

function ProjectsSection({
    projects,
    total,
    tenantId,
}: {
    projects: ProjectRow[];
    total: number;
    tenantId: number | null;
}) {
    const more = total - projects.length;
    return (
        <Card padding="lg" data-testid="admin-user-projects">
            <SectionHeader
                title="Projects"
                total={total}
                drillHref={tenantId !== null && total > 0 ? `/admin/tenants/${tenantId}` : null}
                more={more}
            />
            {projects.length === 0 ? (
                <p className="mt-3 text-[12px] text-muted-foreground">
                    No projects.
                </p>
            ) : (
                <ul className="mt-3 max-h-[420px] divide-y divide-border/60 overflow-y-auto">
                    {projects.map((p) => (
                        <li
                            key={p.id}
                            className="flex items-center justify-between py-2"
                        >
                            <span className="text-sm text-foreground">
                                {p.name}
                            </span>
                            <span className="text-[11px] text-muted-foreground">
                                {p.screens_count}{' '}
                                {p.screens_count === 1 ? 'screen' : 'screens'} ·{' '}
                                {relativeTime(p.updated_at)}
                            </span>
                        </li>
                    ))}
                </ul>
            )}
        </Card>
    );
}

function ProviderCustomersSection({
    providerCustomers,
}: {
    providerCustomers: ProviderCustomerRow[];
}) {
    return (
        <Card padding="lg" data-testid="admin-user-provider-customers">
            <h2 className="text-base font-semibold tracking-tight text-foreground">
                Provider customers
            </h2>
            {providerCustomers.length === 0 ? (
                <p className="mt-3 text-[12px] text-muted-foreground">
                    No provider customer ids on file.
                </p>
            ) : (
                <ul className="mt-3 space-y-2">
                    {providerCustomers.map((c) => (
                        <li
                            key={c.id}
                            className="flex flex-col rounded-md border border-border bg-card/50 px-3 py-2"
                        >
                            <span className="text-[11px] font-medium text-muted-foreground">
                                {c.provider_key}
                            </span>
                            <span className="mt-0.5 font-mono text-[12px] text-foreground/80">
                                {c.provider_customer_id}
                            </span>
                        </li>
                    ))}
                </ul>
            )}
        </Card>
    );
}

function AuditSection({
    log,
    total,
    userId,
}: {
    log: AuditRow[];
    total: number;
    userId: number;
}) {
    const more = total - log.length;
    return (
        <Card padding="lg" data-testid="admin-user-audit-log">
            <SectionHeader
                title="Audit log"
                total={total}
                drillHref={
                    total > 0
                        ? `/admin/audit-log?target_type=User&target_id=${userId}`
                        : null
                }
                more={more}
            />
            {log.length === 0 ? (
                <p className="mt-3 text-[12px] text-muted-foreground">
                    No audit entries reference this user.
                </p>
            ) : (
                <ul className="mt-3 max-h-[480px] space-y-3 overflow-y-auto text-[12px]">
                    {log.map((row) => (
                        <li
                            key={row.id}
                            className="flex flex-col gap-1 border-b border-border/60 pb-3 last:border-0"
                        >
                            <span className="font-mono text-[11px] text-accent">
                                {row.action}
                            </span>
                            <span className="text-foreground/80">
                                {row.summary ?? '—'}
                            </span>
                            <span className="text-[11px] text-muted-foreground">
                                {row.actor?.email ?? 'system'} ·{' '}
                                {relativeTime(row.created_at)}
                            </span>
                        </li>
                    ))}
                </ul>
            )}
        </Card>
    );
}
