/**
 * Aside panel switcher — opens/closes named sidebar panels.
 */
import { warnOnce, resolveHost } from '../core/app-dom.js';
import { isEditableTarget } from '../core/app-form-utils.js';
import { initPersistedDetailsGroup } from '../core/app-details-open-state.js';
import { createUiStorage } from '../core/app-ui-storage.js';
import { bindAsidePanelChannel, requestSidebarAction } from '../core/app-ui-channels.js';

export function initAsidePanels(root = document, options = {}) {
  const {
    barSelector = '.aside-icon-bar',
    panelSelector = '.app-sidebar-panel',
    titleSelector = '.app-sidebar-title',
    toolsSelector = '[data-aside-tools]',
    revealSidebarOnActivate = true,
    persistSidebarStateOnActivate = true,
    storageNamespace = 'app-ui',
    storageVersion = 'v1',
    storageScope = 'aside-panels',
    detailsStorageScope = 'aside-details',
  } = options;

  const host = resolveHost(root);
  const bar = host.matches?.(barSelector)
    ? host
    : host.querySelector(barSelector);
  if (!(bar instanceof HTMLElement)) {
    warnOnce('UI_EL_MISSING', `Missing aside bar: ${barSelector}`, { module: 'aside-panels' });
    return { destroy: () => {} };
  }
  if (bar.dataset.asidePanelsBound === '1' && bar._asidePanelsApi) {
    return bar._asidePanelsApi;
  }

  const tabs = Array.from(bar.querySelectorAll('[data-aside-target]'));
  if (!tabs.length) {
    warnOnce('UI_EL_MISSING', 'No aside tabs found', { module: 'aside-panels' });
    return { destroy: () => {} };
  }
  const shortcutItems = Array.from(bar.querySelectorAll('[data-aside-target], [data-aside-shortcut]'));
  const panels = Array.from(host.querySelectorAll(panelSelector));
  if (!panels.length) {
    warnOnce('UI_EL_MISSING', 'No aside panels found', { module: 'aside-panels' });
  }

  const titleEl = host.querySelector(titleSelector);
  const toolsHost = host.querySelector(toolsSelector);
  const defaultTitle = titleEl?.dataset.asideTitleDefault || titleEl?.textContent || '';
  const storageKey = bar.dataset.asideStorage || '';
  const storage = createUiStorage({
    namespace: storageNamespace,
    version: storageVersion,
    scope: storageScope,
  });
  const scopedStorageKey = storage.buildKey('state', storageKey);
  const isMac = /(Mac|iPhone|iPad|iPod)/i.test(navigator.platform || navigator.userAgent);
  const shortcutPrefix = isMac ? '⌘' : 'Ctrl+';
  const panelDetailsRegistry = new WeakMap();
  const panelDetailsInstances = new Set();
  const rootEl = document.documentElement;

  const getPanelKey = (panel) => panel?.dataset?.asidePanel || '';
  const getTabKey = (tab) => tab?.dataset?.asideTarget || '';
  const getPanelTools = (panel) => panel?.querySelector('[data-aside-panel-tools]') || null;
  const getTabHref = (tab) => tab?.dataset?.asideHref || '';
  const actionMenus = () => Array.from(bar.querySelectorAll('[data-aside-target], [data-aside-shortcut]'));

  const findActiveDetailsKeys = (panel) => Array.from(panel.querySelectorAll('details[data-details-key]'))
    .filter((details) => details.querySelector('a.active, a[aria-current="page"]'))
    .map((details) => details.dataset.detailsKey || '')
    .filter(Boolean);

  const initPanelDetails = (panel) => {
    if (!(panel instanceof HTMLElement)) {
      return;
    }
    const existing = panelDetailsRegistry.get(panel);
    if (existing) {
      existing.apply();
      return;
    }
    const panelStorageKey = panel.dataset.asideDetailsStorage || '';
    if (!panelStorageKey) {
      return;
    }
    const openActive = panel.dataset.asideDetailsOpenActive === '1';
    const detailsState = initPersistedDetailsGroup({
      root: panel,
      storageKey: panelStorageKey,
      ensureOpenKeys: openActive ? () => findActiveDetailsKeys(panel) : [],
      storageNamespace,
      storageVersion,
      storageScope: detailsStorageScope,
    });
    if (detailsState) {
      panelDetailsRegistry.set(panel, detailsState);
      panelDetailsInstances.add(detailsState);
    }
  };

  const readStored = () => {
    if (!scopedStorageKey) {
      return null;
    }
    return storage.getItem(scopedStorageKey);
  };

  const writeStored = (key) => {
    if (!scopedStorageKey) {
      return;
    }
    storage.setItem(scopedStorageKey, key);
  };

  const syncTools = (panel) => {
    if (!(toolsHost instanceof HTMLElement)) {
      return;
    }
    toolsHost.innerHTML = '';
    const tools = getPanelTools(panel);
    if (!(tools instanceof HTMLElement)) {
      return;
    }
    toolsHost.innerHTML = tools.innerHTML;
  };

  const isSidebarHidden = () => rootEl.classList.contains('sidebar-hidden');
  const isSidebarCollapsed = () => rootEl.classList.contains('sidebar-collapsed');

  const openSidebar = (persist) => {
    if (!revealSidebarOnActivate) {
      return;
    }
    if (isSidebarHidden()) {
      requestSidebarAction('show', { persist });
    }
    if (isSidebarCollapsed()) {
      requestSidebarAction('open', { persist });
    }
  };

  const setActive = (key, { fromUser = false } = {}) => {
    if (!key) {
      return;
    }

    let activePanel = null;
    panels.forEach((panel) => {
      const isActive = getPanelKey(panel) === key;
      if (isActive) {
        activePanel = panel;
      }
      panel.hidden = !isActive;
      panel.setAttribute('aria-hidden', isActive ? 'false' : 'true');
    });

    tabs.forEach((tab) => {
      const isActive = getTabKey(tab) === key;
      tab.classList.toggle('active', isActive);
      tab.setAttribute('aria-selected', isActive ? 'true' : 'false');
      tab.setAttribute('tabindex', isActive ? '0' : '-1');
    });

    if (titleEl instanceof HTMLElement) {
      const nextTitle = activePanel?.dataset?.asideTitle || defaultTitle;
      if (nextTitle) {
        titleEl.textContent = nextTitle;
      }
    }
    if (activePanel instanceof HTMLElement) {
      syncTools(activePanel);
      initPanelDetails(activePanel);
    }
    writeStored(key);
    if (fromUser) {
      openSidebar(persistSidebarStateOnActivate);
    }
  };

  const getInitialKey = () => {
    const stored = readStored();
    if (stored && panels.some((panel) => getPanelKey(panel) === stored)) {
      return stored;
    }
    const activeTab = tabs.find((tab) => tab.classList.contains('active'));
    if (activeTab) {
      return getTabKey(activeTab);
    }
    const visiblePanel = panels.find((panel) => !panel.hidden);
    if (visiblePanel) {
      return getPanelKey(visiblePanel);
    }
    return getTabKey(tabs[0]);
  };

  setActive(getInitialKey(), { fromUser: false });
  document.documentElement.classList.remove('aside-pending');

  const cleanupFns = [];
  const originalTooltips = new Map();
  shortcutItems.forEach((item, idx) => {
    const base = item.dataset.tooltipBase || item.getAttribute('data-tooltip') || item.getAttribute('aria-label') || '';
    if (!base) {
      return;
    }
    const shortcutKey = idx === 9 ? '0' : String(idx + 1);
    item.dataset.tooltipBase = base;
    originalTooltips.set(item, item.getAttribute('data-tooltip') || '');
    item.setAttribute('data-tooltip', `${base} (${shortcutPrefix}${shortcutKey})`);
  });

  tabs.forEach((tab) => {
    const onClick = (event) => {
      event.preventDefault();
      const key = getTabKey(tab);
      const isActive = tab.classList.contains('active');
      const href = getTabHref(tab);

      if (href) {
        const base = document.baseURI || window.location.origin;
        const targetUrl = new URL(href, base);
        const currentUrl = new URL(window.location.href);
        const isSame = targetUrl.pathname === currentUrl.pathname && targetUrl.search === currentUrl.search;
        if (!isSame) {
          setActive(key, { fromUser: true });
          window.location.href = targetUrl.toString();
          return;
        }
      }

      if (isSidebarCollapsed()) {
        requestSidebarAction('open', { persist: persistSidebarStateOnActivate });
        setActive(key, { fromUser: true });
        return;
      }

      if (isActive) {
        requestSidebarAction(isSidebarHidden() ? 'show' : 'hide', { persist: true });
        return;
      }
      setActive(key, { fromUser: true });
    };
    tab.addEventListener('click', onClick);
    cleanupFns.push(() => tab.removeEventListener('click', onClick));
  });

  const onKeyDown = (event) => {
    if (!(event.metaKey || event.ctrlKey)) {
      return;
    }
    if (event.altKey) {
      return;
    }
    if (isEditableTarget(event.target)) {
      return;
    }
    const key = event.key;
    if (!/^[0-9]$/.test(key)) {
      return;
    }
    const index = key === '0' ? 9 : (Number.parseInt(key, 10) - 1);
    if (index < 0 || index >= actionMenus().length) {
      return;
    }
    event.preventDefault();
    actionMenus()[index].click();
  };
  document.addEventListener('keydown', onKeyDown);
  cleanupFns.push(() => document.removeEventListener('keydown', onKeyDown));

  cleanupFns.push(bindAsidePanelChannel((detail) => {
    const action = String(detail?.action || '').trim();
    const key = String(detail?.panel || '').trim();
    if (action !== 'open' || key === '') {
      return;
    }
    if (!tabs.some((tab) => getTabKey(tab) === key)) {
      return;
    }
    setActive(key, { fromUser: detail?.fromUser !== false });
  }));

  const api = {
    setActive,
    open: (key) => setActive(key, { fromUser: true }),
    destroy: () => {
      cleanupFns.forEach((cleanup) => cleanup());
      originalTooltips.forEach((tooltip, item) => {
        if (tooltip) {
          item.setAttribute('data-tooltip', tooltip);
        } else {
          item.removeAttribute('data-tooltip');
        }
      });
      panelDetailsInstances.forEach((detailsState) => {
        if (detailsState && typeof detailsState.destroy === 'function') {
          detailsState.destroy();
        }
      });
      panelDetailsInstances.clear();
      delete bar.dataset.asidePanelsBound;
      delete bar._asidePanelsApi;
    },
  };

  bar.dataset.asidePanelsBound = '1';
  bar._asidePanelsApi = api;
  return api;
}
