import { Editor } from '@tiptap/core';
import StarterKit from '@tiptap/starter-kit';
import Underline from '@tiptap/extension-underline';
import Link from '@tiptap/extension-link';

function createWysiwygData({ initial, disabled }) {
    // Store editor outside Alpine's reactive data to prevent Proxy wrapping,
    // which causes ProseMirror "mismatched transaction" errors.
    let editor = null;
    let skipWatch = false;

    return {
        html: initial || '',
        disabled: !!disabled,
        htmlMode: false,

        init() {
            this.$nextTick(() => {
                this._createEditor();

                this.$watch('html', (val) => {
                    if (skipWatch) return;
                    if (this.htmlMode) return;
                    if (!editor) return;

                    const currentHtml = editor.getHTML();
                    if (currentHtml === val) return;

                    editor.commands.setContent(val || '', false);
                });
            });
        },

        _createEditor() {
            const el = this.$refs.editable;
            if (!el) return;

            if (editor) {
                editor.destroy();
                editor = null;
            }

            el.innerHTML = '';

            editor = new Editor({
                element: el,
                editable: !this.disabled,
                content: this.html || '',
                extensions: [
                    StarterKit.configure({
                        heading: {
                            levels: [2, 3, 4, 5],
                        },
                    }),
                    Underline,
                    Link.configure({
                        openOnClick: false,
                    }),
                ],
                onUpdate: ({ editor: ed }) => {
                    skipWatch = true;
                    this.html = ed.getHTML();
                    this.$nextTick(() => {
                        this.$nextTick(() => {
                            skipWatch = false;
                        });
                    });
                },
            });
        },

        toggleHtmlMode() {
            if (!this.htmlMode) {
                if (editor) {
                    editor.destroy();
                    editor = null;
                }
                this.htmlMode = true;
            } else {
                this.htmlMode = false;
                this.$nextTick(() => {
                    this._createEditor();
                });
            }
        },

        cmd(command) {
            if (this.disabled || !editor) return;

            const chain = editor.chain().focus();
            switch (command) {
                case 'bold':
                    chain.toggleBold().run();
                    break;
                case 'italic':
                    chain.toggleItalic().run();
                    break;
                case 'underline':
                    chain.toggleUnderline().run();
                    break;
                case 'strikeThrough':
                    chain.toggleStrike().run();
                    break;
                case 'insertUnorderedList':
                    chain.toggleBulletList().run();
                    break;
                case 'insertOrderedList':
                    chain.toggleOrderedList().run();
                    break;
                default:
                    break;
            }
        },

        toggleHeading(level) {
            if (this.disabled || !editor) return;
            if (level === 1) return;
            editor.chain().focus().toggleHeading({ level }).run();
        },

        setParagraph() {
            if (this.disabled || !editor) return;
            editor.chain().focus().setParagraph().run();
        },

        setLink() {
            if (this.disabled || !editor) return;
            const url = prompt('URL', 'https://');
            if (!url) return;
            editor.chain().focus().setLink({ href: url }).run();
        },

        unsetLink() {
            if (this.disabled || !editor) return;
            editor.chain().focus().unlink().run();
        },

        toggleBlockquote() {
            if (this.disabled || !editor) return;
            editor.chain().focus().toggleBlockquote().run();
        },

        destroy() {
            if (editor) {
                editor.destroy();
                editor = null;
            }
        },
    };
}

export const initAlpineWysiwyg = () => {
    window.alpineWysiwyg = function ({ initial, disabled }) {
        if (window.Alpine && typeof Alpine.data === 'function') {
            const componentData = Alpine.data('alpineWysiwyg');
            if (componentData) {
                return componentData({ initial, disabled });
            }
        }

        return createWysiwygData({ initial, disabled });
    };

    const defineAlpineWysiwyg = () => {
        if (window.Alpine && typeof Alpine.data === 'function') {
            Alpine.data('alpineWysiwyg', ({ initial, disabled }) => {
                return createWysiwygData({ initial, disabled });
            });
        }
    };

    if (window.Alpine) {
        defineAlpineWysiwyg();
    }

    document.addEventListener('alpine:init', () => {
        defineAlpineWysiwyg();
    });

    if (window.Livewire) {
        document.addEventListener('livewire:init', () => {
            defineAlpineWysiwyg();
        });

        document.addEventListener('livewire:morph', () => {
            if (window.Alpine && typeof Alpine.data === 'function' && !Alpine.data('alpineWysiwyg')) {
                defineAlpineWysiwyg();
            }
            if (window.Alpine && typeof Alpine.initTree === 'function') {
                setTimeout(() => {
                    document.querySelectorAll('[x-data*="alpineWysiwyg"]').forEach(el => {
                        if (!el._x_dataStack) {
                            Alpine.initTree(el);
                        }
                    });
                }, 0);
            }
        });
    }
}
