import { Head, Link, router } from '@inertiajs/react';
import type { ColumnDef } from '@tanstack/react-table';
import { format } from 'date-fns';
import { ArrowLeft, Paperclip, Pencil, Plus, Trash2 } from 'lucide-react';
import { useState } from 'react';
import { DataTable } from '@/components/data-table';
import { DateTimeField } from '@/components/datetime-field';
import { DeleteConfirmDialog } from '@/components/delete-confirm-dialog';
import { FileUploadField } from '@/components/file-upload-field';
import { FormDialog } from '@/components/form-dialog';
import InputError from '@/components/input-error';
import { PageHeader } from '@/components/page-header';
import { RowActions } from '@/components/row-actions';
import { RupiahInput } from '@/components/rupiah-input';
import { Badge } from '@/components/ui/badge';
import { Button } from '@/components/ui/button';
import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card';
import { Label } from '@/components/ui/label';
import { RadioGroup, RadioGroupItem } from '@/components/ui/radio-group';
import { Textarea } from '@/components/ui/textarea';
import { usePermissions } from '@/hooks/use-permissions';
import { formatRupiah } from '@/lib/currency';
import { index as tuitionInvoiceIndex } from '@/routes/admin/finances/tuition-invoices';
import {
    destroy,
    store,
    update,
} from '@/routes/admin/finances/tuition-invoices/payments';
import { formatAcademicTermLabel } from '@/types/academic-term';
import type { TuitionInvoice } from '@/types/tuition-invoice';
import type { TuitionPayment } from '@/types/tuition-payment';
import {
    PaymentMethodLabels,
    PaymentMethods,
    PaymentStatusLabels,
} from '@/types/tuition-payment';

type Props = {
    invoice: TuitionInvoice;
    payments: TuitionPayment[];
};

export default function TuitionPaymentIndex({ invoice, payments }: Props) {
    const [createOpen, setCreateOpen] = useState(false);
    const [editing, setEditing] = useState<TuitionPayment | null>(null);
    const [deleting, setDeleting] = useState<TuitionPayment | null>(null);
    const { hasPermission } = usePermissions();
    const canCreate = hasPermission('create-tuition-payments');
    const canUpdate = hasPermission('update-tuition-payments');
    const canDelete = hasPermission('delete-tuition-payments');

    function handleDelete() {
        if (!deleting) {
            return;
        }

        router.delete(destroy([invoice.id, deleting.id]), {
            onSuccess: () => setDeleting(null),
        });
    }

    const paidTotal = payments.reduce(
        (sum, payment) => sum + Number(payment.amount_paid),
        0,
    );
    const amountDue = Number(invoice.amount_due);
    const isFullyPaid = paidTotal >= amountDue;

    const columns: ColumnDef<TuitionPayment>[] = [
        {
            accessorKey: 'paid_at',
            header: () => <span>Tanggal Bayar</span>,
            cell: ({ row }) =>
                format(new Date(row.original.paid_at), 'd MMM yyyy, HH:mm'),
        },
        {
            accessorKey: 'amount_paid',
            header: () => <span>Jumlah</span>,
            cell: ({ row }) => formatRupiah(row.getValue('amount_paid')),
        },
        {
            accessorKey: 'payment_method',
            header: () => <span>Metode</span>,
            cell: ({ row }) => {
                const method = row.getValue('payment_method') as
                    keyof typeof PaymentMethodLabels | null;

                return method ? PaymentMethodLabels[method] : '-';
            },
        },
        {
            accessorKey: 'status',
            header: () => <span className="block text-center">Status</span>,
            meta: {
                className: 'w-[120px] text-center',
                headerClassName: 'w-[120px] text-center',
            },
            cell: ({ row }) => {
                const status = row.getValue('status') as
                    keyof typeof PaymentStatusLabels | null;

                return (
                    <div className="flex justify-center">
                        {status ? (
                            <Badge
                                variant={
                                    status === 'paid'
                                        ? 'default'
                                        : status === 'partial'
                                          ? 'secondary'
                                          : 'outline'
                                }
                            >
                                {PaymentStatusLabels[status]}
                            </Badge>
                        ) : (
                            <span className="text-muted-foreground">-</span>
                        )}
                    </div>
                );
            },
        },
        {
            accessorKey: 'recorder.full_name',
            header: () => <span>Dicatat Oleh</span>,
            cell: ({ row }) => row.original.recorder?.full_name ?? '-',
        },
        {
            accessorKey: 'proof_name',
            header: () => <span>Bukti</span>,
            cell: ({ row }) => {
                const payment = row.original;

                if (!payment.proof_url) {
                    return <span className="text-muted-foreground">-</span>;
                }

                return (
                    <a
                        href={payment.proof_url}
                        target="_blank"
                        rel="noreferrer"
                        className="inline-flex items-center gap-1 text-primary underline underline-offset-4 hover:text-primary/80"
                    >
                        <Paperclip className="h-3.5 w-3.5" />
                        {payment.proof_name}
                    </a>
                );
            },
        },
    ];

    if (canUpdate || canDelete) {
        columns.push({
            id: 'actions',
            header: () => <span className="block text-center">Aksi</span>,
            meta: {
                className: 'w-[100px] text-center',
                headerClassName: 'w-[100px] text-center',
            },
            cell: ({ row }) => (
                <RowActions
                    actions={[
                        {
                            label: 'Edit',
                            icon: <Pencil className="h-4 w-4" />,
                            show: canUpdate,
                            onClick: () => setEditing(row.original),
                        },
                        {
                            label: 'Hapus',
                            icon: (
                                <Trash2 className="h-4 w-4 text-destructive" />
                            ),
                            show: canDelete,
                            onClick: () => setDeleting(row.original),
                        },
                    ]}
                />
            ),
        });
    }

    return (
        <>
            <Head title="Pembayaran" />

            <div className="flex h-full flex-1 flex-col gap-6 overflow-x-auto p-4 md:p-6">
                <PageHeader
                    title="Pembayaran"
                    actions={
                        <Button variant="outline" asChild>
                            <Link href={tuitionInvoiceIndex.url()}>
                                <ArrowLeft className="h-4 w-4" />
                                Kembali
                            </Link>
                        </Button>
                    }
                />

                <Card>
                    <CardHeader>
                        <CardTitle>
                            {invoice.student?.user?.profile?.full_name ?? 'N/A'}
                        </CardTitle>
                    </CardHeader>
                    <CardContent className="grid gap-1 text-sm text-muted-foreground">
                        <p>
                            NIM: {invoice.student?.student_number} &middot;{' '}
                            {invoice.student?.department?.name ?? '-'}
                        </p>
                        <p>
                            Periode:{' '}
                            {invoice.academic_term
                                ? formatAcademicTermLabel(invoice.academic_term)
                                : '-'}
                        </p>
                        <p>
                            Jumlah Tagihan: {formatRupiah(invoice.amount_due)}
                        </p>
                        <p>
                            Total Terbayar: {formatRupiah(paidTotal)}{' '}
                            {isFullyPaid ? (
                                <Badge variant="default" className="ml-1">
                                    Lunas
                                </Badge>
                            ) : paidTotal > 0 ? (
                                <Badge variant="secondary" className="ml-1">
                                    Sebagian
                                </Badge>
                            ) : (
                                <Badge variant="outline" className="ml-1">
                                    Belum Bayar
                                </Badge>
                            )}
                        </p>
                    </CardContent>
                </Card>

                <div className="flex items-center justify-between">
                    <h2 className="text-lg font-semibold">
                        Riwayat Pembayaran
                    </h2>
                    {!isFullyPaid && canCreate && (
                        <Button onClick={() => setCreateOpen(true)}>
                            <Plus className="h-4 w-4" />
                            Tambah Pembayaran
                        </Button>
                    )}
                </div>

                <DataTable columns={columns} data={payments} />

                <CreateForm
                    open={createOpen}
                    onOpenChange={setCreateOpen}
                    invoiceId={invoice.id}
                    remaining={amountDue - paidTotal}
                />

                <EditForm
                    key={editing?.id}
                    open={editing !== null}
                    onOpenChange={(open) => {
                        if (!open) {
                            setEditing(null);
                        }
                    }}
                    invoiceId={invoice.id}
                    editing={editing}
                    remaining={
                        editing
                            ? amountDue -
                              (paidTotal - Number(editing.amount_paid))
                            : 0
                    }
                />

                <DeleteConfirmDialog
                    target={deleting}
                    onOpenChange={(open) => {
                        if (!open) {
                            setDeleting(null);
                        }
                    }}
                    title="Hapus Pembayaran"
                    description={() =>
                        'Apakah Anda yakin ingin menghapus data pembayaran ini? Tindakan ini tidak dapat dibatalkan.'
                    }
                    onConfirm={handleDelete}
                />
            </div>
        </>
    );
}

function CreateForm({
    open,
    onOpenChange,
    invoiceId,
    remaining,
}: {
    open: boolean;
    onOpenChange: (open: boolean) => void;
    invoiceId: number;
    remaining: number;
}) {
    return (
        <FormDialog
            open={open}
            onOpenChange={onOpenChange}
            title="Tambah Pembayaran"
            action={store(invoiceId)}
            resetOnSuccess
            onSuccess={() => onOpenChange(false)}
        >
            {({ errors }) => (
                <div className="grid gap-4">
                    <PaymentFields
                        errors={errors}
                        resetKey={open ? 'open' : 'closed'}
                        remaining={remaining}
                    />
                </div>
            )}
        </FormDialog>
    );
}

function EditForm({
    open,
    onOpenChange,
    invoiceId,
    editing,
    remaining,
}: {
    open: boolean;
    onOpenChange: (open: boolean) => void;
    invoiceId: number;
    editing: TuitionPayment | null;
    remaining: number;
}) {
    return (
        <FormDialog
            open={open}
            onOpenChange={onOpenChange}
            title="Edit Pembayaran"
            action={editing ? update([invoiceId, editing.id]) : ''}
            resetOnSuccess
            onSuccess={() => onOpenChange(false)}
        >
            {({ errors }) =>
                editing && (
                    <div className="grid gap-4">
                        <PaymentFields
                            errors={errors}
                            editing={editing}
                            remaining={remaining}
                        />
                    </div>
                )
            }
        </FormDialog>
    );
}

function PaymentFields({
    errors,
    editing,
    resetKey,
    remaining,
}: {
    errors: Record<string, string>;
    editing?: TuitionPayment;
    resetKey?: string;
    remaining: number;
}) {
    return (
        <>
            <div className="grid gap-2">
                <Label htmlFor="amount_paid">
                    Jumlah Dibayar <span className="text-destructive">*</span>
                </Label>
                <RupiahInput
                    id="amount_paid"
                    name="amount_paid"
                    placeholder="1.500.000"
                    defaultValue={editing?.amount_paid}
                    ariaInvalid={!!errors.amount_paid}
                />
                <p className="text-xs text-muted-foreground">
                    Sisa tagihan: {formatRupiah(remaining)}
                </p>
                <InputError message={errors.amount_paid} />
            </div>
            <DateTimeField
                label="Tanggal & Waktu Bayar"
                name="paid_at"
                required
                defaultValue={editing?.paid_at}
                placeholder="Pilih tanggal bayar"
                error={errors.paid_at}
                maxNow
            />
            <div className="grid gap-2">
                <Label>
                    Metode Pembayaran{' '}
                    <span className="text-destructive">*</span>
                </Label>
                <RadioGroup
                    name="payment_method"
                    defaultValue={editing?.payment_method ?? ''}
                    className="flex flex-row gap-4"
                >
                    {PaymentMethods.map((method) => (
                        <div key={method} className="flex items-center gap-2">
                            <RadioGroupItem
                                value={method}
                                id={`payment_method-${method}`}
                            />
                            <Label
                                htmlFor={`payment_method-${method}`}
                                className="font-normal"
                            >
                                {PaymentMethodLabels[method]}
                            </Label>
                        </div>
                    ))}
                </RadioGroup>
                <InputError message={errors.payment_method} />
            </div>
            <div className="grid gap-2">
                <Label htmlFor="notes">Catatan</Label>
                <Textarea
                    id="notes"
                    name="notes"
                    placeholder="Catatan tambahan"
                    defaultValue={editing?.notes ?? ''}
                />
                <InputError message={errors.notes} />
            </div>
            <FileUploadField
                key={resetKey}
                name="proof"
                label="Bukti Pembayaran"
                existingFileName={editing?.proof_name}
                existingFileUrl={editing?.proof_url}
                error={errors.proof}
            />
        </>
    );
}
