import { Head, Link, router } from '@inertiajs/react';
import { useEffect, useRef, useState } from 'react';
import { Badge } from '@/components/ui/badge';
import { Button } from '@/components/ui/button';
import {
    Card,
    CardContent,
    CardDescription,
    CardFooter,
    CardHeader,
    CardTitle,
} from '@/components/ui/card';
import {
    Dialog,
    DialogContent,
    DialogDescription,
    DialogFooter,
    DialogHeader,
    DialogTitle,
} from '@/components/ui/dialog';
import {
    Select,
    SelectContent,
    SelectItem,
    SelectTrigger,
    SelectValue,
} from '@/components/ui/select';
import {
    Table,
    TableBody,
    TableCell,
    TableHead,
    TableHeader,
    TableRow,
} from '@/components/ui/table';
import { creditsLabel } from '@/lib/credits';
import { formatDate, formatEuro } from '@/lib/format';
import { cn } from '@/lib/utils';
import { index as billingIndex, portal } from '@/routes/billing';
import { checkout as packageCheckout } from '@/routes/billing/packages';
import {
    checkout as subscriptionCheckout,
    swap as subscriptionSwap,
} from '@/routes/billing/subscription';
import type {
    CreditMovement,
    CreditMovementKind,
    CreditsOverview,
    CurrentPlan,
    Order,
    Package,
    PlanOverview,
} from '@/types';

type Subscription = {
    status: string;
    active: boolean;
    on_grace_period: boolean;
    ends_at: string | null;
};

type Props = {
    packages?: Package[];
    credits?: CreditsOverview;
    /** Vecchio prop, tenuto come riserva finché il backend non espone `credits`. */
    creditsAvailable?: number;
    subscription?: Subscription | null;
    orders?: Order[];
    movements?: CreditMovement[];
    highlightPackage?: string | null;
    plan?: PlanOverview;
};

const orderStatusLabels: Record<Order['status'], string> = {
    pending: 'In attesa',
    paid: 'Pagato',
    failed: 'Fallito',
    refunded: 'Rimborsato',
};

const orderStatusVariants: Record<
    Order['status'],
    'default' | 'secondary' | 'destructive' | 'outline'
> = {
    pending: 'outline',
    paid: 'secondary',
    failed: 'destructive',
    refunded: 'outline',
};

const movementLabels: Record<CreditMovementKind, string> = {
    grant: 'Accredito',
    consume: 'Consumo',
    refund: 'Rimborso',
    expire: 'Scadenza',
    rollover: 'Riporto crediti',
    forfeit: 'Oltre il massimale di riporto',
};

const quantityOptions = Array.from({ length: 10 }, (_, i) => i + 1);

const intervalSuffix = (interval: Package['interval']) =>
    interval === 'year' ? '/anno' : '/mese';

/** "40 crediti al mese". */
const planCreditsLine = (credits: number, interval: Package['interval']) =>
    `${creditsLabel(credits)} ${interval === 'year' ? "all'anno" : 'al mese'}`;

/* -------------------------------------------------------------------------
 * Saldo
 * ---------------------------------------------------------------------- */

function CreditBalance({ credits }: { credits: CreditsOverview }) {
    return (
        <Card>
            <CardContent className="flex flex-wrap items-end justify-between gap-x-10 gap-y-6">
                <div>
                    <p className="text-muted-foreground text-sm">
                        Crediti disponibili
                    </p>
                    <p className="text-5xl leading-none font-semibold tabular-nums">
                        {credits.available}
                    </p>
                </div>

                <dl className="border-border grid gap-x-8 gap-y-2 border-l pl-6 text-sm sm:grid-cols-2">
                    <div>
                        <dt className="text-muted-foreground">In scadenza</dt>
                        <dd className="font-medium tabular-nums">
                            {credits.expiring_soon}
                            {credits.expiring_at && (
                                <span className="text-muted-foreground font-normal">
                                    {' '}
                                    il {formatDate(credits.expiring_at)}
                                </span>
                            )}
                        </dd>
                    </div>
                    <div>
                        <dt className="text-muted-foreground">
                            Consumati in 30 giorni
                        </dt>
                        <dd className="font-medium tabular-nums">
                            {credits.consumed_30d}
                        </dd>
                    </div>
                </dl>
            </CardContent>
        </Card>
    );
}

/* -------------------------------------------------------------------------
 * Piano attuale
 * ---------------------------------------------------------------------- */

function CurrentPlanCard({
    current,
    otherPlans,
    onSwitch,
}: {
    current: CurrentPlan;
    otherPlans: Package[];
    onSwitch: () => void;
}) {
    return (
        <Card>
            <CardHeader>
                <div className="flex flex-wrap items-baseline justify-between gap-x-4 gap-y-1">
                    <CardTitle className="text-xl">{current.name}</CardTitle>
                    <p className="tabular-nums">
                        <span className="text-xl font-semibold">
                            {formatEuro(current.price_cents)}
                        </span>
                        <span className="text-muted-foreground ml-1 text-sm">
                            {intervalSuffix(current.interval)}
                        </span>
                    </p>
                </div>
                <CardDescription>
                    {planCreditsLine(current.credits, current.interval)}
                </CardDescription>
            </CardHeader>
            <CardContent>
                <p className="text-muted-foreground text-sm">
                    {current.renews_at
                        ? `I crediti del piano si rinnovano il ${formatDate(current.renews_at)}. Quelli non usati scadono allo stesso giorno.`
                        : 'I crediti del piano si rinnovano a ogni fattura pagata e scadono a fine periodo.'}
                </p>
            </CardContent>
            <CardFooter className="flex flex-wrap gap-2">
                {otherPlans.length > 0 && (
                    <Button variant="outline" onClick={onSwitch}>
                        Cambia piano
                    </Button>
                )}
                <Button variant="outline" asChild>
                    <Link href={portal()}>Gestisci fatturazione</Link>
                </Button>
            </CardFooter>
        </Card>
    );
}

function PlanSwitchDialog({
    open,
    onOpenChange,
    plans,
}: {
    open: boolean;
    onOpenChange: (open: boolean) => void;
    plans: Package[];
}) {
    const [target, setTarget] = useState<Package | null>(null);
    const [switching, setSwitching] = useState(false);

    useEffect(() => {
        if (!open) {
            setTarget(null);
        }
    }, [open]);

    const confirm = () => {
        if (!target) {
            return;
        }

        setSwitching(true);
        router.patch(
            subscriptionSwap(),
            { package: target.slug },
            {
                onFinish: () => setSwitching(false),
                onSuccess: () => onOpenChange(false),
            },
        );
    };

    return (
        <Dialog open={open} onOpenChange={onOpenChange}>
            <DialogContent>
                <DialogHeader>
                    <DialogTitle>Cambia piano</DialogTitle>
                    <DialogDescription>
                        Il cambio è immediato. Stripe calcola il conguaglio sul
                        periodo già pagato e i nuovi crediti arrivano con la
                        fattura successiva.
                    </DialogDescription>
                </DialogHeader>

                <div className="flex flex-col gap-2">
                    {plans.map((pkg) => {
                        const isTarget = target?.slug === pkg.slug;

                        return (
                            <button
                                key={pkg.id}
                                type="button"
                                aria-pressed={isTarget}
                                onClick={() => setTarget(pkg)}
                                className={cn(
                                    'flex items-baseline justify-between gap-4 rounded-md border p-3 text-left transition-colors',
                                    isTarget
                                        ? 'border-primary ring-primary/30 bg-accent ring-2'
                                        : 'border-border hover:bg-accent/50',
                                )}
                            >
                                <span>
                                    <span className="block text-sm font-medium">
                                        {pkg.name}
                                    </span>
                                    <span className="text-muted-foreground block text-sm">
                                        {planCreditsLine(
                                            pkg.credits,
                                            pkg.interval,
                                        )}
                                    </span>
                                </span>
                                <span className="shrink-0 text-sm tabular-nums">
                                    <span className="font-medium">
                                        {formatEuro(pkg.price_cents)}
                                    </span>
                                    <span className="text-muted-foreground">
                                        {intervalSuffix(pkg.interval)}
                                    </span>
                                </span>
                            </button>
                        );
                    })}
                </div>

                <DialogFooter>
                    <Button
                        variant="outline"
                        onClick={() => onOpenChange(false)}
                    >
                        Annulla
                    </Button>
                    <Button onClick={confirm} disabled={!target || switching}>
                        {target ? `Passa a ${target.name}` : 'Scegli un piano'}
                    </Button>
                </DialogFooter>
            </DialogContent>
        </Dialog>
    );
}

function PlanCard({
    pkg,
    featured,
    highlighted,
    cardRef,
    onActivate,
    activating,
}: {
    pkg: Package;
    featured: boolean;
    highlighted: boolean;
    cardRef?: React.Ref<HTMLDivElement>;
    onActivate: (pkg: Package) => void;
    activating: boolean;
}) {
    // Le descrizioni del catalogo spesso iniziano con la stessa riga di crediti:
    // in quel caso mostrarle entrambe sarebbe una ripetizione.
    const descriptionRepeatsCredits =
        pkg.description?.startsWith(creditsLabel(pkg.credits)) ?? false;

    return (
        <Card
            ref={cardRef}
            className={cn(
                'flex flex-col',
                featured && 'border-primary',
                highlighted && 'border-primary ring-primary/20 ring-2',
            )}
        >
            <CardHeader>
                <div className="flex items-center justify-between gap-2">
                    <CardTitle>{pkg.name}</CardTitle>
                    {highlighted && <Badge>Scelto dalla pagina prezzi</Badge>}
                </div>
            </CardHeader>
            <CardContent className="flex-1 space-y-2">
                <p className="tabular-nums">
                    <span className="text-2xl font-bold">
                        {formatEuro(pkg.price_cents)}
                    </span>
                    <span className="text-muted-foreground ml-1 text-sm">
                        {intervalSuffix(pkg.interval)}
                    </span>
                </p>
                {!descriptionRepeatsCredits && (
                    <p className="text-sm">
                        {planCreditsLine(pkg.credits, pkg.interval)}
                    </p>
                )}
                {pkg.description && (
                    <p className="text-muted-foreground text-sm">
                        {pkg.description}
                    </p>
                )}
            </CardContent>
            <CardFooter>
                <Button
                    className="w-full"
                    variant={featured ? 'default' : 'outline'}
                    onClick={() => onActivate(pkg)}
                    disabled={activating}
                >
                    Attiva {pkg.name}
                </Button>
            </CardFooter>
        </Card>
    );
}

/* -------------------------------------------------------------------------
 * Pagina
 * ---------------------------------------------------------------------- */

export default function BillingIndex({
    packages,
    credits,
    creditsAvailable,
    subscription,
    orders,
    movements,
    highlightPackage,
    plan,
}: Props) {
    const [quantities, setQuantities] = useState<Record<number, number>>({});
    const [purchasing, setPurchasing] = useState<number | null>(null);
    const [activating, setActivating] = useState<number | null>(null);
    const [switchOpen, setSwitchOpen] = useState(false);
    const highlightedCardRef = useRef<HTMLDivElement>(null);

    const balance: CreditsOverview = credits ?? {
        available: creditsAvailable ?? 0,
        expiring_soon: 0,
        expiring_at: null,
        consumed_30d: 0,
    };
    const current = plan?.current ?? null;
    const plans = plan?.plans ?? [];
    const topups = plan?.topups ?? packages ?? [];
    const ledger = movements ?? [];
    const orderList = orders ?? [];
    const otherPlans = plans.filter((pkg) => pkg.slug !== current?.slug);

    const quantityFor = (packageId: number) => quantities[packageId] ?? 1;

    useEffect(() => {
        if (highlightPackage && highlightedCardRef.current) {
            highlightedCardRef.current.scrollIntoView({ block: 'center' });
        }
    }, [highlightPackage]);

    const handleBuy = (pkg: Package) => {
        setPurchasing(pkg.id);
        router.post(
            packageCheckout(pkg.id),
            { quantity: quantityFor(pkg.id) },
            { onFinish: () => setPurchasing(null) },
        );
    };

    const handleActivate = (pkg: Package) => {
        setActivating(pkg.id);
        router.post(
            subscriptionCheckout(),
            { package: pkg.slug },
            { onFinish: () => setActivating(null) },
        );
    };

    return (
        <>
            <Head title="Crediti e piano" />
            <div className="flex flex-1 flex-col gap-10 p-4">
                <section className="space-y-3">
                    <h2 className="text-lg font-semibold">I tuoi crediti</h2>
                    <CreditBalance credits={balance} />
                </section>

                <section className="space-y-3">
                    <h2 className="text-lg font-semibold">Il tuo piano</h2>

                    {current ? (
                        <>
                            <CurrentPlanCard
                                current={current}
                                otherPlans={otherPlans}
                                onSwitch={() => setSwitchOpen(true)}
                            />
                            <PlanSwitchDialog
                                open={switchOpen}
                                onOpenChange={setSwitchOpen}
                                plans={otherPlans}
                            />
                        </>
                    ) : plans.length > 0 ? (
                        <>
                            <p className="text-muted-foreground max-w-[42rem] text-sm">
                                Il piano accredita i suoi crediti a ogni fattura
                                pagata. I crediti valgono per il periodo in
                                corso.
                            </p>
                            <div className="grid gap-4 md:grid-cols-2 lg:grid-cols-3">
                                {plans.map((pkg) => (
                                    <PlanCard
                                        key={pkg.id}
                                        pkg={pkg}
                                        featured={pkg.slug === 'pro'}
                                        highlighted={
                                            highlightPackage === pkg.slug
                                        }
                                        cardRef={
                                            highlightPackage === pkg.slug
                                                ? highlightedCardRef
                                                : undefined
                                        }
                                        onActivate={handleActivate}
                                        activating={activating === pkg.id}
                                    />
                                ))}
                            </div>
                        </>
                    ) : (
                        <Card>
                            <CardContent className="text-muted-foreground text-sm">
                                {subscription
                                    ? `Abbonamento ${subscription.status}: nessun piano corrispondente tra quelli disponibili.`
                                    : 'Nessun piano disponibile al momento.'}
                                {subscription?.on_grace_period &&
                                    subscription.ends_at && (
                                        <>
                                            {' '}
                                            Attivo fino al{' '}
                                            {formatDate(subscription.ends_at)}.
                                        </>
                                    )}
                            </CardContent>
                        </Card>
                    )}
                </section>

                <section className="space-y-3">
                    <h2 className="text-lg font-semibold">Ricariche</h2>
                    <p className="text-muted-foreground max-w-[42rem] text-sm">
                        Crediti extra da acquistare una tantum, quando quelli
                        del piano non bastano.
                    </p>
                    {topups.length === 0 ? (
                        <p className="text-muted-foreground text-sm">
                            Nessuna ricarica disponibile al momento.
                        </p>
                    ) : (
                        <div className="grid gap-4 md:grid-cols-2 lg:grid-cols-3">
                            {topups.map((pkg) => {
                                const isHighlighted =
                                    highlightPackage === pkg.slug;

                                return (
                                    <Card
                                        key={pkg.id}
                                        ref={
                                            isHighlighted
                                                ? highlightedCardRef
                                                : undefined
                                        }
                                        className={cn(
                                            'flex flex-col',
                                            isHighlighted &&
                                                'border-primary ring-primary/20 ring-2',
                                        )}
                                    >
                                        <CardHeader>
                                            <div className="flex items-center justify-between gap-2">
                                                <CardTitle>
                                                    {pkg.name}
                                                </CardTitle>
                                                {isHighlighted && (
                                                    <Badge>
                                                        Scelto dalla pagina
                                                        prezzi
                                                    </Badge>
                                                )}
                                            </div>
                                        </CardHeader>
                                        <CardContent className="flex-1 space-y-2">
                                            <p className="tabular-nums">
                                                <span className="text-2xl font-bold">
                                                    {formatEuro(
                                                        pkg.price_cents,
                                                    )}
                                                </span>
                                                <span className="text-muted-foreground ml-1 text-sm">
                                                    una tantum
                                                </span>
                                            </p>
                                            <p className="text-sm">
                                                {creditsLabel(pkg.credits)}
                                            </p>
                                        </CardContent>
                                        <CardFooter className="flex items-center gap-2">
                                            <Select
                                                value={String(
                                                    quantityFor(pkg.id),
                                                )}
                                                onValueChange={(value) =>
                                                    setQuantities((prev) => ({
                                                        ...prev,
                                                        [pkg.id]: Number(value),
                                                    }))
                                                }
                                            >
                                                <SelectTrigger
                                                    className="w-20"
                                                    size="sm"
                                                    aria-label={`Quantità di ${pkg.name}`}
                                                >
                                                    <SelectValue />
                                                </SelectTrigger>
                                                <SelectContent>
                                                    {quantityOptions.map(
                                                        (n) => (
                                                            <SelectItem
                                                                key={n}
                                                                value={String(
                                                                    n,
                                                                )}
                                                            >
                                                                {n}
                                                            </SelectItem>
                                                        ),
                                                    )}
                                                </SelectContent>
                                            </Select>
                                            <Button
                                                className="flex-1"
                                                variant="outline"
                                                onClick={() => handleBuy(pkg)}
                                                disabled={purchasing === pkg.id}
                                            >
                                                Acquista
                                            </Button>
                                        </CardFooter>
                                    </Card>
                                );
                            })}
                        </div>
                    )}
                </section>

                <Card>
                    <CardHeader>
                        <CardTitle>Movimenti</CardTitle>
                        <CardDescription>
                            Accrediti, consumi e scadenze dei tuoi crediti.
                        </CardDescription>
                    </CardHeader>
                    <CardContent>
                        {ledger.length === 0 ? (
                            <p className="text-muted-foreground text-sm">
                                Nessun movimento registrato.
                            </p>
                        ) : (
                            <Table>
                                <TableHeader>
                                    <TableRow>
                                        <TableHead>Data</TableHead>
                                        <TableHead>Movimento</TableHead>
                                        <TableHead>Dettaglio</TableHead>
                                        <TableHead className="text-right">
                                            Crediti
                                        </TableHead>
                                    </TableRow>
                                </TableHeader>
                                <TableBody>
                                    {ledger.map((movement) => (
                                        <TableRow key={movement.id}>
                                            <TableCell>
                                                {formatDate(
                                                    movement.created_at,
                                                )}
                                            </TableCell>
                                            <TableCell>
                                                {movement.kind_label ??
                                                    movementLabels[
                                                        movement.kind
                                                    ] ??
                                                    movement.kind}
                                            </TableCell>
                                            <TableCell className="text-muted-foreground">
                                                {movement.classroom?.name ??
                                                    movement.note ??
                                                    '—'}
                                            </TableCell>
                                            <TableCell
                                                className={cn(
                                                    'text-right font-medium tabular-nums',
                                                    movement.amount > 0
                                                        ? 'text-primary'
                                                        : 'text-muted-foreground',
                                                )}
                                            >
                                                {movement.amount > 0 ? '+' : ''}
                                                {movement.amount}
                                            </TableCell>
                                        </TableRow>
                                    ))}
                                </TableBody>
                            </Table>
                        )}
                    </CardContent>
                </Card>

                <Card>
                    <CardHeader>
                        <CardTitle>Ordini</CardTitle>
                        <CardDescription>
                            Storico di rinnovi del piano e ricariche.
                        </CardDescription>
                    </CardHeader>
                    <CardContent>
                        {orderList.length === 0 ? (
                            <p className="text-muted-foreground text-sm">
                                Nessun ordine effettuato.
                            </p>
                        ) : (
                            <Table>
                                <TableHeader>
                                    <TableRow>
                                        <TableHead>Data</TableHead>
                                        <TableHead>Pacchetto</TableHead>
                                        <TableHead>Quantità</TableHead>
                                        <TableHead>Importo</TableHead>
                                        <TableHead>Stato</TableHead>
                                    </TableRow>
                                </TableHeader>
                                <TableBody>
                                    {orderList.map((order) => (
                                        <TableRow key={order.id}>
                                            <TableCell>
                                                {formatDate(order.created_at)}
                                            </TableCell>
                                            <TableCell>
                                                <span className="flex flex-wrap items-center gap-2">
                                                    {order.package?.name ?? '—'}
                                                    {order.kind ===
                                                        'subscription' && (
                                                        <Badge variant="outline">
                                                            Abbonamento
                                                        </Badge>
                                                    )}
                                                </span>
                                            </TableCell>
                                            <TableCell className="tabular-nums">
                                                {order.quantity}
                                            </TableCell>
                                            <TableCell className="tabular-nums">
                                                {formatEuro(order.amount_cents)}
                                            </TableCell>
                                            <TableCell>
                                                <Badge
                                                    variant={
                                                        orderStatusVariants[
                                                            order.status
                                                        ]
                                                    }
                                                >
                                                    {
                                                        orderStatusLabels[
                                                            order.status
                                                        ]
                                                    }
                                                </Badge>
                                            </TableCell>
                                        </TableRow>
                                    ))}
                                </TableBody>
                            </Table>
                        )}
                    </CardContent>
                </Card>
            </div>
        </>
    );
}

BillingIndex.layout = {
    breadcrumbs: [
        {
            title: 'Crediti e piano',
            href: billingIndex(),
        },
    ],
};
