import { Head, Link, useForm } from '@inertiajs/react';
import { AlertCircle, ArrowLeft, Plus, Save, Trash2 } from 'lucide-react';
import { type FormEvent, useMemo } from 'react';

import { Alert, AlertDescription, AlertTitle } from '@/components/ui/alert';
import { Button } from '@/components/ui/button';
import {
    Card,
    CardContent,
    CardDescription,
    CardHeader,
    CardTitle,
} from '@/components/ui/card';
import { Input } from '@/components/ui/input';
import { Label } from '@/components/ui/label';
import { SearchableSelect } from '@/components/ui/searchable-select';
import { Textarea } from '@/components/ui/textarea';
import AppLayout from '@/layouts/app-layout';
import { formatIDR } from '@/lib/formatters';
import accountingRoutes from '@/routes/accounting';
import type { BreadcrumbItem } from '@/types';
import type { Account } from '@/types/accounting';

interface PageProps {
    accounts: Account[];
}

interface JournalLineForm {
    account_id: string | number;
    debit: string | number;
    credit: string | number;
    description: string;
}

const breadcrumbs: BreadcrumbItem[] = [
    {
        title: 'Akuntansi',
        href: accountingRoutes.journal().url,
    },
    {
        title: 'Jurnal Umum',
        href: accountingRoutes.journal().url,
    },
    {
        title: 'Buat Jurnal',
        href: accountingRoutes.journal.create().url,
    },
];

export default function CreateJournal({ accounts }: PageProps) {
    const { data, setData, post, processing, errors } = useForm({
        description: '',
        transaction_date: new Date().toISOString().split('T')[0],
        lines: [
            { account_id: '', debit: 0, credit: 0, description: '' },
            { account_id: '', debit: 0, credit: 0, description: '' },
        ] as JournalLineForm[],
    });

    const accountOptions = useMemo(
        () =>
            accounts.map((acc) => ({
                value: acc.id.toString(),
                label: `${acc.code} - ${acc.name}`,
            })),
        [accounts],
    );

    const totals = useMemo(() => {
        const debit = data.lines.reduce(
            (sum, line) => sum + Number(line.debit || 0),
            0,
        );
        const credit = data.lines.reduce(
            (sum, line) => sum + Number(line.credit || 0),
            0,
        );
        return { debit, credit, difference: Math.abs(debit - credit) };
    }, [data.lines]);

    const addLine = () => {
        setData('lines', [
            ...data.lines,
            { account_id: '', debit: 0, credit: 0, description: '' },
        ]);
    };

    const removeLine = (index: number) => {
        if (data.lines.length <= 2) return;
        const newLines = [...data.lines];
        newLines.splice(index, 1);
        setData('lines', newLines);
    };

    const updateLine = (
        index: number,
        field: keyof JournalLineForm,
        value: string | number,
    ) => {
        const newLines = [...data.lines];

        // Logical constraint: if debit is set, credit must be 0 and vice versa
        if (field === 'debit' && Number(value) > 0) {
            newLines[index] = { ...newLines[index], debit: value, credit: 0 };
        } else if (field === 'credit' && Number(value) > 0) {
            newLines[index] = { ...newLines[index], credit: value, debit: 0 };
        } else {
            newLines[index] = { ...newLines[index], [field]: value };
        }

        setData('lines', newLines);
    };

    const handleSubmit = (e: FormEvent) => {
        e.preventDefault();
        post(accountingRoutes.journal.store().url);
    };

    const isBalanced = totals.difference < 0.01 && totals.debit > 0;

    return (
        <AppLayout breadcrumbs={breadcrumbs}>
            <Head title="Buat Entri Jurnal Jurnal Umum" />

            <div className="mx-auto flex h-full w-full max-w-5xl flex-col gap-4 p-4">
                <div className="flex items-center gap-4">
                    <Button variant="outline" size="icon" asChild>
                        <Link href={accountingRoutes.journal().url}>
                            <ArrowLeft className="h-4 w-4" />
                        </Link>
                    </Button>
                    <div className="flex flex-col gap-1">
                        <h1 className="text-2xl font-black">
                            Buat Entri Jurnal
                        </h1>
                        <p className="text-sm text-muted-foreground">
                            Catat transaksi manual ke dalam buku besar.
                        </p>
                    </div>
                </div>

                {!isBalanced && totals.debit > 0 && (
                    <Alert variant="destructive">
                        <AlertCircle className="h-4 w-4" />
                        <AlertTitle>Jurnal Tidak Seimbang</AlertTitle>
                        <AlertDescription>
                            Total Debit ({formatIDR(totals.debit)}) tidak sama
                            dengan Total Kredit ({formatIDR(totals.credit)}).
                            Selisih: {formatIDR(totals.difference)}
                        </AlertDescription>
                    </Alert>
                )}

                <form onSubmit={handleSubmit} className="grid gap-6">
                    <Card>
                        <CardHeader>
                            <CardTitle>Informasi Jurnal</CardTitle>
                            <CardDescription>
                                Detail header untuk entri jurnal ini.
                            </CardDescription>
                        </CardHeader>
                        <CardContent className="grid gap-6 md:grid-cols-2">
                            <div className="space-y-2">
                                <Label htmlFor="transaction_date">
                                    Tanggal Transaksi{' '}
                                    <span className="text-red-500">*</span>
                                </Label>
                                <Input
                                    id="transaction_date"
                                    type="date"
                                    value={data.transaction_date}
                                    onChange={(e) =>
                                        setData(
                                            'transaction_date',
                                            e.target.value,
                                        )
                                    }
                                    className={
                                        errors.transaction_date
                                            ? 'border-red-500'
                                            : ''
                                    }
                                />
                                {errors.transaction_date && (
                                    <p className="text-xs text-red-500">
                                        {errors.transaction_date}
                                    </p>
                                )}
                            </div>
                            <div className="space-y-2">
                                <Label htmlFor="description">
                                    Keterangan Utama{' '}
                                    <span className="text-red-500">*</span>
                                </Label>
                                <Textarea
                                    id="description"
                                    placeholder="Contoh: Setoran modal awal atau Penyesuaian akhir bulan"
                                    value={data.description}
                                    onChange={(e) =>
                                        setData('description', e.target.value)
                                    }
                                    className={
                                        errors.description
                                            ? 'border-red-500'
                                            : ''
                                    }
                                />
                                {errors.description && (
                                    <p className="text-xs text-red-500">
                                        {errors.description}
                                    </p>
                                )}
                            </div>
                        </CardContent>
                    </Card>

                    <Card>
                        <CardHeader className="flex flex-row items-center justify-between space-y-0">
                            <div>
                                <CardTitle>Rincian Baris Jurnal</CardTitle>
                                <CardDescription>
                                    Tambahkan baris debit dan kredit.
                                </CardDescription>
                            </div>
                            <Button
                                type="button"
                                variant="outline"
                                size="sm"
                                onClick={addLine}
                            >
                                <Plus className="mr-2 h-4 w-4" />
                                Tambah Baris
                            </Button>
                        </CardHeader>
                        <CardContent className="space-y-4">
                            <div className="hidden grid-cols-12 gap-4 border-b px-2 pb-2 text-sm font-bold md:grid">
                                <div className="col-span-4">Akun</div>
                                <div className="col-span-2 text-right">
                                    Debit
                                </div>
                                <div className="col-span-2 text-right">
                                    Kredit
                                </div>
                                <div className="col-span-3">Keterangan</div>
                                <div className="col-span-1"></div>
                            </div>

                            {data.lines.map((line, index) => (
                                <div
                                    key={index}
                                    className="relative grid grid-cols-1 gap-4 rounded-lg border p-2 md:grid-cols-12 md:border-none"
                                >
                                    <div className="col-span-1 space-y-1 md:col-span-4">
                                        <Label className="md:hidden">
                                            Akun
                                        </Label>
                                        <SearchableSelect
                                            options={accountOptions}
                                            value={line.account_id.toString()}
                                            onValueChange={(v) =>
                                                updateLine(
                                                    index,
                                                    'account_id',
                                                    v,
                                                )
                                            }
                                            placeholder="Pilih Akun"
                                            className={
                                                errors[
                                                    `lines.${index}.account_id` as keyof typeof errors
                                                ]
                                                    ? 'border-red-500'
                                                    : ''
                                            }
                                        />
                                        {errors[
                                            `lines.${index}.account_id` as keyof typeof errors
                                        ] && (
                                            <p className="text-xs text-red-500">
                                                {
                                                    errors[
                                                        `lines.${index}.account_id` as keyof typeof errors
                                                    ]
                                                }
                                            </p>
                                        )}
                                    </div>
                                    <div className="col-span-1 space-y-1 md:col-span-2">
                                        <Label className="md:hidden">
                                            Debit
                                        </Label>
                                        <Input
                                            type="number"
                                            className="text-right"
                                            value={line.debit}
                                            onChange={(e) =>
                                                updateLine(
                                                    index,
                                                    'debit',
                                                    e.target.value,
                                                )
                                            }
                                            min="0"
                                        />
                                    </div>
                                    <div className="col-span-1 space-y-1 md:col-span-2">
                                        <Label className="md:hidden">
                                            Kredit
                                        </Label>
                                        <Input
                                            type="number"
                                            className="text-right"
                                            value={line.credit}
                                            onChange={(e) =>
                                                updateLine(
                                                    index,
                                                    'credit',
                                                    e.target.value,
                                                )
                                            }
                                            min="0"
                                        />
                                    </div>
                                    <div className="col-span-1 space-y-1 md:col-span-3">
                                        <Label className="md:hidden">
                                            Keterangan Baris
                                        </Label>
                                        <Input
                                            placeholder="Opsional"
                                            value={line.description}
                                            onChange={(e) =>
                                                updateLine(
                                                    index,
                                                    'description',
                                                    e.target.value,
                                                )
                                            }
                                        />
                                    </div>
                                    <div className="col-span-1 flex items-end justify-end md:col-span-1">
                                        <Button
                                            type="button"
                                            variant="ghost"
                                            size="icon"
                                            className="h-10 w-10 text-destructive"
                                            onClick={() => removeLine(index)}
                                            disabled={data.lines.length <= 2}
                                        >
                                            <Trash2 className="h-4 w-4" />
                                        </Button>
                                    </div>
                                    {errors[
                                        `lines.${index}` as keyof typeof errors
                                    ] && (
                                        <div className="col-span-full mt-1 text-xs text-red-500">
                                            {
                                                errors[
                                                    `lines.${index}` as keyof typeof errors
                                                ]
                                            }
                                        </div>
                                    )}
                                </div>
                            ))}

                            <div className="grid grid-cols-1 gap-4 border-t pt-4 font-bold md:grid-cols-12">
                                <div className="col-span-4 hidden self-center pr-4 text-right md:block">
                                    TOTAL
                                </div>
                                <div className="col-span-1 rounded bg-muted p-2 text-right md:col-span-2">
                                    <Label className="mb-1 block text-xs md:hidden">
                                        Total Debit
                                    </Label>
                                    {formatIDR(totals.debit)}
                                </div>
                                <div className="col-span-1 rounded bg-muted p-2 text-right md:col-span-2">
                                    <Label className="mb-1 block text-xs md:hidden">
                                        Total Kredit
                                    </Label>
                                    {formatIDR(totals.credit)}
                                </div>
                                <div className="col-span-1 flex flex-col items-end gap-1 md:col-span-3 md:col-start-9">
                                    <div
                                        className={cn(
                                            'rounded px-2 py-1 text-sm font-medium',
                                            isBalanced
                                                ? 'bg-green-100 text-green-700'
                                                : 'bg-red-100 text-red-700',
                                        )}
                                    >
                                        {isBalanced
                                            ? 'Balanced'
                                            : `Diff: ${formatIDR(totals.difference)}`}
                                    </div>
                                </div>
                            </div>
                        </CardContent>
                    </Card>

                    <div className="flex justify-end gap-2 pb-10">
                        <Button
                            type="button"
                            variant="outline"
                            asChild
                            disabled={processing}
                        >
                            <Link href={accountingRoutes.journal().url}>
                                Batal
                            </Link>
                        </Button>
                        <Button
                            type="submit"
                            disabled={processing || !isBalanced}
                        >
                            <Save className="mr-2 h-4 w-4" />
                            Simpan Jurnal
                        </Button>
                    </div>
                </form>
            </div>
        </AppLayout>
    );
}

// Helper for conditional class names
function cn(...classes: (string | boolean | undefined)[]) {
    return classes.filter(Boolean).join(' ');
}
