import { Head, Link, useForm, usePage } from '@inertiajs/react';
import { Download, Plus, Trash2 } from 'lucide-react';
import { useState } from 'react';
import type { FormEvent } from 'react';
import PayslipController from '@/actions/App/Http/Controllers/Admin/PayslipController';
import InputError from '@/components/input-error';
import Heading from '@/components/heading';
import { Badge } from '@/components/ui/badge';
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 { formatCurrency } from '@/lib/utils';
import { dashboard } from '@/routes';
import { index as payrollIndex } from '@/routes/admin/payroll-runs';
import { show as showPayroll } from '@/routes/admin/payroll-runs';

type Line = {
    id: number;
    type: string;
    type_label: string;
    label: string;
    quantity: number | null;
    rate: number | null;
    base_amount: number | null;
    amount: number;
    is_employer_contribution: boolean;
    is_earning: boolean;
    is_deduction: boolean;
    is_adjustable: boolean;
};

type PayslipShow = {
    id: number;
    code: string;
    status_label: string;
    employee_full_name: string;
    employee_code: string | null;
    job_title: string | null;
    classification: string | null;
    professional_category_label: string | null;
    cnps_number: string | null;
    cmu_number: string | null;
    marital_status_label: string | null;
    dependent_children_count: number | null;
    tax_parts: number | null;
    payment_method_label: string | null;
    mobile_money_provider: string | null;
    payment_account_number: string | null;
    gross_salary: number;
    taxable_income: number;
    igr_amount: number;
    cn_amount: number;
    cnps_employee_amount: number;
    cnps_employer_amount: number;
    net_salary: number;
    lines: Line[];
    payroll_run: {
        code: string;
        status_label: string;
        period_label: string;
    };
    can: { adjust: boolean };
};

type AdjustableType = { value: string; label: string };

type AdjustLine = {
    type: string;
    label: string;
    quantity: string;
    rate: string;
    amount: string;
    is_taxable: boolean;
    is_subject_to_cnps: boolean;
};

export default function PayslipsShow({
    payslip,
    adjustableTypes,
}: {
    payslip: PayslipShow;
    adjustableTypes: AdjustableType[];
}) {
    const errors = (usePage().props as { errors?: Record<string, string> }).errors ?? {};
    const initialAdjustable = payslip.lines
        .filter((line) => line.is_adjustable)
        .map((line) => ({
            type: line.type,
            label: line.label,
            quantity: line.quantity !== null ? String(line.quantity) : '',
            rate: line.rate !== null ? String(line.rate) : '',
            amount: String(line.amount),
            is_taxable: true,
            is_subject_to_cnps: line.type !== 'other_deduction',
        }));

    const form = useForm<{ lines: AdjustLine[] }>({ lines: initialAdjustable });

    function submit(event: FormEvent) {
        event.preventDefault();
        form.transform((data) => ({
            lines: data.lines.map((line) => ({
                type: line.type,
                label: line.label,
                quantity: line.quantity === '' ? null : Number(line.quantity),
                rate: line.rate === '' ? null : Number(line.rate),
                amount: line.amount === '' ? null : Number(line.amount),
                is_taxable: line.is_taxable,
                is_subject_to_cnps: line.is_subject_to_cnps,
            })),
        }));
        form.post(PayslipController.adjust.url(payslip.code), { preserveScroll: true });
    }

    const earnings = payslip.lines.filter((line) => line.is_earning);
    const deductions = payslip.lines.filter((line) => line.is_deduction);
    const employer = payslip.lines.filter((line) => line.is_employer_contribution);

    return (
        <>
            <Head title={`Bulletin ${payslip.code}`} />
            <div className="mx-auto flex w-full max-w-4xl flex-1 flex-col gap-6 p-4 md:p-6">
                <div className="flex flex-col gap-3 sm:flex-row sm:items-start sm:justify-between">
                    <Heading
                        title={payslip.employee_full_name}
                        description={`${payslip.code} · ${payslip.payroll_run.period_label}`}
                    />
                    <Button variant="outline" asChild>
                        <a href={PayslipController.downloadPdf.url(payslip.code)}>
                            <Download className="size-4" />
                            Télécharger le PDF
                        </a>
                    </Button>
                </div>

                <div className="flex flex-wrap gap-2">
                    <Badge>{payslip.status_label}</Badge>
                    <Badge variant="outline">{payslip.payroll_run.status_label}</Badge>
                </div>
                <InputError message={errors.payroll} />

                <div className="grid gap-3 sm:grid-cols-2 text-sm">
                    <p>Matricule : {payslip.employee_code ?? '—'}</p>
                    <p>Poste : {payslip.job_title ?? '—'}</p>
                    <p>CNPS : {payslip.cnps_number ?? '—'}</p>
                    <p>CMU : {payslip.cmu_number ?? '—'}</p>
                    <p>
                        Situation : {payslip.marital_status_label ?? '—'} · {payslip.dependent_children_count ?? 0} enfant(s) · {payslip.tax_parts ?? '—'} part(s)
                    </p>
                    <p>
                        Paiement : {payslip.payment_method_label ?? '—'}
                        {payslip.mobile_money_provider ? ` · ${payslip.mobile_money_provider}` : ''}
                        {payslip.payment_account_number ? ` · ${payslip.payment_account_number}` : ''}
                    </p>
                </div>

                <LineTable title="Gains" lines={earnings} />
                <LineTable title="Retenues" lines={deductions} />
                <p className="text-lg font-semibold">Net à payer : {formatCurrency(payslip.net_salary)}</p>
                <LineTable title="Cotisations patronales (hors net)" lines={employer} />

                {payslip.can.adjust && (
                    <form onSubmit={submit} className="space-y-4 rounded-lg border p-4">
                        <div className="flex items-center justify-between">
                            <h2 className="font-medium">Ajuster le bulletin</h2>
                            <Button
                                type="button"
                                variant="outline"
                                size="sm"
                                onClick={() =>
                                    form.setData('lines', [
                                        ...form.data.lines,
                                        {
                                            type: adjustableTypes[0]?.value ?? 'bonus',
                                            label: '',
                                            quantity: '',
                                            rate: '',
                                            amount: '',
                                            is_taxable: true,
                                            is_subject_to_cnps: true,
                                        },
                                    ])
                                }
                            >
                                <Plus className="size-4" />
                                Ligne
                            </Button>
                        </div>
                        <p className="text-sm text-muted-foreground">
                            Primes, heures supplémentaires et autres retenues uniquement. L'IGR, la CN et la CNPS sont recalculées automatiquement.
                        </p>
                        {form.data.lines.map((line, index) => (
                            <div key={index} className="grid gap-3 rounded-md border p-3 md:grid-cols-6">
                                <div className="md:col-span-2 space-y-1">
                                    <Label>Type</Label>
                                    <Select
                                        value={line.type}
                                        onValueChange={(value) => {
                                            const next = [...form.data.lines];
                                            next[index] = { ...next[index], type: value };
                                            form.setData('lines', next);
                                        }}
                                    >
                                        <SelectTrigger>
                                            <SelectValue />
                                        </SelectTrigger>
                                        <SelectContent>
                                            {adjustableTypes.map((type) => (
                                                <SelectItem key={type.value} value={type.value}>
                                                    {type.label}
                                                </SelectItem>
                                            ))}
                                        </SelectContent>
                                    </Select>
                                </div>
                                <div className="md:col-span-2 space-y-1">
                                    <Label>Libellé</Label>
                                    <Input
                                        value={line.label}
                                        onChange={(event) => {
                                            const next = [...form.data.lines];
                                            next[index] = { ...next[index], label: event.target.value };
                                            form.setData('lines', next);
                                        }}
                                    />
                                </div>
                                {line.type === 'overtime' ? (
                                    <>
                                        <div className="space-y-1">
                                            <Label>Heures</Label>
                                            <Input
                                                value={line.quantity}
                                                onChange={(event) => {
                                                    const next = [...form.data.lines];
                                                    next[index] = { ...next[index], quantity: event.target.value };
                                                    form.setData('lines', next);
                                                }}
                                            />
                                        </div>
                                        <div className="space-y-1">
                                            <Label>Majoration</Label>
                                            <Input
                                                value={line.rate}
                                                placeholder="1.5"
                                                onChange={(event) => {
                                                    const next = [...form.data.lines];
                                                    next[index] = { ...next[index], rate: event.target.value };
                                                    form.setData('lines', next);
                                                }}
                                            />
                                        </div>
                                    </>
                                ) : (
                                    <div className="space-y-1">
                                        <Label>Montant</Label>
                                        <Input
                                            value={line.amount}
                                            onChange={(event) => {
                                                const next = [...form.data.lines];
                                                next[index] = { ...next[index], amount: event.target.value };
                                                form.setData('lines', next);
                                            }}
                                        />
                                    </div>
                                )}
                                <div className="flex items-end">
                                    <Button
                                        type="button"
                                        variant="ghost"
                                        size="icon"
                                        onClick={() =>
                                            form.setData(
                                                'lines',
                                                form.data.lines.filter((_, lineIndex) => lineIndex !== index),
                                            )
                                        }
                                    >
                                        <Trash2 className="size-4" />
                                    </Button>
                                </div>
                                {line.type !== 'other_deduction' && (
                                    <div className="md:col-span-6 flex gap-4 text-sm">
                                        <label className="flex items-center gap-2">
                                            <Checkbox
                                                checked={line.is_taxable}
                                                onCheckedChange={(checked) => {
                                                    const next = [...form.data.lines];
                                                    next[index] = { ...next[index], is_taxable: Boolean(checked) };
                                                    form.setData('lines', next);
                                                }}
                                            />
                                            Soumis à IGR/CN
                                        </label>
                                        <label className="flex items-center gap-2">
                                            <Checkbox
                                                checked={line.is_subject_to_cnps}
                                                onCheckedChange={(checked) => {
                                                    const next = [...form.data.lines];
                                                    next[index] = { ...next[index], is_subject_to_cnps: Boolean(checked) };
                                                    form.setData('lines', next);
                                                }}
                                            />
                                            Assiette CNPS
                                        </label>
                                    </div>
                                )}
                            </div>
                        ))}
                        <Button type="submit" disabled={form.processing}>
                            Recalculer
                        </Button>
                    </form>
                )}

                <Button variant="ghost" asChild>
                    <Link href={showPayroll.url(payslip.payroll_run.code)}>Retour au cycle</Link>
                </Button>
            </div>
        </>
    );
}

function LineTable({ title, lines }: { title: string; lines: Line[] }) {
    return (
        <section className="space-y-2">
            <h2 className="text-sm font-semibold uppercase tracking-wide text-muted-foreground">{title}</h2>
            <div className="overflow-x-auto rounded-md border">
                <table className="w-full text-sm">
                    <thead className="bg-muted/40 text-left">
                        <tr>
                            <th className="p-2">Libellé</th>
                            <th className="p-2 text-right">Base / qté</th>
                            <th className="p-2 text-right">Taux</th>
                            <th className="p-2 text-right">Montant</th>
                        </tr>
                    </thead>
                    <tbody>
                        {lines.length === 0 ? (
                            <tr>
                                <td className="p-3 text-muted-foreground" colSpan={4}>
                                    Aucune ligne
                                </td>
                            </tr>
                        ) : (
                            lines.map((line) => (
                                <tr key={line.id} className="border-t">
                                    <td className="p-2">{line.label}</td>
                                    <td className="p-2 text-right">
                                        {line.quantity ?? (line.base_amount !== null ? formatCurrency(line.base_amount) : '—')}
                                    </td>
                                    <td className="p-2 text-right">
                                        {line.rate !== null ? `${(line.rate * 100).toFixed(2)} %` : '—'}
                                    </td>
                                    <td className="p-2 text-right">{formatCurrency(line.amount)}</td>
                                </tr>
                            ))
                        )}
                    </tbody>
                </table>
            </div>
        </section>
    );
}

PayslipsShow.layout = {
    breadcrumbs: [
        { title: 'Tableau de bord', href: dashboard() },
        { title: 'Paie', href: payrollIndex() },
    ],
};
