import { useEffect, useRef, useState } from 'react';
import { Link } from '@inertiajs/react';
import { ArrowLeft, Loader2, Printer, TriangleAlert } from 'lucide-react';
import AppLayout from '@/Layouts/AppLayout';
import { Button } from '@/Components/ui/button';
import { StatusBadge } from '@/Components/Proto/UI/StatusBadge';
import { statusTone } from '@/lib/sampleOrderStatusTones';
import { useToast } from '@/Components/Toast';

// Packing labels sheet (legacy printlabelpacking.php, opened by the btn-printlabel popup in
// samplerequestpacking.php with &PDFOutput=I + AutoPrint(true) — i.e. shown INLINE *and*
// auto-printed). This page reproduces both halves: the PDF is built in the browser, embedded
// here, and the print dialog fires once on its own.
//
// The route is deliberately UNLINKED from the sidebar/menu — it is reached by typing the URL
// (or from the Packing detail button, which prints the *uncommitted* dropdown state client-side
// and therefore never navigates here). Do not add a nav entry for it.

// Same "doc-section" shell as Packing/Detail.jsx.
const SECTION_CARD = 'overflow-hidden rounded-xl border border-border bg-card shadow-sm';
const SECTION_HEAD = 'border-b border-border/60 px-5 py-3';
const SECTION_TITLE = 'm-0 text-[11px] font-bold uppercase tracking-[0.05em] text-card-foreground';
const SECTION_SUB = 'mt-0.5 block text-[11px] font-medium text-muted-foreground';

// The viewer should own the content area without pushing the page into a second scrollbar.
const VIEWER_BOX = 'h-[calc(100vh-260px)] min-h-[420px] w-full';

export default function SampleOrderPackingLabels({ sampleOrder = {}, labels = [], labelImage = null }) {
    const { show: showToast } = useToast();
    const q = sampleOrder;

    const [pdfUrl, setPdfUrl] = useState(null);
    // 'empty' → nothing to print · 'building' → rendering · 'ready' → embedded · 'error'
    const [state, setState] = useState(labels.length === 0 ? 'empty' : 'building');
    const [attempt, setAttempt] = useState(0);

    // Auto-print fires ONCE per page load. Without this guard React 18/19 StrictMode
    // (double-invoked effects → a second blob → a second iframe load) would raise the
    // print dialog twice, and every later re-render of the iframe would raise it again.
    const printedRef = useRef(false);
    const frameRef = useRef(null);

    // Toast through a ref: `show` from a real provider is stable, but useToast() falls back to
    // a fresh no-op object when rendered outside one — keeping it out of the dep array below
    // makes the build effect immune to that difference.
    const toastRef = useRef(showToast);
    toastRef.current = showToast;

    // Build the sheet. The dynamic import is MANDATORY here: @react-pdf/renderer at module
    // top level pulls Node-only deps and crashes Inertia SSR.
    useEffect(() => {
        if (labels.length === 0) {
            setState('empty');
            return undefined;
        }

        let cancelled = false;
        setState('building');

        (async () => {
            let url = null;
            try {
                const { renderPackingLabelBlob } = await import('@/Components/MenuSampleOrders/pdf/PackingLabelPdf');
                const blob = await renderPackingLabelBlob({ labels, labelImage });
                url = URL.createObjectURL(blob);
                if (cancelled) {
                    // StrictMode's throwaway first pass (or a navigation mid-render): release the
                    // blob here, because it never reaches state and so never reaches the cleanup below.
                    URL.revokeObjectURL(url);
                    return;
                }
                setPdfUrl(url);
                setState('ready');
            } catch {
                if (cancelled) return;
                setState('error');
                toastRef.current('Could not build the label sheet. Please try again.', 'error');
            }
        })();

        return () => { cancelled = true; };
    }, [labels, labelImage, attempt]);

    // Release the blob URL when it is replaced and on unmount — an un-revoked object URL keeps
    // the whole PDF alive in memory for the life of the tab.
    useEffect(() => () => { if (pdfUrl) URL.revokeObjectURL(pdfUrl); }, [pdfUrl]);

    // Equivalent of legacy's AutoPrint(true). Called from the iframe's onLoad because the
    // embedded viewer has to be live before print() can reach it; re-armable by the button.
    const firePrint = (auto) => {
        if (auto) {
            if (printedRef.current) return;
            printedRef.current = true;
        }
        const win = frameRef.current?.contentWindow;
        if (!win) return;
        try {
            win.focus();
            win.print();
        } catch {
            // Some browsers refuse print() on a cross-document blob view; the embedded viewer
            // still has its own print control, so this is a degradation, not a failure.
            if (!auto) toastRef.current('Use the print control inside the preview.', 'info');
        }
    };

    return (
        <section className="flex min-w-0 flex-col gap-4.5">
            <header className="flex items-center justify-between gap-4">
                <p className="m-0 flex items-center gap-2 text-xs font-semibold text-muted-foreground">
                    <Link href={route('sample-orders.packing')} className="text-muted-foreground no-underline hover:text-primary">Packing</Link>
                    <span aria-hidden="true">›</span>
                    <span className="text-foreground">Sample Order #{q.id} — Labels</span>
                </p>
                <div className="flex shrink-0 items-center gap-2">
                    <Button
                        type="button"
                        disabled={state !== 'ready'}
                        onClick={() => firePrint(false)}
                        className="h-9 rounded-lg px-4 text-xs font-bold"
                    >
                        <Printer className="size-3.5" />
                        Print
                    </Button>
                    {/* Back to the Packing QUEUE, not to packing/{id}: this page serves an order in
                        ANY status, while the detail screen is hard-scoped to status 2 and would 404
                        for exactly the re-labelling case this route exists for. */}
                    <Link
                        href={route('sample-orders.packing')}
                        className="inline-flex h-9 items-center justify-center gap-1.5 rounded-lg border border-input bg-card px-4 text-xs font-bold text-foreground transition-colors hover:border-primary hover:text-primary"
                    >
                        <ArrowLeft className="size-3.5" />
                        Back to Packing
                    </Link>
                </div>
            </header>

            <article className={SECTION_CARD}>
                <header className={`${SECTION_HEAD} flex flex-wrap items-center justify-between gap-2`}>
                    <div className="min-w-0">
                        <h2 className={SECTION_TITLE}>Packing Labels</h2>
                        <small className={SECTION_SUB}>
                            {q.company || '—'}
                            <span aria-hidden="true" className="text-muted-foreground/40"> · </span>
                            {labels.length} label{labels.length === 1 ? '' : 's'}
                            <span aria-hidden="true" className="text-muted-foreground/40"> · </span>
                            10 per A4 sheet
                        </small>
                    </div>
                    {q.status && <StatusBadge tone={statusTone(q.status)}>{q.status}</StatusBadge>}
                </header>

                <div className="p-4">
                    {state === 'empty' && (
                        <p className="m-0 px-1 py-6 text-xs text-muted-foreground">
                            No lot has been assigned to this order yet, so there is nothing to label.
                        </p>
                    )}

                    {state === 'building' && (
                        <div className={`grid ${VIEWER_BOX} place-items-center rounded-lg border border-dashed border-border`}>
                            <span className="flex items-center gap-2 text-xs font-semibold text-muted-foreground">
                                <Loader2 className="size-4 animate-spin" />
                                Preparing labels…
                            </span>
                        </div>
                    )}

                    {state === 'error' && (
                        <div className={`grid ${VIEWER_BOX} place-items-center rounded-lg border border-dashed border-danger/40`}>
                            <div className="flex flex-col items-center gap-2.5 px-6 text-center">
                                <TriangleAlert className="size-5 text-danger" aria-hidden="true" />
                                <p className="m-0 text-xs font-semibold text-danger">The label sheet could not be built.</p>
                                <Button type="button" variant="outline" onClick={() => setAttempt((n) => n + 1)} className="h-9 rounded-lg px-4 text-xs font-bold">
                                    Try again
                                </Button>
                            </div>
                        </div>
                    )}

                    {state === 'ready' && pdfUrl && (
                        <iframe
                            ref={frameRef}
                            title={`Packing labels for Sample Order #${q.id}`}
                            src={pdfUrl}
                            onLoad={() => firePrint(true)}
                            className={`${VIEWER_BOX} rounded-lg border border-border bg-white`}
                        />
                    )}
                </div>
            </article>
        </section>
    );
}

SampleOrderPackingLabels.layout = [AppLayout];
