import { Node, mergeAttributes } from '@tiptap/core';
import { NodeViewWrapper, ReactNodeViewRenderer, type ReactNodeViewProps } from '@tiptap/react';
import * as React from 'react';

/**
 * Inline atom node representing a signature placeholder inside a document.
 * Two flavors:
 *   - slot="sender"    → the Conciergerie (TLL) signature, optionally pre-filled
 *   - slot="recipient" → the partner's signature, filled at sign-time
 *
 * Authoring stays inside Tiptap (insertable / deletable), and the node
 * survives the editor's HTML round-trip (its `data-signature-slot` attribute
 * is preserved on save and re-parsed on load).
 *
 * The public DocumentRenderer also recognizes these spans and swaps them
 * with the real signature images at view-time.
 */

export interface SignatureSlotAttrs {
    slot: 'sender' | 'recipient';
}

/**
 * Per-editor URLs the NodeView reads to decide what to render inline.
 * Passed via editor `editorProps` so we don't need React context.
 */
declare module '@tiptap/core' {
    interface EditorOptions {
        signatureContext?: {
            senderSignatureUrl?: string | null;
            senderStampUrl?: string | null;
            recipientSignatureUrl?: string | null;
        };
    }
    interface Commands<ReturnType> {
        signatureSlot: {
            insertSignatureSlot: (slot: 'sender' | 'recipient') => ReturnType;
        };
    }
}

export const SignatureSlot = Node.create<{ context?: () => SignatureSlotContext }>({
    name: 'signatureSlot',
    group: 'inline',
    inline: true,
    atom: true,
    selectable: true,
    draggable: false,

    addAttributes() {
        return {
            slot: {
                default: 'sender',
                parseHTML: (el: HTMLElement) =>
                    el.getAttribute('data-signature-slot') === 'recipient' ? 'recipient' : 'sender',
                renderHTML: (attrs: { slot: string }) => ({
                    'data-signature-slot': attrs.slot,
                }),
            },
        };
    },

    parseHTML() {
        return [
            {
                tag: 'span[data-signature-slot]',
            },
        ];
    },

    renderHTML({ HTMLAttributes, node }) {
        const slot = (node.attrs as SignatureSlotAttrs).slot ?? 'sender';
        const label = slot === 'sender' ? '[Signature Conciergerie]' : '[Signature Partenaire]';
        return [
            'span',
            mergeAttributes(HTMLAttributes, {
                'data-signature-slot': slot,
                class: 'signature-slot',
            }),
            label,
        ];
    },

    addCommands() {
        return {
            insertSignatureSlot:
                (slot: 'sender' | 'recipient') =>
                ({ commands }) =>
                    commands.insertContent({
                        type: this.name,
                        attrs: { slot },
                    }),
        };
    },

    addNodeView() {
        return ReactNodeViewRenderer(SignatureSlotView);
    },
});

interface SignatureSlotContext {
    senderSignatureUrl?: string | null;
    senderStampUrl?: string | null;
    recipientSignatureUrl?: string | null;
}

function SignatureSlotView({ node, editor }: ReactNodeViewProps) {
    const slot = (node.attrs as SignatureSlotAttrs).slot ?? 'sender';
    const ctx = (editor.options.signatureContext ?? {}) as SignatureSlotContext;

    const isSender = slot === 'sender';
    const senderStamp = ctx.senderStampUrl ?? '/admin-sign/sign-admin.png';
    const labelText = isSender ? 'Signature et cachet du mandataire' : 'Signature du Partenaire';

    return (
        <NodeViewWrapper as="span" className="signature-slot-wrapper" data-signature-slot={slot}>
            <span
                className="inline-block w-full max-w-xs text-center align-top"
                contentEditable={false}
            >
                <span className="mb-2 block text-base font-semibold text-black">{labelText}</span>
                {isSender ? (
                    <img
                        src={ctx.senderSignatureUrl || senderStamp}
                        alt="Signature Conciergerie"
                        className="mx-auto block h-48 w-64 object-contain"
                    />
                ) : ctx.recipientSignatureUrl ? (
                    <img
                        src={ctx.recipientSignatureUrl}
                        alt="Signature Partenaire"
                        className="mx-auto block h-48 w-full max-w-xs rounded border border-gray-400 object-contain"
                    />
                ) : (
                    <span className="mx-auto flex h-48 w-full max-w-xs items-center justify-center rounded border border-dashed border-gray-400 bg-white text-xs italic text-slate-400">
                        Zone de signature du partenaire
                    </span>
                )}
            </span>
        </NodeViewWrapper>
    );
}
