import { esc, stripTags } from './utils.js';

export function createNotesEditor(options) {
  options = options || {};
  var editor = null;

  function mount(container, initialHtml) {
    var T = window.Tiptap || {};
    if (!T.Editor) {
      container.innerHTML = '<textarea class="notes-body-fallback" placeholder="Write your note...">' + esc(stripTags(initialHtml)) + '</textarea>';
      editor = null;
      var fb = container.querySelector('.notes-body-fallback');
      if (fb) fb.addEventListener('input', function() { markDirty(); });
      return;
    }
    container.innerHTML = toolbarHTML() + '<div class="tp-content"></div>';
    editor = new T.Editor({
      element: container.querySelector('.tp-content'),
      extensions: [
        T.StarterKit,
        T.Link.configure({ openOnClick: false, autolink: true }),
        T.Underline
      ],
      content: initialHtml || '',
      autofocus: false,
      onUpdate: function() {
        markDirty();
        updateToolbarState(container);
      },
      onSelectionUpdate: function() { updateToolbarState(container); }
    });
    wireToolbar(container, editor);
  }

  function destroy() {
    if (!editor) return;
    editor.destroy();
    editor = null;
  }

  function getBody() {
    if (!editor) {
      var fb = document.querySelector('.notes-body-fallback');
      return fb ? fb.value : '';
    }
    var html = editor.getHTML();
    return (html === '<p></p>' || html === '') ? '' : html;
  }

  function applyGenerated(container, body) {
    if (editor && typeof editor.commands === 'object') {
      try {
        editor.commands.setContent(body || '<p></p>', { emitUpdate: true });
        if (typeof options.onDirty === 'function') options.onDirty();
        return;
      } catch (err) {
        console.warn('[notes] Tiptap setContent failed, rebuilding:', err && err.message);
      }
    }
    destroy();
    mount(container, body || '<p></p>');
    if (typeof options.onDirty === 'function') options.onDirty();
  }

  function markDirty() {
    if (typeof options.onDirty === 'function') options.onDirty();
    if (typeof options.onStatus === 'function') options.onStatus('Saving...', 'saving');
    if (typeof options.onAutosave === 'function') options.onAutosave();
  }

  function toolbarHTML() {
    var btns = ''
      + '<button type="button" class="tp-btn" data-cmd="bold" title="Bold"><i class="fas fa-bold"></i></button>'
      + '<button type="button" class="tp-btn" data-cmd="italic" title="Italic"><i class="fas fa-italic"></i></button>'
      + '<button type="button" class="tp-btn" data-cmd="underline" title="Underline"><i class="fas fa-underline"></i></button>'
      + '<button type="button" class="tp-btn" data-cmd="strike" title="Strike"><i class="fas fa-strikethrough"></i></button>'
      + '<span class="tp-sep"></span>'
      + '<button type="button" class="tp-btn" data-cmd="h2" title="Heading 2">H2</button>'
      + '<button type="button" class="tp-btn" data-cmd="h3" title="Heading 3">H3</button>'
      + '<span class="tp-sep"></span>'
      + '<button type="button" class="tp-btn" data-cmd="bulletList" title="Bullet list"><i class="fas fa-list-ul"></i></button>'
      + '<button type="button" class="tp-btn" data-cmd="orderedList" title="Numbered list"><i class="fas fa-list-ol"></i></button>'
      + '<button type="button" class="tp-btn" data-cmd="blockquote" title="Quote"><i class="fas fa-quote-left"></i></button>'
      + '<button type="button" class="tp-btn" data-cmd="codeBlock" title="Code"><i class="fas fa-code"></i></button>'
      + '<span class="tp-sep"></span>'
      + '<button type="button" class="tp-btn" data-cmd="link" title="Link"><i class="fas fa-link"></i></button>'
      + '<span class="tp-sep"></span>'
      + '<button type="button" class="tp-btn" data-cmd="clear" title="Clear formatting"><i class="fas fa-remove-format"></i></button>';
    return ''
      + '<div class="tp-toolbar">' + btns + '</div>'
      + '<div class="tp-link-bar" style="display:none;">'
      +   '<input type="url" class="tp-link-input" placeholder="https://">'
      +   '<button type="button" class="tp-link-apply">Apply</button>'
      +   '<button type="button" class="tp-link-remove">Remove</button>'
      +   '<button type="button" class="tp-link-cancel">x</button>'
      + '</div>';
  }

  function wireToolbar(wrap, ed) {
    var toolbar = wrap.querySelector('.tp-toolbar');
    var linkBar = wrap.querySelector('.tp-link-bar');
    var linkInput = wrap.querySelector('.tp-link-input');

    toolbar.addEventListener('mousedown', function(e) {
      var btn = e.target.closest('.tp-btn[data-cmd]');
      if (!btn) return;
      e.preventDefault();
      var cmd = btn.dataset.cmd;
      switch (cmd) {
        case 'bold':         ed.chain().focus().toggleBold().run(); break;
        case 'italic':       ed.chain().focus().toggleItalic().run(); break;
        case 'underline':    ed.chain().focus().toggleUnderline().run(); break;
        case 'strike':       ed.chain().focus().toggleStrike().run(); break;
        case 'h2':           ed.chain().focus().toggleHeading({ level: 2 }).run(); break;
        case 'h3':           ed.chain().focus().toggleHeading({ level: 3 }).run(); break;
        case 'bulletList':   ed.chain().focus().toggleBulletList().run(); break;
        case 'orderedList':  ed.chain().focus().toggleOrderedList().run(); break;
        case 'blockquote':   ed.chain().focus().toggleBlockquote().run(); break;
        case 'codeBlock':    ed.chain().focus().toggleCodeBlock().run(); break;
        case 'clear':        ed.chain().focus().unsetAllMarks().clearNodes().run(); break;
        case 'link':
          if (linkBar.style.display === 'none') {
            linkInput.value = ed.getAttributes('link').href || '';
            linkBar.style.display = 'flex';
            setTimeout(function() { linkInput.focus(); }, 0);
          } else {
            linkBar.style.display = 'none';
          }
          break;
      }
      updateToolbarState(wrap);
    });

    wrap.querySelector('.tp-link-apply').addEventListener('mousedown', function(e) {
      e.preventDefault();
      var url = linkInput.value.trim();
      if (url) ed.chain().focus().extendMarkRange('link').setLink({ href: url }).run();
      linkBar.style.display = 'none';
    });
    wrap.querySelector('.tp-link-remove').addEventListener('mousedown', function(e) {
      e.preventDefault();
      ed.chain().focus().unsetLink().run();
      linkBar.style.display = 'none';
    });
    wrap.querySelector('.tp-link-cancel').addEventListener('mousedown', function(e) {
      e.preventDefault();
      linkBar.style.display = 'none';
    });
    linkInput.addEventListener('keydown', function(e) {
      if (e.key === 'Enter')  { e.preventDefault(); wrap.querySelector('.tp-link-apply').dispatchEvent(new MouseEvent('mousedown')); }
      if (e.key === 'Escape') { linkBar.style.display = 'none'; }
    });
  }

  function updateToolbarState(wrap) {
    if (!editor) return;
    wrap.querySelectorAll('.tp-btn[data-cmd]').forEach(function(btn) {
      var cmd = btn.dataset.cmd;
      var active = false;
      if      (cmd === 'bold')        active = editor.isActive('bold');
      else if (cmd === 'italic')      active = editor.isActive('italic');
      else if (cmd === 'underline')   active = editor.isActive('underline');
      else if (cmd === 'strike')      active = editor.isActive('strike');
      else if (cmd === 'h2')          active = editor.isActive('heading', { level: 2 });
      else if (cmd === 'h3')          active = editor.isActive('heading', { level: 3 });
      else if (cmd === 'bulletList')  active = editor.isActive('bulletList');
      else if (cmd === 'orderedList') active = editor.isActive('orderedList');
      else if (cmd === 'blockquote')  active = editor.isActive('blockquote');
      else if (cmd === 'codeBlock')   active = editor.isActive('codeBlock');
      else if (cmd === 'link')        active = editor.isActive('link');
      btn.classList.toggle('active', active);
    });
  }

  return {
    mount: mount,
    destroy: destroy,
    getBody: getBody,
    applyGenerated: applyGenerated
  };
}
