/**
 * Slide-in filter drawer with focus trap, scroll lock, and apply/reset/discard lifecycle.
 */
import { warnOnce, resolveHost } from '../core/app-dom.js';
import { createFocusTrap, createScrollLock } from '../core/app-focus-trap.js';

export function initFilterDrawer(options = {}) {
  const {
    root = document,
    drawerSelector = '[data-filter-drawer]',
    openSelector = '[data-filter-drawer-open]',
    closeSelector = '[data-filter-drawer-close]',
    applySelector = '[data-filter-drawer-apply]',
    resetSelector = '[data-filter-drawer-reset]',
    onOpen = null,
    onClose = null,
    onApply = null,
    onReset = null,
    onDiscard = null,
  } = options;

  const host = resolveHost(root);
  const drawer = host.querySelector(drawerSelector);
  if (!(drawer instanceof HTMLElement)) {
    warnOnce('UI_EL_MISSING', `Missing filter drawer: ${drawerSelector}`, { module: 'filter-drawer' });
    return null;
  }

  if (drawer.dataset.filterDrawerBound === '1' && drawer._filterDrawerApi) {
    return drawer._filterDrawerApi;
  }

  const openButtons = Array.from(host.querySelectorAll(openSelector));
  const closeButtons = Array.from(drawer.querySelectorAll(closeSelector));
  const applyButton = drawer.querySelector(applySelector);
  const resetButton = drawer.querySelector(resetSelector);
  const applyBaseLabel = applyButton ? String(applyButton.textContent || '').trim() : '';
  const openButtonBaseLabels = new WeakMap();
  const panel = drawer.querySelector('[data-filter-drawer-panel]') || drawer;
  const originalParent = drawer.parentNode;
  const originalNextSibling = drawer.nextSibling;

  const cleanupFns = [];
  const bind = (target, eventName, handler, bindOptions = undefined) => {
    target.addEventListener(eventName, handler, bindOptions);
    cleanupFns.push(() => target.removeEventListener(eventName, handler, bindOptions));
  };

  let isOpen = false;
  let lastTrigger = null;
  const focusTrap = createFocusTrap(panel);
  const scrollLock = createScrollLock();

  const ensureDrawerInBody = () => {
    if (!document.body || !drawer.isConnected || drawer.parentNode === document.body) {
      return;
    }
    document.body.appendChild(drawer);
  };

  const restoreDrawerPosition = () => {
    if (!(originalParent instanceof Node) || !drawer.isConnected) {
      return;
    }
    if (!originalParent.isConnected || drawer.parentNode === originalParent) {
      return;
    }
    if (originalNextSibling && originalNextSibling.parentNode === originalParent) {
      originalParent.insertBefore(drawer, originalNextSibling);
      return;
    }
    originalParent.appendChild(drawer);
  };

  ensureDrawerInBody();

  if (!drawer.hasAttribute('role')) {
    drawer.setAttribute('role', 'dialog');
  }
  if (!drawer.hasAttribute('aria-modal')) {
    drawer.setAttribute('aria-modal', 'true');
  }
  drawer.setAttribute('aria-hidden', drawer.hidden ? 'true' : 'false');
  if (!panel.hasAttribute('tabindex')) {
    panel.setAttribute('tabindex', '-1');
  }

  const lockPageScroll = () => scrollLock.lock();
  const unlockPageScroll = () => scrollLock.unlock();
  cleanupFns.push(() => focusTrap.destroy());

  const setOpen = (nextOpen) => {
    if (nextOpen) {
      ensureDrawerInBody();
    }
    isOpen = nextOpen;
    drawer.hidden = !nextOpen;
    drawer.setAttribute('aria-hidden', nextOpen ? 'false' : 'true');
    drawer.classList.toggle('is-open', nextOpen);
    document.body.classList.toggle('filter-drawer-open', nextOpen);

    if (nextOpen) {
      lockPageScroll();
      focusTrap.activate(lastTrigger);
    } else {
      focusTrap.deactivate();
      unlockPageScroll();
    }

    openButtons.forEach((button) => {
      button.setAttribute('aria-expanded', nextOpen ? 'true' : 'false');
    });

    if (!nextOpen) {
      lastTrigger = null;
      if (typeof onClose === 'function') {
        onClose();
      }
      return;
    }

    if (typeof onOpen === 'function') {
      onOpen();
    }
  };

  const normalizeForcedClose = () => {
    if (!isOpen) {
      return;
    }
    isOpen = false;
    focusTrap.deactivate();
    unlockPageScroll();
    document.body.classList.remove('filter-drawer-open');
    openButtons.forEach((button) => {
      button.setAttribute('aria-expanded', 'false');
    });
    if (typeof onClose === 'function') {
      onClose();
    }
  };

  const open = (trigger = null) => {
    if (isOpen) {
      return;
    }
    lastTrigger = trigger && typeof trigger.focus === 'function'
      ? trigger
      : (document.activeElement instanceof HTMLElement ? document.activeElement : null);
    setOpen(true);
  };

  const close = (mode = 'discard') => {
    if (!isOpen) {
      return;
    }
    if (mode === 'discard' && typeof onDiscard === 'function') {
      onDiscard();
    }
    setOpen(false);
  };

  openButtons.forEach((button) => {
    bind(button, 'click', (event) => {
      event.preventDefault();
      open(button);
    });
  });

  closeButtons.forEach((button) => {
    bind(button, 'click', (event) => {
      event.preventDefault();
      close('discard');
    });
  });

  if (applyButton) {
    bind(applyButton, 'click', async (event) => {
      event.preventDefault();
      if (applyButton.disabled) {
        return;
      }
      let shouldClose = true;
      if (typeof onApply === 'function') {
        const result = await onApply();
        shouldClose = result !== false;
      }
      if (shouldClose) {
        close('apply');
      }
    });
  }

  if (resetButton) {
    bind(resetButton, 'click', async (event) => {
      event.preventDefault();
      if (typeof onReset === 'function') {
        await onReset();
      }
    });
  }

  bind(drawer, 'click', (event) => {
    if (!isOpen) {
      return;
    }
    if (!panel.contains(event.target)) {
      close('discard');
    }
  });

  const onKeyDown = (event) => {
    if (!isOpen) {
      return;
    }
    if (event.key === 'Escape') {
      event.preventDefault();
      close('discard');
    }
  };
  bind(document, 'keydown', onKeyDown);

  const documentObserver = new MutationObserver(() => {
    if (!drawer.isConnected || drawer.hidden) {
      normalizeForcedClose();
    }
  });
  if (document.body) {
    documentObserver.observe(document.body, { childList: true, subtree: true });
    cleanupFns.push(() => documentObserver.disconnect());
  }
  const drawerAttributeObserver = new MutationObserver(() => {
    if (drawer.hidden) {
      normalizeForcedClose();
    }
  });
  drawerAttributeObserver.observe(drawer, { attributes: true, attributeFilter: ['hidden'] });
  cleanupFns.push(() => drawerAttributeObserver.disconnect());

  const setApplyEnabled = (enabled) => {
    if (!applyButton) {
      return;
    }
    const nextEnabled = enabled === true;
    applyButton.disabled = !nextEnabled;
    applyButton.setAttribute('aria-disabled', nextEnabled ? 'false' : 'true');
  };

  const setApplyCount = (count) => {
    if (!applyButton) {
      return;
    }
    const parsed = Number.parseInt(String(count ?? '0'), 10);
    const normalized = Number.isFinite(parsed) && parsed > 0 ? parsed : 0;
    applyButton.textContent = normalized > 0
      ? `${applyBaseLabel} (${normalized})`
      : applyBaseLabel;
  };

  const setTriggerCount = (count) => {
    const parsed = Number.parseInt(String(count ?? '0'), 10);
    const normalized = Number.isFinite(parsed) && parsed > 0 ? parsed : 0;

    openButtons.forEach((button) => {
      const baseLabel = openButtonBaseLabels.get(button)
        || String(button.getAttribute('aria-label') || button.textContent || '').trim();

      if (!baseLabel) {
        return;
      }
      if (!openButtonBaseLabels.has(button)) {
        openButtonBaseLabels.set(button, baseLabel);
      }

      const nextLabel = normalized > 0 ? `${baseLabel} (${normalized})` : baseLabel;
      const icon = button.querySelector('i');
      if (icon) {
        while (icon.nextSibling) {
          icon.parentNode?.removeChild(icon.nextSibling);
        }
        icon.insertAdjacentText('afterend', ` ${nextLabel}`);
      } else {
        button.textContent = nextLabel;
      }
      button.setAttribute('aria-label', nextLabel);
      button.setAttribute('data-tooltip', nextLabel);
    });
  };

  setApplyEnabled(false);
  setApplyCount(0);
  setTriggerCount(0);

  const destroy = () => {
    cleanupFns.forEach((cleanup) => cleanup());
    cleanupFns.length = 0;
    if (isOpen) {
      close('discard');
    }
    unlockPageScroll();
    document.body.classList.remove('filter-drawer-open');
    restoreDrawerPosition();
    delete drawer.dataset.filterDrawerBound;
    delete drawer._filterDrawerApi;
  };

  const api = {
    open,
    close,
    isOpen: () => isOpen,
    drawer,
    setApplyEnabled,
    setApplyCount,
    setTriggerCount,
    destroy,
  };

  drawer.dataset.filterDrawerBound = '1';
  drawer._filterDrawerApi = api;
  return api;
}
