import { Head, useForm } from '@inertiajs/react';
import { useState } from 'react';
import type { FormEvent } from 'react';
import PayrollTaxSettingsController from '@/actions/App/Http/Controllers/Admin/PayrollTaxSettingsController';
import Heading from '@/components/heading';
import InputError from '@/components/input-error';
import { Button } from '@/components/ui/button';
import { Checkbox } from '@/components/ui/checkbox';
import { Input } from '@/components/ui/input';
import { Label } from '@/components/ui/label';
import {
    Select,
    SelectContent,
    SelectItem,
    SelectTrigger,
    SelectValue,
} from '@/components/ui/select';
import { dashboard } from '@/routes';
import { index } from '@/routes/admin/payroll-tax-settings';

type Option = { value: string; label: string };
type Account = { id: number; code: string; label: string };

type Bracket = {
    id: number;
    tax_type: string;
    tax_type_label: string;
    effective_date: string;
    lower_bound: number;
    upper_bound: number | null;
    rate: number;
    fixed_deduction: number;
    bracket_order: number;
};

type TaxPart = {
    id: number;
    effective_date: string;
    marital_status: string;
    marital_status_label: string;
    dependent_children_count: number;
    parts: number;
    is_max_bracket: boolean;
};

type CnpsRow = {
    id: number;
    effective_date: string;
    contribution_type: string;
    contribution_type_label: string;
    employee_rate: number;
    employer_rate: number;
    monthly_ceiling: number | null;
};

const TABS = [
    { id: 'igr', label: 'Barème IGR' },
    { id: 'cn', label: 'Barème CN' },
    { id: 'parts', label: 'Parts fiscales' },
    { id: 'cnps', label: 'CNPS' },
    { id: 'settings', label: 'Paramètres' },
] as const;

export default function PayrollTaxSettingsIndex({
    brackets,
    taxParts,
    cnpsSettings,
    payrollSettings,
    accounts,
    taxTypes,
    maritalStatuses,
    cnpsContributionTypes,
    can,
}: {
    brackets: Bracket[];
    taxParts: TaxPart[];
    cnpsSettings: CnpsRow[];
    payrollSettings: {
        legal_monthly_hours: number | null;
        employer_cnps_number: string | null;
        chart_of_account_codes: Record<string, string | null>;
    };
    accounts: Account[];
    taxTypes: Option[];
    maritalStatuses: Option[];
    cnpsContributionTypes: Option[];
    can: { update: boolean };
}) {
    const [tab, setTab] = useState<(typeof TABS)[number]['id']>('igr');
    const emptyIgr = brackets.filter((bracket) => bracket.tax_type === 'igr').length === 0;
    const emptyCn = brackets.filter((bracket) => bracket.tax_type === 'cn').length === 0;
    const emptyParts = taxParts.length === 0;
    const emptyCnps = cnpsSettings.length === 0;

    return (
        <>
            <Head title="Barèmes de paie" />
            <div className="flex h-full flex-1 flex-col gap-6 p-4 md:p-6">
                <Heading
                    title="Barèmes de paie"
                    description="Aucun taux n'est pré-rempli. La paie ne pourra pas être calculée tant qu'aucun barème n'est saisi ici."
                />
                <div className="flex flex-wrap gap-2">
                    {TABS.map((item) => (
                        <Button
                            key={item.id}
                            type="button"
                            variant={tab === item.id ? 'default' : 'outline'}
                            size="sm"
                            onClick={() => setTab(item.id)}
                        >
                            {item.label}
                        </Button>
                    ))}
                </div>

                {tab === 'igr' && (
                    <BracketPanel
                        taxType="igr"
                        rows={brackets.filter((bracket) => bracket.tax_type === 'igr')}
                        empty={emptyIgr}
                        canUpdate={can.update}
                    />
                )}
                {tab === 'cn' && (
                    <BracketPanel
                        taxType="cn"
                        rows={brackets.filter((bracket) => bracket.tax_type === 'cn')}
                        empty={emptyCn}
                        canUpdate={can.update}
                    />
                )}
                {tab === 'parts' && (
                    <PartsPanel rows={taxParts} maritalStatuses={maritalStatuses} empty={emptyParts} canUpdate={can.update} />
                )}
                {tab === 'cnps' && (
                    <CnpsPanel rows={cnpsSettings} types={cnpsContributionTypes} empty={emptyCnps} canUpdate={can.update} />
                )}
                {tab === 'settings' && (
                    <SettingsPanel settings={payrollSettings} accounts={accounts} canUpdate={can.update} />
                )}
            </div>
        </>
    );
}

function EmptyState({ message }: { message: string }) {
    return (
        <p className="rounded-md border border-dashed p-4 text-sm text-muted-foreground">
            {message}
        </p>
    );
}

function BracketPanel({
    taxType,
    rows,
    empty,
    canUpdate,
}: {
    taxType: string;
    rows: Bracket[];
    empty: boolean;
    canUpdate: boolean;
}) {
    const form = useForm({
        tax_type: taxType,
        effective_date: '2026-01-01',
        lower_bound: '0',
        upper_bound: '',
        rate: '0',
        fixed_deduction: '0',
        bracket_order: String(rows.length + 1),
    });

    function submit(event: FormEvent) {
        event.preventDefault();
        form.transform((data) => ({
            ...data,
            lower_bound: Number(data.lower_bound),
            upper_bound: data.upper_bound === '' ? null : Number(data.upper_bound),
            rate: Number(data.rate),
            fixed_deduction: Number(data.fixed_deduction),
            bracket_order: Number(data.bracket_order),
        }));
        form.post(PayrollTaxSettingsController.storeBracket.url(), { preserveScroll: true });
    }

    return (
        <div className="space-y-4">
            {empty && (
                <EmptyState message="La paie ne pourra pas être calculée tant qu'aucun barème n'est saisi ici." />
            )}
            <table className="w-full text-sm">
                <thead>
                    <tr className="text-left text-muted-foreground">
                        <th className="p-2">Effet</th>
                        <th className="p-2">Ordre</th>
                        <th className="p-2">De</th>
                        <th className="p-2">À</th>
                        <th className="p-2">Taux</th>
                        <th></th>
                    </tr>
                </thead>
                <tbody>
                    {rows.map((row) => (
                        <tr key={row.id} className="border-t">
                            <td className="p-2">{row.effective_date}</td>
                            <td className="p-2">{row.bracket_order}</td>
                            <td className="p-2">{row.lower_bound}</td>
                            <td className="p-2">{row.upper_bound ?? '∞'}</td>
                            <td className="p-2">{(row.rate * 100).toFixed(2)} %</td>
                            <td className="p-2">
                                {canUpdate && (
                                    <Button
                                        variant="ghost"
                                        size="sm"
                                        onClick={() =>
                                            form.delete(PayrollTaxSettingsController.destroyBracket.url(row.id), {
                                                preserveScroll: true,
                                            })
                                        }
                                    >
                                        Supprimer
                                    </Button>
                                )}
                            </td>
                        </tr>
                    ))}
                </tbody>
            </table>
            {canUpdate && (
                <form onSubmit={submit} className="grid gap-3 rounded-md border p-4 md:grid-cols-6">
                    <Field label="Date d'effet" error={form.errors.effective_date}>
                        <Input type="date" value={form.data.effective_date} onChange={(e) => form.setData('effective_date', e.target.value)} />
                    </Field>
                    <Field label="Ordre" error={form.errors.bracket_order}>
                        <Input value={form.data.bracket_order} onChange={(e) => form.setData('bracket_order', e.target.value)} />
                    </Field>
                    <Field label="Borne inf." error={form.errors.lower_bound}>
                        <Input value={form.data.lower_bound} onChange={(e) => form.setData('lower_bound', e.target.value)} />
                    </Field>
                    <Field label="Borne sup. (vide = ouverte)" error={form.errors.upper_bound}>
                        <Input value={form.data.upper_bound} onChange={(e) => form.setData('upper_bound', e.target.value)} />
                    </Field>
                    <Field label="Taux (0.10 = 10 %)" error={form.errors.rate}>
                        <Input value={form.data.rate} onChange={(e) => form.setData('rate', e.target.value)} />
                    </Field>
                    <div className="flex items-end">
                        <Button type="submit" disabled={form.processing}>Ajouter</Button>
                    </div>
                </form>
            )}
        </div>
    );
}

function PartsPanel({
    rows,
    maritalStatuses,
    empty,
    canUpdate,
}: {
    rows: TaxPart[];
    maritalStatuses: Option[];
    empty: boolean;
    canUpdate: boolean;
}) {
    const form = useForm({
        effective_date: '2026-01-01',
        marital_status: maritalStatuses[0]?.value ?? 'single',
        dependent_children_count: '0',
        parts: '1',
        is_max_bracket: false,
    });

    function submit(event: FormEvent) {
        event.preventDefault();
        form.transform((data) => ({
            ...data,
            dependent_children_count: Number(data.dependent_children_count),
            parts: Number(data.parts),
        }));
        form.post(PayrollTaxSettingsController.storeTaxPart.url(), { preserveScroll: true });
    }

    return (
        <div className="space-y-4">
            {empty && <EmptyState message="La paie ne pourra pas être calculée tant qu'aucune grille de parts n'est saisie ici." />}
            <table className="w-full text-sm">
                <thead>
                    <tr className="text-left text-muted-foreground">
                        <th className="p-2">Effet</th>
                        <th className="p-2">Situation</th>
                        <th className="p-2">Enfants</th>
                        <th className="p-2">Parts</th>
                        <th className="p-2">Plafond</th>
                        <th></th>
                    </tr>
                </thead>
                <tbody>
                    {rows.map((row) => (
                        <tr key={row.id} className="border-t">
                            <td className="p-2">{row.effective_date}</td>
                            <td className="p-2">{row.marital_status_label}</td>
                            <td className="p-2">{row.dependent_children_count}</td>
                            <td className="p-2">{row.parts}</td>
                            <td className="p-2">{row.is_max_bracket ? 'Oui' : 'Non'}</td>
                            <td className="p-2">
                                {canUpdate && (
                                    <Button
                                        variant="ghost"
                                        size="sm"
                                        onClick={() =>
                                            form.delete(PayrollTaxSettingsController.destroyTaxPart.url(row.id), {
                                                preserveScroll: true,
                                            })
                                        }
                                    >
                                        Supprimer
                                    </Button>
                                )}
                            </td>
                        </tr>
                    ))}
                </tbody>
            </table>
            {canUpdate && (
                <form onSubmit={submit} className="grid gap-3 rounded-md border p-4 md:grid-cols-5">
                    <Field label="Date d'effet">
                        <Input type="date" value={form.data.effective_date} onChange={(e) => form.setData('effective_date', e.target.value)} />
                    </Field>
                    <Field label="Situation">
                        <Select value={form.data.marital_status} onValueChange={(value) => form.setData('marital_status', value)}>
                            <SelectTrigger><SelectValue /></SelectTrigger>
                            <SelectContent>
                                {maritalStatuses.map((status) => (
                                    <SelectItem key={status.value} value={status.value}>{status.label}</SelectItem>
                                ))}
                            </SelectContent>
                        </Select>
                    </Field>
                    <Field label="Enfants">
                        <Input value={form.data.dependent_children_count} onChange={(e) => form.setData('dependent_children_count', e.target.value)} />
                    </Field>
                    <Field label="Parts">
                        <Input value={form.data.parts} onChange={(e) => form.setData('parts', e.target.value)} />
                    </Field>
                    <label className="flex items-end gap-2 text-sm">
                        <Checkbox
                            checked={form.data.is_max_bracket}
                            onCheckedChange={(checked) => form.setData('is_max_bracket', Boolean(checked))}
                        />
                        Plafond (is_max)
                    </label>
                    <Button type="submit" disabled={form.processing}>Ajouter</Button>
                </form>
            )}
        </div>
    );
}

function CnpsPanel({
    rows,
    types,
    empty,
    canUpdate,
}: {
    rows: CnpsRow[];
    types: Option[];
    empty: boolean;
    canUpdate: boolean;
}) {
    const form = useForm({
        effective_date: '2026-01-01',
        contribution_type: types[0]?.value ?? 'retirement_pension',
        employee_rate: '0',
        employer_rate: '0',
        monthly_ceiling: '',
    });

    function submit(event: FormEvent) {
        event.preventDefault();
        form.transform((data) => ({
            ...data,
            employee_rate: Number(data.employee_rate),
            employer_rate: Number(data.employer_rate),
            monthly_ceiling: data.monthly_ceiling === '' ? null : Number(data.monthly_ceiling),
        }));
        form.post(PayrollTaxSettingsController.storeCnpsSetting.url(), { preserveScroll: true });
    }

    return (
        <div className="space-y-4">
            {empty && <EmptyState message="La paie ne pourra pas être calculée tant qu'aucun barème CNPS n'est saisi ici." />}
            <table className="w-full text-sm">
                <thead>
                    <tr className="text-left text-muted-foreground">
                        <th className="p-2">Effet</th>
                        <th className="p-2">Branche</th>
                        <th className="p-2">Salarié</th>
                        <th className="p-2">Employeur</th>
                        <th className="p-2">Plafond</th>
                        <th></th>
                    </tr>
                </thead>
                <tbody>
                    {rows.map((row) => (
                        <tr key={row.id} className="border-t">
                            <td className="p-2">{row.effective_date}</td>
                            <td className="p-2">{row.contribution_type_label}</td>
                            <td className="p-2">{(row.employee_rate * 100).toFixed(2)} %</td>
                            <td className="p-2">{(row.employer_rate * 100).toFixed(2)} %</td>
                            <td className="p-2">{row.monthly_ceiling ?? '—'}</td>
                            <td className="p-2">
                                {canUpdate && (
                                    <Button
                                        variant="ghost"
                                        size="sm"
                                        onClick={() =>
                                            form.delete(PayrollTaxSettingsController.destroyCnpsSetting.url(row.id), {
                                                preserveScroll: true,
                                            })
                                        }
                                    >
                                        Supprimer
                                    </Button>
                                )}
                            </td>
                        </tr>
                    ))}
                </tbody>
            </table>
            {canUpdate && (
                <form onSubmit={submit} className="grid gap-3 rounded-md border p-4 md:grid-cols-5">
                    <Field label="Date d'effet">
                        <Input type="date" value={form.data.effective_date} onChange={(e) => form.setData('effective_date', e.target.value)} />
                    </Field>
                    <Field label="Branche">
                        <Select value={form.data.contribution_type} onValueChange={(value) => form.setData('contribution_type', value)}>
                            <SelectTrigger><SelectValue /></SelectTrigger>
                            <SelectContent>
                                {types.map((type) => (
                                    <SelectItem key={type.value} value={type.value}>{type.label}</SelectItem>
                                ))}
                            </SelectContent>
                        </Select>
                    </Field>
                    <Field label="Taux salarié">
                        <Input value={form.data.employee_rate} onChange={(e) => form.setData('employee_rate', e.target.value)} />
                    </Field>
                    <Field label="Taux employeur">
                        <Input value={form.data.employer_rate} onChange={(e) => form.setData('employer_rate', e.target.value)} />
                    </Field>
                    <Field label="Plafond mensuel">
                        <Input value={form.data.monthly_ceiling} onChange={(e) => form.setData('monthly_ceiling', e.target.value)} />
                    </Field>
                    <Button type="submit" disabled={form.processing}>Ajouter</Button>
                </form>
            )}
        </div>
    );
}

function SettingsPanel({
    settings,
    accounts,
    canUpdate,
}: {
    settings: {
        legal_monthly_hours: number | null;
        employer_cnps_number: string | null;
        chart_of_account_codes: Record<string, string | null>;
    };
    accounts: Account[];
    canUpdate: boolean;
}) {
    const form = useForm({
        legal_monthly_hours: settings.legal_monthly_hours !== null ? String(settings.legal_monthly_hours) : '',
        employer_cnps_number: settings.employer_cnps_number ?? '',
        chart_of_account_codes: {
            personnel_expense: settings.chart_of_account_codes.personnel_expense ?? '',
            employer_contributions_expense: settings.chart_of_account_codes.employer_contributions_expense ?? '',
            cnps_payable: settings.chart_of_account_codes.cnps_payable ?? '',
            igr_payable: settings.chart_of_account_codes.igr_payable ?? '',
            cn_payable: settings.chart_of_account_codes.cn_payable ?? '',
            net_payable: settings.chart_of_account_codes.net_payable ?? '',
        },
    });

    function submit(event: FormEvent) {
        event.preventDefault();
        form.transform((data) => ({
            legal_monthly_hours: data.legal_monthly_hours === '' ? null : Number(data.legal_monthly_hours),
            employer_cnps_number: data.employer_cnps_number || null,
            chart_of_account_codes: Object.fromEntries(
                Object.entries(data.chart_of_account_codes).map(([key, value]) => [key, value || null]),
            ),
        }));
        form.put(PayrollTaxSettingsController.updateSettings.url(), { preserveScroll: true });
    }

    const labels: Record<string, string> = {
        personnel_expense: 'Charges de personnel',
        employer_contributions_expense: 'Charges patronales',
        cnps_payable: 'CNPS à payer',
        igr_payable: 'IGR à payer',
        cn_payable: 'CN à payer',
        net_payable: 'Net à payer',
    };

    return (
        <form onSubmit={submit} className="max-w-xl space-y-4">
            <Field label="Heures légales mensuelles">
                <Input
                    value={form.data.legal_monthly_hours}
                    onChange={(e) => form.setData('legal_monthly_hours', e.target.value)}
                    disabled={!canUpdate}
                />
            </Field>
            <Field label="N° CNPS employeur">
                <Input
                    value={form.data.employer_cnps_number}
                    onChange={(e) => form.setData('employer_cnps_number', e.target.value)}
                    disabled={!canUpdate}
                />
            </Field>
            {Object.entries(labels).map(([key, label]) => (
                <Field key={key} label={label}>
                    <Select
                        value={form.data.chart_of_account_codes[key as keyof typeof form.data.chart_of_account_codes] || '__none'}
                        onValueChange={(value) =>
                            form.setData('chart_of_account_codes', {
                                ...form.data.chart_of_account_codes,
                                [key]: value === '__none' ? '' : value,
                            })
                        }
                        disabled={!canUpdate}
                    >
                        <SelectTrigger><SelectValue placeholder="Non configuré" /></SelectTrigger>
                        <SelectContent>
                            <SelectItem value="__none">Non configuré</SelectItem>
                            {accounts.map((account) => (
                                <SelectItem key={account.code} value={account.code}>
                                    {account.code} — {account.label}
                                </SelectItem>
                            ))}
                        </SelectContent>
                    </Select>
                </Field>
            ))}
            {canUpdate && <Button type="submit" disabled={form.processing}>Enregistrer</Button>}
        </form>
    );
}

function Field({
    label,
    error,
    children,
}: {
    label: string;
    error?: string;
    children: React.ReactNode;
}) {
    return (
        <div className="space-y-1">
            <Label>{label}</Label>
            {children}
            <InputError message={error} />
        </div>
    );
}

PayrollTaxSettingsIndex.layout = {
    breadcrumbs: [
        { title: 'Tableau de bord', href: dashboard() },
        { title: 'Barèmes de paie', href: index() },
    ],
};
