import { cn } from '@/lib/utils';
import * as React from 'react';
import { createPortal } from 'react-dom';
import { InlineSignatureWidget } from './inline-signature-widget';
import { normalizeSignatureSlots, renderStaticSignatureSlots } from './normalize-slots';

interface DocumentRendererProps {
    html: string;
    senderSignatureUrl?: string | null;
    senderStampUrl?: string | null;
    recipientSignatureUrl?: string | null;
    recipientStampUrl?: string | null;
    /** ISO date — appended under the recipient signature image when locked. */
    recipientSignedAt?: string | null;
    className?: string;
    /** Wrap with the TLL branded header/house/footer (default true). */
    branded?: boolean;
    /**
     * When provided, every `<span data-signature-slot="recipient">` in the
     * document body becomes an inline `<InlineSignatureWidget>` mounted via
     * React portal — same UX as the mandat (PropertyContract) signature.
     * Omit (or set `locked`) once the document has been signed.
     */
    recipientPad?: {
        value: string | null;
        onChange: (base64: string | null) => void;
    };
    /** True once the recipient has signed — slots become passive images. */
    locked?: boolean;
}

/**
 * Read-only renderer with two passes:
 *
 *  1. DOM pass (imperative): walks every `[data-signature-slot]` element
 *     and prepares it as either (a) a passive image host or (b) a portal
 *     mount point for the interactive widget.
 *
 *  2. Portal pass (declarative): renders an `<InlineSignatureWidget>`
 *     into each prepared mount point so the recipient signs inline,
 *     exactly where the admin placed the slot.
 */
export function DocumentRenderer({
    html,
    senderSignatureUrl,
    senderStampUrl,
    recipientSignatureUrl,
    recipientStampUrl,
    recipientSignedAt,
    className,
    branded = true,
    recipientPad,
    locked = false,
}: DocumentRendererProps) {
    const containerRef = React.useRef<HTMLDivElement>(null);
    // When there's no interactive recipient pad, fully bake the signature
    // blocks into the HTML — eliminates any reliance on a post-mount JS pass
    // for the passive layout. Only the interactive pad path still needs the
    // imperative effect below to mount the canvas portal.
    const normalizedHtml = React.useMemo(
        () =>
            recipientPad && !locked
                ? normalizeSignatureSlots(html)
                : renderStaticSignatureSlots(html, {
                      senderSignatureUrl,
                      senderStampUrl,
                      recipientSignatureUrl,
                      recipientSignedAt,
                  }),
        [html, recipientPad, locked, senderSignatureUrl, senderStampUrl, recipientSignatureUrl, recipientSignedAt],
    );

    const [recipientHosts, setRecipientHosts] = React.useState<HTMLElement[]>([]);

    // Re-scan slots when the document HTML or any signature URL changes.
    // We don't include `recipientPad` here so transient onChange-triggered
    // re-renders don't unmount the portal contents.
    React.useEffect(() => {
        const root = containerRef.current;
        if (!root) return;

        const hosts: HTMLElement[] = [];
        const slots = root.querySelectorAll<HTMLElement>('[data-signature-slot]');

        slots.forEach((slot) => {
            const which = slot.dataset.signatureSlot;

            // Skip slots already processed on a prior effect pass (idempotent
            // re-scan) — avoids infinitely replacing the recipient host div
            // and unmounting the portal.
            if (slot.dataset.signatureSlotProcessed === '1') {
                if (which === 'recipient' && recipientPad && !locked) hosts.push(slot);
                return;
            }
            slot.dataset.signatureSlotProcessed = '1';

            const signatureUrl = which === 'sender' ? senderSignatureUrl : recipientSignatureUrl;
            const stampUrl = which === 'sender' ? senderStampUrl : recipientStampUrl;

            // Reset every time so we don't accumulate stale children.
            slot.innerHTML = '';
            slot.removeAttribute('style');

            // ── Recipient slot, interactive pad mode ─────────────────────
            // Replace the original <span> with a <div> so the React widget
            // (which is a div) lives in a valid HTML container regardless
            // of what wrapped the slot (paragraph, table cell, etc.).
            if (which === 'recipient' && recipientPad && !locked) {
                const host = document.createElement('div');
                host.setAttribute('data-signature-slot', 'recipient');
                host.dataset.signatureSlotProcessed = '1';
                host.style.display = 'block';
                host.style.width = '100%';
                host.style.margin = '12px 0';
                slot.parentNode?.replaceChild(host, slot);
                hosts.push(host);
                return;
            }

            // ── Passive block — mirrors the reservation contract layout ──
            // Centered block: title on top, signature/stamp image below.
            slot.style.display = 'inline-block';
            slot.style.textAlign = 'center';
            slot.style.verticalAlign = 'top';
            slot.style.width = '100%';
            slot.style.maxWidth = '320px';

            const title = document.createElement('div');
            title.textContent = which === 'sender'
                ? 'Signature et cachet du mandataire'
                : 'Signature du Partenaire';
            title.style.fontSize = '14px';
            title.style.fontWeight = '600';
            title.style.color = '#000';
            title.style.marginBottom = '8px';
            slot.appendChild(title);

            // Sender: show stamp (or default) at contract size.
            if (which === 'sender') {
                const stampSrc = stampUrl || signatureUrl;
                if (stampSrc) {
                    const img = document.createElement('img');
                    img.src = stampSrc;
                    img.alt = 'Signature Conciergerie';
                    img.style.display = 'block';
                    img.style.margin = '0 auto';
                    img.style.height = '12rem';
                    img.style.width = '16rem';
                    img.style.objectFit = 'contain';
                    slot.appendChild(img);
                }
                return;
            }

            // Recipient: locked image with optional "Signé le …" caption.
            const box = document.createElement('div');
            box.style.display = 'block';
            box.style.margin = '0 auto';
            box.style.height = '12rem';
            box.style.width = '100%';
            box.style.maxWidth = '20rem';
            box.style.borderRadius = '0.375rem';
            box.style.border = '1px solid #9ca3af';
            box.style.background = '#fff';
            box.style.overflow = 'hidden';

            if (signatureUrl) {
                const img = document.createElement('img');
                img.src = signatureUrl;
                img.alt = 'Signature Partenaire';
                img.style.height = '100%';
                img.style.width = '100%';
                img.style.objectFit = 'contain';
                box.appendChild(img);
            } else {
                const ph = document.createElement('span');
                ph.textContent = 'En attente de signature';
                ph.style.display = 'flex';
                ph.style.alignItems = 'center';
                ph.style.justifyContent = 'center';
                ph.style.height = '100%';
                ph.style.color = '#94a3b8';
                ph.style.fontStyle = 'italic';
                ph.style.fontSize = '13px';
                box.appendChild(ph);
            }
            slot.appendChild(box);

            if (recipientSignedAt && signatureUrl) {
                const caption = document.createElement('div');
                caption.textContent = 'Signé le ' + formatDateFr(recipientSignedAt);
                caption.style.fontSize = '11px';
                caption.style.color = '#64748b';
                caption.style.marginTop = '6px';
                slot.appendChild(caption);
            }
        });

        setRecipientHosts(hosts);
    }, [normalizedHtml, senderSignatureUrl, senderStampUrl, recipientSignatureUrl, recipientStampUrl, recipientSignedAt, locked, recipientPad ? 'on' : 'off']);

    const body = (
        <div
            ref={containerRef}
            className="tiptap-content tiptap-rendered"
            // eslint-disable-next-line react/no-danger
            dangerouslySetInnerHTML={{ __html: normalizedHtml }}
        />
    );

    const portals = recipientPad
        ? recipientHosts.map((host, i) =>
              createPortal(
                  <InlineSignatureWidget
                      key={`pad-${i}`}
                      slot="recipient"
                      value={recipientPad.value}
                      onChange={recipientPad.onChange}
                  />,
                  host,
                  `recipient-portal-${i}`,
              ),
          )
        : null;

    if (!branded) {
        return (
            <div className={cn('bg-white p-6 sm:p-10', className)}>
                {body}
                {portals}
            </div>
        );
    }

    return (
        <div className={cn('tll-letterhead relative bg-white', className)}>
            <header className="tll-letterhead__header relative flex items-start px-8 pt-8 pb-2">
                <img src="/Logo.png" alt="The Landlord" className="h-20 w-auto object-contain" />
            </header>
            <div className="px-8 pb-32 pt-2 sm:px-12">{body}</div>
            <footer className="tll-letterhead__footer absolute bottom-0 left-0 right-0 flex flex-col gap-3 border-t border-slate-200 bg-slate-50 px-8 py-4 text-xs text-slate-500 sm:flex-row sm:items-start sm:gap-10">
                <div className="flex items-start gap-2">
                    <MapPinGlyph className="mt-0.5 h-5 w-5 shrink-0 text-[#1b4e4d]" />
                    <div>
                        <p className="text-sm font-semibold text-slate-900">Adresse</p>
                        <p className="text-slate-500">13 Rue Mohamed Fadhel Ben Achour, Tunis 2070</p>
                    </div>
                </div>
                <div className="flex items-start gap-2">
                    <MailGlyph className="mt-0.5 h-5 w-5 shrink-0 text-[#1b4e4d]" />
                    <div>
                        <p className="text-sm font-semibold text-slate-900">E-mail</p>
                        <p className="text-slate-500">contact@thelandlord.tn</p>
                    </div>
                </div>
            </footer>
            {portals}
        </div>
    );
}

function formatDateFr(value: string): string {
    const d = new Date(value);
    if (Number.isNaN(d.getTime())) return value;
    const dd = String(d.getDate()).padStart(2, '0');
    const mm = String(d.getMonth() + 1).padStart(2, '0');
    const yyyy = d.getFullYear();
    const hh = String(d.getHours()).padStart(2, '0');
    const mi = String(d.getMinutes()).padStart(2, '0');
    return `${dd}/${mm}/${yyyy} ${hh}:${mi}`;
}

function HouseGlyph({ className }: { className?: string }) {
    return (
        <svg
            viewBox="0 0 24 24"
            xmlns="http://www.w3.org/2000/svg"
            className={className}
            fill="none"
            stroke="currentColor"
            strokeWidth="2"
            strokeLinecap="round"
            strokeLinejoin="round"
            aria-hidden="true"
        >
            <path d="M3 11l9-8 9 8" />
            <path d="M5 10v10h14V10" />
        </svg>
    );
}

function MapPinGlyph({ className }: { className?: string }) {
    return (
        <svg
            viewBox="0 0 24 24"
            xmlns="http://www.w3.org/2000/svg"
            className={className}
            fill="none"
            stroke="currentColor"
            strokeWidth="2"
            strokeLinecap="round"
            strokeLinejoin="round"
            aria-hidden="true"
        >
            <path d="M20 10c0 6-8 12-8 12s-8-6-8-12a8 8 0 1 1 16 0Z" />
            <circle cx="12" cy="10" r="3" />
        </svg>
    );
}

function MailGlyph({ className }: { className?: string }) {
    return (
        <svg
            viewBox="0 0 24 24"
            xmlns="http://www.w3.org/2000/svg"
            className={className}
            fill="none"
            stroke="currentColor"
            strokeWidth="2"
            strokeLinecap="round"
            strokeLinejoin="round"
            aria-hidden="true"
        >
            <rect x="3" y="5" width="18" height="14" rx="2" />
            <path d="m3 7 9 6 9-6" />
        </svg>
    );
}
