import { useEffect, useRef, useState } from 'react';
import { useForm, useHttp } from '@inertiajs/react';
import { AlertTriangle, ArrowRight, ArrowRightLeft, Building2, Loader2 } from 'lucide-react';
import AppLayout from '@/Layouts/AppLayout';
import { useToast } from '@/Components/Toast';
import { SearchableSelect } from '@/Components/Form/SearchableSelect';
import { TopBar, Crumb, CrumbSep, CrumbCurrent } from '@/Components/Table';
import { Card } from '@/Components/ui/card';
import { Button } from '@/Components/ui/button';
import {
    Dialog,
    DialogClose,
    DialogContent,
    DialogDescription,
    DialogFooter,
    DialogHeader,
    DialogTitle,
} from '@/Components/ui/dialog';
import { cn } from '@/lib/utils';

// Change Company (legacy changecompany.php) — merge one company into another. Every record
// tied to the "Company Lama" (source) is reassigned to the "Company Baru" (target); the source
// is then soft-deleted. Picking a company on either side fetches its related-record counts
// (legacy getrelasitablecompany.php) for a preview before committing; the "Company Info" block
// (legacy getcompanyinfoforupdate.php) is read straight from the preloaded `companies` list
// instead of a second AJAX call, since address + sales name already ride along in that payload.

function FieldError({ message }) {
    return message ? <p className="mt-1 text-xs text-destructive">{message}</p> : null;
}

/** Related-record counts for one selected company, refetched whenever it changes. */
function useRelations(companyId) {
    const [relations, setRelations] = useState(null);
    const [loading, setLoading] = useState(false);
    const http = useHttp({});
    const ref = useRef(companyId);
    ref.current = companyId;

    useEffect(() => {
        http.cancel();
        setRelations(null);
        if (!companyId) {
            setLoading(false);
            return;
        }
        const requested = companyId;
        setLoading(true);
        http.get(route('companies.change.relations', { company: requested }), {
            onSuccess: (resp) => { if (ref.current === requested) setRelations(resp?.tables ?? []); },
            onFinish: () => { if (ref.current === requested) setLoading(false); },
        });
        // eslint-disable-next-line react-hooks/exhaustive-deps
    }, [companyId]);

    return { relations, loading };
}

const sumCounts = (relations) => (relations ? relations.reduce((total, t) => total + t.count, 0) : null);

/** Compact label:value read-out for the picked company (id / address / sales). */
function CompanyInfo({ info }) {
    return (
        <dl className="grid grid-cols-[auto_1fr] gap-x-4 gap-y-1.5 rounded-lg border border-border bg-secondary/40 p-3 text-xs">
            <dt className="text-muted-foreground">ID Company</dt>
            <dd className="m-0 font-medium tabular-nums text-foreground">{info.id}</dd>
            <dt className="text-muted-foreground">Alamat</dt>
            <dd className="m-0 wrap-break-word text-foreground">{info.address || '—'}</dd>
            <dt className="text-muted-foreground">Sales</dt>
            <dd className="m-0 text-foreground">{info.salesName || '—'}</dd>
        </dl>
    );
}

/** Per-table related-record counts, with the running total pinned in the header. */
function RelationTable({ relations, loading, total }) {
    return (
        <div className="overflow-hidden rounded-lg border border-border">
            <div className="flex items-center justify-between gap-2 border-b border-border bg-secondary/40 px-3 py-2">
                <h3 className="m-0 text-[11px] font-semibold uppercase tracking-wide text-muted-foreground">Table Relation</h3>
                {total !== null && (
                    <span className="rounded-full bg-card px-2 py-0.5 text-[11px] font-semibold tabular-nums text-muted-foreground">
                        {total.toLocaleString('id-ID')} baris
                    </span>
                )}
            </div>
            {loading || relations === null ? (
                <p className="m-0 flex items-center gap-2 px-3 py-4 text-xs text-muted-foreground">
                    <Loader2 className="size-3.5 animate-spin" aria-hidden="true" /> Memuat…
                </p>
            ) : (
                <ul className="m-0 max-h-[280px] list-none divide-y divide-border/50 overflow-y-auto p-0">
                    {relations.map((t) => (
                        <li key={t.key} className="flex items-center justify-between gap-3 px-3 py-1.5 text-xs">
                            <span className="min-w-0 truncate text-muted-foreground">{t.label}</span>
                            <span className={cn('shrink-0 font-semibold tabular-nums', t.count > 0 ? 'text-foreground' : 'text-muted-foreground/40')}>
                                {t.count.toLocaleString('id-ID')}
                            </span>
                        </li>
                    ))}
                </ul>
            )}
        </div>
    );
}

/**
 * One side of the merge. `role="source"` is the company being emptied + deleted (Company Lama);
 * `role="target"` receives the records (Company Baru). Colour + role chip carry the direction so
 * the two identical forms never read as interchangeable.
 */
function CompanyPanel({ role, options, selectedId, onChange, error, relations, relationsLoading, sameConflict }) {
    const isSource = role === 'source';
    const info = options.find((o) => o.id === selectedId) ?? null;

    return (
        <Card className="gap-0 overflow-visible p-0">
            <header className="flex items-center justify-between gap-3 border-b border-border px-5 py-4">
                <div className="flex items-center gap-2.5">
                    <span className={cn('grid size-8 shrink-0 place-items-center rounded-lg', isSource ? 'bg-warning-bg text-warning-text' : 'bg-success-bg text-success-text')}>
                        <Building2 className="size-4" aria-hidden="true" />
                    </span>
                    <div>
                        <p className="m-0 text-[10.5px] font-semibold uppercase tracking-wide text-muted-foreground">{isSource ? 'Sumber' : 'Tujuan'}</p>
                        <h2 className="m-0 text-sm font-bold leading-tight text-card-foreground">{isSource ? 'Company Lama' : 'Company Baru'}</h2>
                    </div>
                </div>
                <span className={cn(
                    'inline-flex items-center gap-1.5 whitespace-nowrap rounded-full px-2.5 py-1 text-[11px] font-semibold',
                    isSource ? 'bg-warning-bg text-warning-text' : 'bg-success-bg text-success-text',
                )}>
                    <span aria-hidden="true" className={cn('size-1.5 rounded-full', isSource ? 'bg-warning' : 'bg-success')} />
                    {isSource ? 'Akan dihapus' : 'Menerima data'}
                </span>
            </header>

            <div className="p-5 [&>*+*]:mt-4">
                <div>
                    <SearchableSelect
                        label="Company *"
                        placeholder="Pilih Company"
                        options={options}
                        value={selectedId}
                        onChange={onChange}
                    />
                    <FieldError message={error} />
                    {sameConflict && (
                        <p className="mt-1 flex items-center gap-1.5 text-xs text-warning-text">
                            <AlertTriangle className="size-3.5 shrink-0" aria-hidden="true" />
                            Company Lama dan Company Baru tidak boleh sama.
                        </p>
                    )}
                </div>

                {info && <CompanyInfo info={info} />}

                {selectedId && (
                    <RelationTable relations={relations} loading={relationsLoading} total={sumCounts(relations)} />
                )}
            </div>
        </Card>
    );
}

export default function ChangeCompany({ companies = [] }) {
    const { show: showToast } = useToast();
    const [confirmOpen, setConfirmOpen] = useState(false);

    const options = companies.map((c) => ({
        id: c.ID,
        name: c.CompanyName,
        subtext: [c.CompanyAddress, c.SalesName].filter(Boolean).join(' · '),
        address: c.CompanyAddress,
        salesName: c.SalesName,
    }));

    const form = useForm({ OldCompanyID: null, NewCompanyID: null });
    const oldRelations = useRelations(form.data.OldCompanyID);
    const newRelations = useRelations(form.data.NewCompanyID);

    const nameOf = (id) => options.find((o) => o.id === id)?.name ?? '';
    const oldName = nameOf(form.data.OldCompanyID);
    const newName = nameOf(form.data.NewCompanyID);
    const movingCount = sumCounts(oldRelations.relations);

    const sameCompany = !!form.data.OldCompanyID && form.data.OldCompanyID === form.data.NewCompanyID;
    const canSubmit = !!form.data.OldCompanyID && !!form.data.NewCompanyID && !sameCompany;

    // The form's submit only opens the confirmation dialog; the real POST fires on confirm.
    const requestConfirm = (e) => {
        e.preventDefault();
        if (canSubmit) setConfirmOpen(true);
    };

    const commitMerge = () => {
        form.post(route('companies.change.update'), {
            onError: () => showToast('Please check the form and try again.', 'error'),
            onFinish: () => setConfirmOpen(false),
        });
    };

    return (
        <section className="flex min-w-0 flex-col gap-5">
            <TopBar
                title="Change Company"
                breadcrumb={
                    <>
                        <Crumb href={route('companies.index')}>Companies</Crumb>
                        <CrumbSep />
                        <CrumbCurrent>Change Company</CrumbCurrent>
                    </>
                }
            />

            <div className="flex items-start gap-3 rounded-xl border border-warning-border bg-warning-bg/60 p-4 text-warning-text">
                <AlertTriangle className="mt-0.5 size-4 shrink-0" aria-hidden="true" />
                <div className="text-xs leading-relaxed">
                    <p className="m-0 font-semibold">Menggabungkan dua company</p>
                    <p className="m-0 mt-0.5 text-warning-text/90">
                        Semua data yang tertaut ke <strong>Company Lama</strong> akan dipindahkan ke <strong>Company Baru</strong>,
                        lalu Company Lama dihapus. Periksa data di bawah sebelum melanjutkan.
                    </p>
                </div>
            </div>

            <form onSubmit={requestConfirm} className="flex flex-col gap-5">
                <div className="grid gap-4 lg:grid-cols-[1fr_auto_1fr] lg:items-stretch">
                    <CompanyPanel
                        role="source"
                        options={options}
                        selectedId={form.data.OldCompanyID}
                        onChange={(id) => form.setData('OldCompanyID', id)}
                        error={form.errors.OldCompanyID}
                        relations={oldRelations.relations}
                        relationsLoading={oldRelations.loading}
                    />

                    <div className="flex items-center justify-center py-1 lg:py-0">
                        <span className="grid size-9 shrink-0 place-items-center rounded-full border border-border bg-card text-muted-foreground shadow-sm">
                            <ArrowRight className="size-4 rotate-90 lg:rotate-0" aria-hidden="true" />
                        </span>
                    </div>

                    <CompanyPanel
                        role="target"
                        options={options}
                        selectedId={form.data.NewCompanyID}
                        onChange={(id) => form.setData('NewCompanyID', id)}
                        error={form.errors.NewCompanyID}
                        relations={newRelations.relations}
                        relationsLoading={newRelations.loading}
                        sameConflict={sameCompany}
                    />
                </div>

                <div className="flex flex-col-reverse items-stretch gap-3 border-t border-border pt-4 sm:flex-row sm:items-center sm:justify-between">
                    <p className="m-0 text-xs text-muted-foreground">
                        {canSubmit ? (
                            <>
                                <span className="font-semibold text-foreground">{oldName}</span> akan digabungkan ke{' '}
                                <span className="font-semibold text-foreground">{newName}</span>
                                {movingCount !== null && <> · {movingCount.toLocaleString('id-ID')} data dipindahkan</>}
                            </>
                        ) : (
                            'Pilih Company Lama dan Company Baru untuk melanjutkan.'
                        )}
                    </p>
                    <Button type="submit" disabled={!canSubmit || form.processing} className="gap-1.5 sm:w-auto">
                        {form.processing ? (
                            <><Loader2 className="size-4 animate-spin" aria-hidden="true" /> Menyimpan…</>
                        ) : (
                            <><ArrowRightLeft className="size-4" aria-hidden="true" /> Change Company</>
                        )}
                    </Button>
                </div>
            </form>

            <Dialog open={confirmOpen} onOpenChange={(open) => !form.processing && setConfirmOpen(open)}>
                <DialogContent className="sm:max-w-md">
                    <DialogHeader>
                        <DialogTitle>Ubah Company?</DialogTitle>
                        <DialogDescription asChild>
                            <div className="space-y-3 text-sm">
                                <p className="m-0">
                                    <span className="font-semibold text-foreground">{oldName}</span> akan digabungkan ke{' '}
                                    <span className="font-semibold text-foreground">{newName}</span>.
                                </p>
                                <div className="rounded-lg border border-border bg-secondary/40 p-3 text-xs text-muted-foreground">
                                    {movingCount !== null && (
                                        <p className="m-0">
                                            <span className="font-semibold tabular-nums text-foreground">{movingCount.toLocaleString('id-ID')}</span> data
                                            akan dipindahkan ke <span className="font-medium text-foreground">{newName}</span>.
                                        </p>
                                    )}
                                    <p className="m-0 mt-1">
                                        <span className="font-medium text-warning-text">{oldName}</span> kemudian dihapus dari daftar company aktif.
                                    </p>
                                </div>
                            </div>
                        </DialogDescription>
                    </DialogHeader>
                    <DialogFooter>
                        <Button type="button" onClick={commitMerge} disabled={form.processing} className="gap-1.5">
                            {form.processing ? (
                                <><Loader2 className="size-4 animate-spin" aria-hidden="true" /> Menyimpan…</>
                            ) : (
                                'Ya, Change Company'
                            )}
                        </Button>
                        <DialogClose asChild>
                            <Button type="button" variant="outline" disabled={form.processing}>Batal</Button>
                        </DialogClose>
                    </DialogFooter>
                </DialogContent>
            </Dialog>
        </section>
    );
}

ChangeCompany.layout = [AppLayout];
