/**
 * Handover protocol schema editor.
 *
 * Renders a structured field list from JSON and serializes changes
 * back to a hidden input on form submit.
 */
import { resolveHost } from '/js/core/app-dom.js';

const FIELD_TYPES = ['heading', 'paragraph', 'text', 'textarea', 'number', 'date', 'checkbox', 'select'];
const DISPLAY_ONLY_TYPES = ['heading', 'paragraph'];
const EMPTY_API = Object.freeze({ destroy: () => {} });

const resolveEditor = (root) => {
  const host = resolveHost(root);
  if (host instanceof HTMLElement && host.matches('#handover-schema-editor[data-app-component="helpdesk-handover-schema-editor"]')) {
    return host;
  }
  return host.querySelector('#handover-schema-editor[data-app-component="helpdesk-handover-schema-editor"]');
};

/**
 * Remove all child nodes from an element (safe alternative to setting markup).
 * @param {HTMLElement} el
 */
function clearElement(el) {
  while (el.firstChild) {
    el.removeChild(el.firstChild);
  }
}

function init(root) {
  const listenerController = new AbortController();
  const on = (target, type, handler, options = {}) => {
    if (!target || typeof target.addEventListener !== 'function') {
      return;
    }
    target.addEventListener(type, handler, { ...options, signal: listenerController.signal });
  };

  const t = JSON.parse(root.dataset.translations || '{}');
  const initialFields = JSON.parse(root.dataset.initialFields || '[]');
  const scope = root.closest('.app-details-container') || document;
  const hiddenInput = scope.querySelector('#handover-schema-json');
  const previewContainer = scope.querySelector('#handover-schema-preview');
  const form = hiddenInput?.closest('form');

  /** @type {Array<object>} */
  let fields = initialFields.map((f) => ({ ...f, options: f.options ? f.options.map((o) => ({ ...o })) : [] }));

  render();
  renderPreview();
  syncHiddenInput();

  on(form, 'submit', () => syncHiddenInput());

  function render() {
    clearElement(root);

    if (fields.length === 0) {
      const empty = document.createElement('div');
      empty.className = 'handover-schema-empty-state';
      const emptyText = document.createElement('p');
      emptyText.textContent = t.no_fields || 'No fields defined yet.';
      empty.appendChild(emptyText);
      const addButton = document.createElement('button');
      addButton.type = 'button';
      addButton.className = 'secondary outline';
      addButton.appendChild(createIcon('bi-plus-lg'));
      addButton.appendChild(document.createTextNode(' ' + (t.add_field || 'Add field')));
      on(addButton, 'click', () => {
        fields.push({ type: 'text', key: '', label: '', required: false, options: [] });
        render();
        notifyChange();
      });
      empty.appendChild(addButton);
      root.appendChild(empty);
    } else {
      const list = document.createElement('div');
      list.className = 'handover-schema-list';
      fields.forEach((field, index) => {
        if (index > 0) {
          list.appendChild(buildInsertDivider(index));
        }
        list.appendChild(buildFieldRow(field, index));
      });
      root.appendChild(list);
      root.appendChild(buildInsertDivider(fields.length));
    }
  }

  function buildInsertDivider(insertIndex) {
    const divider = document.createElement('div');
    divider.className = 'handover-schema-insert-divider';
    const button = document.createElement('button');
    button.type = 'button';
    button.className = 'secondary outline small handover-schema-insert-button';
    button.setAttribute('data-tooltip', t.add_field || 'Add field');
    button.setAttribute('aria-label', t.add_field || 'Add field');
    button.appendChild(createIcon('bi-plus'));
    on(button, 'click', () => {
      fields.splice(insertIndex, 0, { type: 'text', key: '', label: '', required: false, options: [] });
      render();
      notifyChange();
    });
    divider.appendChild(button);
    return divider;
  }

  function buildFieldRow(field, index) {
    const isDisplayOnly = DISPLAY_ONLY_TYPES.includes(field.type);
    const isSelect = field.type === 'select';

    const row = document.createElement('div');
    row.className = 'handover-schema-row';
    row.dataset.fieldIndex = index;
    on(row, 'mouseenter', () => highlightPreview(index, true));
    on(row, 'mouseleave', () => highlightPreview(index, false));

    // --- Header: "Feld #N" title + action icons ---
    const header = document.createElement('div');
    header.className = 'handover-schema-row-header';

    const title = document.createElement('span');
    title.className = 'handover-schema-row-title';
    title.textContent = (t.field || 'Field') + ' #' + (index + 1);
    header.appendChild(title);

    const actions = document.createElement('div');
    actions.className = 'handover-schema-row-actions';

    if (index > 0) {
      actions.appendChild(createIconButton(
        'bi-arrow-up', 'secondary outline small',
        () => { [fields[index - 1], fields[index]] = [fields[index], fields[index - 1]]; render(); notifyChange(); },
        (t.move_up || 'Move up') + ' ' + (t.field_label || 'field') + ' ' + (index + 1),
      ));
    }
    if (index < fields.length - 1) {
      actions.appendChild(createIconButton(
        'bi-arrow-down', 'secondary outline small',
        () => { [fields[index], fields[index + 1]] = [fields[index + 1], fields[index]]; render(); notifyChange(); },
        (t.move_down || 'Move down') + ' ' + (t.field_label || 'field') + ' ' + (index + 1),
      ));
    }
    actions.appendChild(createIconButton(
      'bi-copy', 'secondary outline small',
      () => {
        const clone = { ...field, label: field.label, key: field.key || '' };
        if (field.options) { clone.options = field.options.map((o) => ({ ...o })); }
        fields.splice(index + 1, 0, clone);
        render();
        notifyChange();
      },
      (t.duplicate_field || 'Duplicate field') + ' ' + (index + 1),
    ));
    actions.appendChild(createIconButton(
      'bi-trash', 'danger outline small',
      () => { fields.splice(index, 1); render(); notifyChange(); },
      (t.remove_field || 'Remove field') + ' ' + (index + 1),
    ));

    header.appendChild(actions);
    row.appendChild(header);

    // --- Type select (full width) ---
    const typeGroup = createGroup(t.field_type || 'Field type');
    const typeSelect = document.createElement('select');
    typeSelect.setAttribute('aria-label', (t.field_type || 'Field type') + ' ' + (index + 1));
    FIELD_TYPES.forEach((ft) => {
      const opt = document.createElement('option');
      opt.value = ft;
      opt.textContent = t['type_' + ft] || ft;
      if (ft === field.type) opt.selected = true;
      typeSelect.appendChild(opt);
    });
    on(typeSelect, 'change', () => {
      field.type = typeSelect.value;
      if (DISPLAY_ONLY_TYPES.includes(field.type)) {
        delete field.key;
        delete field.required;
      } else {
        if (!field.key) field.key = '';
        if (field.required === undefined) field.required = false;
      }
      if (field.type === 'select' && (!field.options || field.options.length === 0)) {
        field.options = [{ value: '', label: '' }];
      }
      render();
      notifyChange();
    });
    typeGroup.appendChild(typeSelect);
    row.appendChild(typeGroup);

    // --- Body: label input ---
    const body = document.createElement('div');
    body.className = 'handover-schema-row-body';

    const labelKey = field.type === 'paragraph' ? (t.text_content || 'Text content') : (t.field_label || 'Label');
    const labelGroup = createGroup(labelKey);
    const labelInput = document.createElement(field.type === 'paragraph' ? 'textarea' : 'input');
    if (field.type !== 'paragraph') {
      labelInput.type = 'text';
    } else {
      labelInput.rows = 2;
    }
    labelInput.value = field.label || '';
    labelInput.setAttribute('aria-label', labelKey + ' ' + (index + 1));
    on(labelInput, 'input', () => { field.label = labelInput.value; notifyChange(); });
    labelGroup.appendChild(labelInput);
    body.appendChild(labelGroup);

    row.appendChild(body);

    // --- Required toggle — own row below key/label ---
    if (!isDisplayOnly) {
      const reqRow = document.createElement('div');
      reqRow.className = 'handover-schema-row-required';
      const reqLabel = document.createElement('label');
      reqLabel.className = 'handover-schema-checkbox-label';
      const reqInput = document.createElement('input');
      reqInput.type = 'checkbox';
      reqInput.checked = !!field.required;
      on(reqInput, 'change', () => { field.required = reqInput.checked; notifyChange(); });
      reqLabel.appendChild(reqInput);
      reqLabel.appendChild(document.createTextNode(' ' + (t.required || 'Required')));
      reqRow.appendChild(reqLabel);
      row.appendChild(reqRow);
    }

    // --- Select options ---
    if (isSelect) {
      const optionsSection = document.createElement('div');
      optionsSection.className = 'handover-schema-options';

      const optionsHeader = document.createElement('div');
      optionsHeader.className = 'handover-schema-options-header';
      const optionsTitle = document.createElement('strong');
      optionsTitle.textContent = t.options || 'Options';
      optionsHeader.appendChild(optionsTitle);

      const addOptButton = document.createElement('button');
      addOptButton.type = 'button';
      addOptButton.className = 'secondary outline small';
      addOptButton.setAttribute('data-tooltip', t.add_option || 'Add option');
      addOptButton.setAttribute('aria-label', t.add_option || 'Add option');
      addOptButton.appendChild(createIcon('bi-plus-lg'));
      on(addOptButton, 'click', () => {
        field.options.push({ value: '', label: '' });
        render();
        notifyChange();
      });
      optionsHeader.appendChild(addOptButton);
      optionsSection.appendChild(optionsHeader);

      if (!field.options) field.options = [];

      field.options.forEach((opt, optIndex) => {
        const optRow = document.createElement('div');
        optRow.className = 'handover-schema-option-row';

        const lblInput = document.createElement('input');
        lblInput.type = 'text';
        lblInput.value = opt.label || '';
        lblInput.placeholder = (t.option_label || 'Label') + ' ' + (optIndex + 1);
        lblInput.setAttribute('aria-label', (t.option_label || 'Label') + ' ' + (optIndex + 1));
        on(lblInput, 'input', () => { opt.label = lblInput.value; notifyChange(); });
        optRow.appendChild(lblInput);

        optRow.appendChild(createIconButton(
          'bi-x-lg', 'danger outline small',
          () => { field.options.splice(optIndex, 1); render(); notifyChange(); },
          (t.remove_option || 'Remove option') + ' ' + (optIndex + 1),
        ));

        optionsSection.appendChild(optRow);
      });

      row.appendChild(optionsSection);
    }

    return row;
  }

  function createGroup(labelText) {
    const group = document.createElement('div');
    group.className = 'handover-schema-field-group';
    if (labelText) {
      const label = document.createElement('span');
      label.className = 'handover-schema-field-label';
      label.textContent = labelText;
      group.appendChild(label);
    }
    return group;
  }

  function createIcon(iconClass) {
    const icon = document.createElement('i');
    icon.className = 'bi ' + iconClass;
    return icon;
  }

  function createIconButton(iconClass, buttonClass, onClick, ariaLabel) {
    const button = document.createElement('button');
    button.type = 'button';
    button.className = buttonClass;
    button.setAttribute('aria-label', ariaLabel);
    button.appendChild(createIcon(iconClass));
    on(button, 'click', onClick);
    return button;
  }

  function renderPreview() {
    if (!previewContainer) return;
    clearElement(previewContainer);

    if (fields.length === 0) {
      const empty = document.createElement('p');
      empty.className = 'handover-schema-preview-empty';
      empty.textContent = t.preview_empty || 'Add fields to see a live preview.';
      previewContainer.appendChild(empty);
      return;
    }

    const formEl = document.createElement('div');
    formEl.className = 'handover-schema-preview-form';

    fields.forEach((field, index) => {
      if (field.type === 'heading') {
        const h = document.createElement('h3');
        h.dataset.fieldIndex = index;
        h.textContent = field.label || '';
        formEl.appendChild(h);
        return;
      }

      if (field.type === 'paragraph') {
        const p = document.createElement('p');
        p.dataset.fieldIndex = index;
        p.textContent = field.label || '';
        formEl.appendChild(p);
        return;
      }

      const group = document.createElement('div');
      group.className = 'handover-schema-preview-field';
      group.dataset.fieldIndex = index;

      if (field.type === 'checkbox') {
        const input = document.createElement('input');
        input.type = 'checkbox';
        on(input, 'click', (e) => e.preventDefault());
        group.appendChild(input);
        const label = document.createElement('label');
        label.textContent = field.label || '';
        if (field.required) {
          const star = document.createElement('span');
          star.className = 'handover-schema-preview-required';
          star.textContent = ' *';
          label.appendChild(star);
        }
        group.appendChild(label);
      } else {
        const label = document.createElement('label');
        label.textContent = field.label || '';
        if (field.required) {
          const star = document.createElement('span');
          star.className = 'handover-schema-preview-required';
          star.textContent = ' *';
          label.appendChild(star);
        }
        group.appendChild(label);

        let input;
        if (field.type === 'textarea') {
          input = document.createElement('textarea');
          input.rows = 3;
        } else if (field.type === 'select') {
          input = document.createElement('select');
          const placeholder = document.createElement('option');
          placeholder.value = '';
          placeholder.textContent = '';
          input.appendChild(placeholder);
          (field.options || []).forEach((opt) => {
            const option = document.createElement('option');
            option.textContent = opt.label || '';
            input.appendChild(option);
          });
        } else {
          input = document.createElement('input');
          input.type = field.type === 'number' ? 'number' : field.type === 'date' ? 'date' : 'text';
        }
        input.disabled = true;
        group.appendChild(input);
      }

      formEl.appendChild(group);
    });

    previewContainer.appendChild(formEl);
  }

  function highlightPreview(index, active) {
    if (!previewContainer) return;
    const el = previewContainer.querySelector('[data-field-index="' + index + '"]');
    if (el) {
      el.classList.toggle('handover-schema-preview-highlight', active);
    }
  }

  function syncHiddenInput() {
    if (!hiddenInput) return;
    hiddenInput.value = fields.length > 0 ? JSON.stringify(fields) : '';
  }

  function notifyChange() {
    syncHiddenInput();
    renderPreview();
    if (hiddenInput) {
      hiddenInput.dispatchEvent(new Event('input', { bubbles: true }));
    }
  }

  return {
    destroy: () => {
      listenerController.abort();
    },
  };
}

export function initHandoverSchemaEditor(root = document) {
  const container = resolveEditor(root);
  if (!container) {
    return EMPTY_API;
  }

  return init(container);
}
