(() => {
  const gallery = document.querySelector('[data-media-upload="gallery"]');
  if (gallery) {
    const fileInput = gallery.querySelector('[data-media-files]');
    const list = gallery.querySelector('[data-media-list]');
    fileInput?.addEventListener('change', () => {
      list.replaceChildren();
      const title = document.querySelector('input[name="title"]')?.value.trim() || '게시글';
      [...fileInput.files].forEach((file, index) => {
        const item = document.createElement('article');
        item.className = 'admin-new-media-item';
        const preview = document.createElement('img');
        preview.src = URL.createObjectURL(file);
        preview.alt = '';
        const name = document.createElement('strong');
        name.textContent = file.name;
        const label = document.createElement('label');
        label.textContent = '대체 텍스트';
        const alt = document.createElement('input');
        alt.name = 'new_gallery_alts[]';
        alt.value = `${title} - 대표 이미지 ${index + 1}`;
        alt.maxLength = 255;
        alt.required = true;
        label.append(alt);
        item.append(preview, name, label);
        list.append(item);
      });
    });
  }

  document.querySelectorAll('.admin-media-delete input[type="checkbox"]').forEach((checkbox) => {
    checkbox.addEventListener('change', () => {
      const item = checkbox.closest('.admin-media-item');
      const alt = item?.querySelector('input:not([type]), input[type="text"]');
      item?.classList.toggle('is-delete', checkbox.checked);
      if (alt) alt.required = !checkbox.checked;
    });
  });
})();

(() => {
  const editor = document.querySelector('[data-block-editor]');
  const sourceWrap = document.querySelector('[data-body-source]');
  const source = document.querySelector('[data-post-body]');
  if (!editor || !sourceWrap || !source) return;

  const list = editor.querySelector('[data-block-list]');
  const deleteBin = editor.querySelector('[data-delete-bin]');
  const inventory = new Map();
  editor.querySelectorAll('[data-existing-inline]').forEach((item) => {
    inventory.set(Number(item.dataset.token), {
      id: Number(item.dataset.id),
      token: Number(item.dataset.token),
      path: item.dataset.path,
      alt: item.dataset.alt,
    });
  });
  let nextToken = Number(editor.dataset.nextToken || 1);

  const button = (label, action, className = '') => {
    const element = document.createElement('button');
    element.type = 'button';
    element.textContent = label;
    element.dataset.blockAction = action;
    if (className) element.className = className;
    return element;
  };

  const resizeText = (textarea) => {
    textarea.style.height = 'auto';
    textarea.style.height = `${Math.max(112, textarea.scrollHeight)}px`;
  };

  const updateControls = () => {
    const blocks = [...list.children];
    blocks.forEach((block, index) => {
      block.querySelector('[data-block-action="up"]').disabled = index === 0;
      block.querySelector('[data-block-action="down"]').disabled = index === blocks.length - 1;
    });
  };

  const bindBlockActions = (block) => {
    block.querySelector('[data-block-action="up"]').addEventListener('click', () => {
      const previous = block.previousElementSibling;
      if (previous) list.insertBefore(block, previous);
      updateControls();
    });
    block.querySelector('[data-block-action="down"]').addEventListener('click', () => {
      const next = block.nextElementSibling;
      if (next) list.insertBefore(next, block);
      updateControls();
    });
    block.querySelector('[data-block-action="remove"]').addEventListener('click', () => {
      if (block.dataset.existingId) {
        const deleted = document.createElement('input');
        deleted.type = 'hidden';
        deleted.name = 'delete_images[]';
        deleted.value = block.dataset.existingId;
        deleteBin.append(deleted);
      }
      block.remove();
      if (!list.children.length) addTextBlock('');
      updateControls();
    });
  };

  const createShell = (type, title) => {
    const block = document.createElement('article');
    block.className = `admin-content-block admin-content-block-${type}`;
    block.dataset.blockType = type;
    const header = document.createElement('header');
    const heading = document.createElement('strong');
    heading.textContent = title;
    const actions = document.createElement('div');
    actions.className = 'admin-content-block-actions';
    actions.append(
      button('위로', 'up'),
      button('아래로', 'down'),
      button('삭제', 'remove', 'is-danger'),
    );
    header.append(heading, actions);
    block.append(header);
    bindBlockActions(block);
    return block;
  };

  const appendInsertControls = (block) => {
    const controls = document.createElement('div');
    controls.className = 'admin-content-insert-actions';
    const addText = document.createElement('button');
    addText.type = 'button';
    addText.textContent = '아래에 문단 추가';
    addText.addEventListener('click', () => {
      const added = addTextBlock('', block.nextElementSibling);
      added.querySelector('textarea').focus();
    });
    const addImage = document.createElement('button');
    addImage.type = 'button';
    addImage.textContent = '아래에 이미지 추가';
    addImage.addEventListener('click', () => chooseImage(block.nextElementSibling));
    controls.append(addText, addImage);
    block.append(controls);
  };

  const addTextBlock = (value, before = null) => {
    const block = createShell('text', '텍스트 문단');
    const textarea = document.createElement('textarea');
    textarea.rows = 4;
    textarea.value = value;
    textarea.placeholder = '본문 내용을 입력하세요.';
    textarea.setAttribute('aria-label', '본문 텍스트 문단');
    textarea.addEventListener('input', () => resizeText(textarea));
    block.append(textarea);
    appendInsertControls(block);
    list.insertBefore(block, before);
    requestAnimationFrame(() => resizeText(textarea));
    updateControls();
    return block;
  };

  const addImageBlock = ({ id = null, token, path, alt, fileInput = null }, before = null) => {
    const block = createShell('image', id ? '등록된 본문 이미지' : '새 본문 이미지');
    block.dataset.token = String(token);
    if (id) block.dataset.existingId = String(id);

    const preview = document.createElement('img');
    preview.src = path;
    preview.alt = '';
    const fields = document.createElement('div');
    fields.className = 'admin-content-image-fields';
    const label = document.createElement('label');
    label.textContent = '대체 텍스트';
    const altInput = document.createElement('input');
    altInput.name = id ? `media_alt[${id}]` : 'new_inline_alts[]';
    altInput.value = alt;
    altInput.maxLength = 255;
    altInput.required = true;
    label.append(altInput);
    fields.append(label);

    if (fileInput) {
      fileInput.name = 'inline_images[]';
      fileInput.className = 'admin-hidden-file';
      const tokenInput = document.createElement('input');
      tokenInput.type = 'hidden';
      tokenInput.name = 'new_inline_tokens[]';
      tokenInput.value = String(token);
      fields.append(fileInput, tokenInput);
    }
    block.append(preview, fields);
    appendInsertControls(block);
    list.insertBefore(block, before);
    updateControls();
    return block;
  };

  const imageCount = () => list.querySelectorAll('[data-block-type="image"]').length;
  const chooseImage = (before = null) => {
    if (imageCount() >= 10) {
      window.alert('본문 이미지는 최대 10장까지 등록할 수 있습니다.');
      return;
    }
    const input = document.createElement('input');
    input.type = 'file';
    input.accept = 'image/jpeg,image/png,image/webp';
    input.className = 'admin-hidden-file';
    input.addEventListener('change', () => {
      const file = input.files?.[0];
      if (!file) return;
      const title = document.querySelector('input[name="title"]')?.value.trim() || '게시글';
      addImageBlock({
        token: nextToken++,
        path: URL.createObjectURL(file),
        alt: `${title} - 본문 이미지`,
        fileInput: input,
      }, before?.isConnected ? before : null);
    }, { once: true });
    deleteBin.append(input);
    input.click();
  };

  const usedTokens = new Set();
  const initialBody = source.value.trim();
  const parts = initialBody ? initialBody.split(/\r?\n(?:[\t ]*\r?\n)+/) : [];
  parts.forEach((part) => {
    const match = part.trim().match(/^\[\[image:(\d+)\]\]$/);
    const media = match ? inventory.get(Number(match[1])) : null;
    if (media) {
      addImageBlock(media);
      usedTokens.add(media.token);
    } else {
      addTextBlock(part);
    }
  });
  inventory.forEach((media) => {
    if (!usedTokens.has(media.token)) addImageBlock(media);
  });
  if (!list.children.length) addTextBlock('');

  editor.querySelector('[data-add-text]').addEventListener('click', () => {
    const block = addTextBlock('');
    block.querySelector('textarea').focus();
  });
  editor.querySelector('[data-add-image]').addEventListener('click', () => chooseImage());

  source.required = false;
  sourceWrap.classList.add('is-enhanced');
  editor.classList.add('is-ready');
  source.closest('form').addEventListener('submit', () => {
    source.value = [...list.children].map((block) => {
      if (block.dataset.blockType === 'image') return `[[image:${block.dataset.token}]]`;
      return block.querySelector('textarea').value.trim();
    }).filter(Boolean).join('\n\n');
  });

  const previewDialog = document.querySelector('[data-live-preview]');
  const openPreview = document.querySelector('[data-open-live-preview]');
  const closePreview = previewDialog?.querySelector('[data-close-live-preview]');
  const renderPreview = () => {
    const previewTitle = previewDialog.querySelector('[data-preview-title]');
    const previewCategory = previewDialog.querySelector('[data-preview-category]');
    const previewAuthor = previewDialog.querySelector('[data-preview-author]');
    const previewBody = previewDialog.querySelector('[data-preview-body]');
    const previewGallery = previewDialog.querySelector('[data-preview-gallery]');
    const galleryMain = previewDialog.querySelector('[data-preview-gallery-main]');
    const galleryThumbs = previewDialog.querySelector('[data-preview-gallery-thumbs]');
    const galleryCount = previewDialog.querySelector('[data-preview-gallery-count]');

    previewTitle.textContent = document.querySelector('input[name="title"]')?.value.trim() || '제목 없는 글';
    previewCategory.textContent = document.querySelector('select[name="category"]')?.value || '';
    previewAuthor.textContent = `${document.querySelector('input[name="author"]')?.value.trim() || ''} 기술팀`;
    previewBody.replaceChildren();
    [...list.children].forEach((block) => {
      if (block.dataset.blockType === 'image') {
        const figure = document.createElement('figure');
        const image = document.createElement('img');
        image.src = block.querySelector('img').src;
        image.alt = block.querySelector('.admin-content-image-fields input')?.value.trim() || '';
        figure.append(image);
        previewBody.append(figure);
        return;
      }
      const value = block.querySelector('textarea').value.trim();
      if (!value) return;
      const paragraph = document.createElement('p');
      paragraph.textContent = value;
      previewBody.append(paragraph);
    });
    if (!previewBody.children.length) {
      const empty = document.createElement('p');
      empty.className = 'is-empty';
      empty.textContent = '본문 내용을 입력하면 여기에 표시됩니다.';
      previewBody.append(empty);
    }

    const galleryItems = [
      ...document.querySelectorAll('[data-media-upload="gallery"] .admin-media-item:not(.is-delete), [data-media-upload="gallery"] .admin-new-media-item'),
    ].map((item) => ({
      src: item.querySelector('img')?.src || '',
      alt: item.querySelector('input:not([type="checkbox"])')?.value.trim() || '',
    })).filter((item) => item.src);
    galleryMain.replaceChildren();
    galleryThumbs.replaceChildren();
    previewGallery.hidden = galleryItems.length === 0;
    if (galleryItems.length) {
      const mainImage = document.createElement('img');
      mainImage.src = galleryItems[0].src;
      mainImage.alt = galleryItems[0].alt;
      galleryMain.append(mainImage);
      galleryItems.forEach((item, index) => {
        const thumb = document.createElement('button');
        thumb.type = 'button';
        thumb.setAttribute('aria-label', `${index + 1}번째 대표 이미지 보기`);
        if (index === 0) thumb.classList.add('is-active');
        const image = document.createElement('img');
        image.src = item.src;
        image.alt = '';
        thumb.append(image);
        thumb.addEventListener('click', () => {
          mainImage.src = item.src;
          mainImage.alt = item.alt;
          [...galleryThumbs.children].forEach((child) => child.classList.toggle('is-active', child === thumb));
        });
        galleryThumbs.append(thumb);
      });
      galleryCount.textContent = `대표 이미지 ${galleryItems.length}장`;
    }
  };

  openPreview?.addEventListener('click', () => {
    renderPreview();
    previewDialog.showModal();
  });
  closePreview?.addEventListener('click', () => previewDialog.close());
  previewDialog?.addEventListener('click', (event) => {
    if (event.target === previewDialog) previewDialog.close();
  });
})();
