import { useForm } from '@inertiajs/react';
import { Plus, Trash2 } from 'lucide-react';
import type { FormEvent } from 'react';
import BudgetController from '@/actions/App/Http/Controllers/Admin/BudgetController';
import InputError from '@/components/input-error';
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 {
    Select,
    SelectContent,
    SelectItem,
    SelectTrigger,
    SelectValue,
} from '@/components/ui/select';
import { Textarea } from '@/components/ui/textarea';
import { formatCurrency } from '@/lib/utils';

export type AccountOption = { id: number; code: string; label: string };
export type DepartmentOption = { id: number; code: string; name: string };

export type BudgetLineData = {
    chart_of_account_id: number;
    planned_amount: string | number;
    notes?: string | null;
};

export type BudgetFormData = {
    id: number;
    fiscal_year: number;
    department_id: number;
    label: string;
    notes: string | null;
    lines: BudgetLineData[];
};

type LineForm = {
    uid: string;
    chart_of_account_id: string;
    planned_amount: string;
    notes: string;
};

type Props = {
    accounts: AccountOption[];
    departments: DepartmentOption[];
    budget?: BudgetFormData | null;
    defaultFiscalYear?: number;
    onCancel: () => void;
};

let uidCounter = 0;
function nextUid(): string {
    uidCounter += 1;
    return `budget-line-${uidCounter}`;
}

function emptyLine(): LineForm {
    return {
        uid: nextUid(),
        chart_of_account_id: '',
        planned_amount: '0',
        notes: '',
    };
}

export function BudgetForm({
    accounts,
    departments,
    budget = null,
    defaultFiscalYear,
    onCancel,
}: Props) {
    const isEditing = budget !== null;

    const form = useForm({
        fiscal_year: budget?.fiscal_year ?? defaultFiscalYear ?? new Date().getFullYear(),
        department_id: budget?.department_id ? String(budget.department_id) : '',
        label: budget?.label ?? '',
        notes: budget?.notes ?? '',
        lines:
            budget && budget.lines.length > 0
                ? budget.lines.map(
                      (line): LineForm => ({
                          uid: nextUid(),
                          chart_of_account_id: String(line.chart_of_account_id),
                          planned_amount: String(line.planned_amount),
                          notes: line.notes ?? '',
                      }),
                  )
                : [emptyLine()],
    });

    const lines = form.data.lines as LineForm[];

    function setLines(next: LineForm[]) {
        form.setData('lines', next);
    }

    function updateLine(index: number, patch: Partial<LineForm>) {
        setLines(lines.map((line, i) => (i === index ? { ...line, ...patch } : line)));
    }

    function addLine() {
        setLines([...lines, emptyLine()]);
    }

    function removeLine(index: number) {
        if (lines.length <= 1) return;
        setLines(lines.filter((_, i) => i !== index));
    }

    const totalPlanned = lines.reduce(
        (sum, line) => sum + (Number(line.planned_amount) || 0),
        0,
    );

    function submit(event: FormEvent) {
        event.preventDefault();

        const payload = {
            fiscal_year: Number(form.data.fiscal_year),
            department_id: Number(form.data.department_id),
            label: form.data.label,
            notes: form.data.notes || null,
            lines: lines.map((line) => ({
                chart_of_account_id: Number(line.chart_of_account_id),
                planned_amount: line.planned_amount || 0,
                notes: line.notes || null,
            })),
        };

        form.transform(() => payload);

        if (isEditing && budget) {
            form.put(BudgetController.update.url(budget.id));
            return;
        }

        form.post(BudgetController.store.url());
    }

    return (
        <form onSubmit={submit} className="space-y-6">
            <Card>
                <CardHeader>
                    <CardTitle>Informations générales</CardTitle>
                </CardHeader>
                <CardContent className="grid gap-4 sm:grid-cols-2">
                    <div className="grid gap-2">
                        <Label>Exercice</Label>
                        <Input
                            type="number"
                            min={2000}
                            max={2100}
                            value={form.data.fiscal_year}
                            onChange={(e) =>
                                form.setData('fiscal_year', Number(e.target.value))
                            }
                            required
                        />
                        <InputError message={form.errors.fiscal_year} />
                    </div>
                    <div className="grid gap-2">
                        <Label>Service</Label>
                        <Select
                            value={form.data.department_id || undefined}
                            onValueChange={(value) =>
                                form.setData('department_id', value)
                            }
                        >
                            <SelectTrigger>
                                <SelectValue placeholder="Choisir un service…" />
                            </SelectTrigger>
                            <SelectContent>
                                {departments.map((d) => (
                                    <SelectItem key={d.id} value={String(d.id)}>
                                        {d.name}
                                    </SelectItem>
                                ))}
                            </SelectContent>
                        </Select>
                        <InputError message={form.errors.department_id} />
                    </div>
                    <div className="grid gap-2 sm:col-span-2">
                        <Label>Libellé</Label>
                        <Input
                            value={form.data.label}
                            onChange={(e) => form.setData('label', e.target.value)}
                            required
                        />
                        <InputError message={form.errors.label} />
                    </div>
                    <div className="grid gap-2 sm:col-span-2">
                        <Label>Notes</Label>
                        <Textarea
                            value={form.data.notes}
                            onChange={(e) => form.setData('notes', e.target.value)}
                            rows={2}
                        />
                    </div>
                </CardContent>
            </Card>

            <Card>
                <CardHeader className="flex-row items-center justify-between space-y-0">
                    <div>
                        <CardTitle>Lignes budgétaires</CardTitle>
                        <CardDescription>
                            Montants prévisionnels par compte de charges.
                        </CardDescription>
                    </div>
                    <Button type="button" variant="outline" size="sm" onClick={addLine}>
                        <Plus />
                        Ajouter
                    </Button>
                </CardHeader>
                <CardContent className="space-y-4">
                    {lines.map((line, index) => (
                        <div
                            key={line.uid}
                            className="grid gap-4 rounded-xl border p-4 sm:grid-cols-4"
                        >
                            <div className="grid gap-2 sm:col-span-2">
                                <Label className="text-xs">Compte</Label>
                                <Select
                                    value={line.chart_of_account_id || undefined}
                                    onValueChange={(value) =>
                                        updateLine(index, { chart_of_account_id: value })
                                    }
                                >
                                    <SelectTrigger>
                                        <SelectValue placeholder="Compte…" />
                                    </SelectTrigger>
                                    <SelectContent>
                                        {accounts.map((account) => (
                                            <SelectItem
                                                key={account.id}
                                                value={String(account.id)}
                                            >
                                                {account.code} — {account.label}
                                            </SelectItem>
                                        ))}
                                    </SelectContent>
                                </Select>
                            </div>
                            <div className="grid gap-2">
                                <Label className="text-xs">Montant prévu</Label>
                                <Input
                                    type="number"
                                    step="0.01"
                                    min="0"
                                    value={line.planned_amount}
                                    onChange={(e) =>
                                        updateLine(index, {
                                            planned_amount: e.target.value,
                                        })
                                    }
                                />
                            </div>
                            <div className="flex items-end justify-end">
                                <Button
                                    type="button"
                                    variant="ghost"
                                    size="icon"
                                    onClick={() => removeLine(index)}
                                    disabled={lines.length <= 1}
                                >
                                    <Trash2 />
                                </Button>
                            </div>
                        </div>
                    ))}
                    <InputError message={form.errors.lines} />
                    <p className="text-right text-sm font-medium">
                        Total prévu : {formatCurrency(totalPlanned)}
                    </p>
                </CardContent>
            </Card>

            <div className="flex justify-end gap-2">
                <Button type="button" variant="outline" onClick={onCancel}>
                    Annuler
                </Button>
                <Button type="submit" disabled={form.processing}>
                    {isEditing ? 'Enregistrer' : 'Créer le budget'}
                </Button>
            </div>
        </form>
    );
}
