import {
  getDeviceId,
  getFullCategories,
  getFilter,
  setFilter,
  setCustomizeMode,
  isCustomizeMode,
  getSavedPresets,
  savePreset,
  deletePreset,
} from '../devices/registry.js';

let refreshToolboxFn = () => {};
let panelEl, treeEl, presetSelect, presetNameInput, btnDone;

export function initToolboxCustomizer(refreshCb) {
  refreshToolboxFn = refreshCb;
  panelEl = document.getElementById('customizer-panel');
  treeEl = document.getElementById('customizer-tree');
  presetSelect = document.getElementById('preset-select');
  presetNameInput = document.getElementById('preset-name');
  btnDone = document.getElementById('customizer-done');

  btnDone.addEventListener('click', exitCustomizeMode);
  document.getElementById('preset-load').addEventListener('click', loadSelectedPreset);
  document.getElementById('preset-save').addEventListener('click', saveCurrentAsPreset);
  document.getElementById('preset-delete').addEventListener('click', deleteSelectedPreset);
  document.getElementById('preset-show-all').addEventListener('click', showAll);
  document.getElementById('preset-hide-all').addEventListener('click', hideAll);
}

export function toggleCustomizeMode() {
  if (isCustomizeMode()) exitCustomizeMode();
  else enterCustomizeMode();
}

export function refreshCustomizer() {
  if (isCustomizeMode()) {
    renderTree();
    renderPresetDropdown();
  }
}

function enterCustomizeMode() {
  setCustomizeMode(true);
  refreshToolboxFn();
  renderTree();
  renderPresetDropdown();
  panelEl.classList.remove('hidden');
  document.getElementById('btn-customize').classList.add('active');
  window.dispatchEvent(new Event('resize'));
}

function exitCustomizeMode() {
  setCustomizeMode(false);
  panelEl.classList.add('hidden');
  document.getElementById('btn-customize').classList.remove('active');
  refreshToolboxFn();
  window.dispatchEvent(new Event('resize'));
}

// ─── Filter helpers ──────────────────────────────────────

function currentFilter() {
  const f = getFilter(getDeviceId());
  return {
    hiddenCategories: new Set(f.hiddenCategories || []),
    hiddenBlocks: new Set(f.hiddenBlocks || []),
  };
}

function saveFilter(hiddenCategories, hiddenBlocks) {
  setFilter(getDeviceId(), {
    hiddenCategories: [...hiddenCategories],
    hiddenBlocks: [...hiddenBlocks],
  });
}

// ─── Preset actions ──────────────────────────────────────

function renderPresetDropdown() {
  const presets = getSavedPresets();
  presetSelect.innerHTML = '<option value="">— select preset —</option>';
  for (const p of presets) {
    const opt = document.createElement('option');
    opt.value = p.name;
    opt.textContent = p.builtin ? `${p.name}` : p.name;
    if (p.builtin) opt.style.fontWeight = 'bold';
    presetSelect.appendChild(opt);
  }
}

function loadSelectedPreset() {
  const name = presetSelect.value;
  if (!name) return;
  const presets = getSavedPresets();
  const preset = presets.find(p => p.name === name);
  if (!preset) return;
  setFilter(getDeviceId(), preset.filter);
  renderTree();
}

function saveCurrentAsPreset() {
  const name = presetNameInput.value.trim();
  if (!name) { presetNameInput.focus(); return; }
  const presets = getSavedPresets();
  if (presets.find(p => p.name === name && p.builtin)) return;
  const f = getFilter(getDeviceId());
  savePreset(name, f);
  presetNameInput.value = '';
  renderPresetDropdown();
  presetSelect.value = name;
}

function deleteSelectedPreset() {
  const name = presetSelect.value;
  if (!name) return;
  const presets = getSavedPresets();
  const preset = presets.find(p => p.name === name);
  if (preset && preset.builtin) return;
  deletePreset(name);
  renderPresetDropdown();
}

function showAll() {
  saveFilter(new Set(), new Set());
  renderTree();
}

function hideAll() {
  const cats = getFullCategories(getDeviceId());
  const hiddenCats = new Set();
  const hiddenBlocks = new Set();
  for (const cat of cats) {
    hiddenCats.add(cat.name);
    if (cat.contents) {
      for (const b of cat.contents) {
        if (b.type) hiddenBlocks.add(b.type);
      }
    }
  }
  saveFilter(hiddenCats, hiddenBlocks);
  renderTree();
}

// ─── Tree rendering ──────────────────────────────────────

function renderTree() {
  const cats = getFullCategories(getDeviceId());
  const { hiddenCategories, hiddenBlocks } = currentFilter();
  treeEl.innerHTML = '';

  for (const cat of cats) {
    const catHidden = hiddenCategories.has(cat.name);

    // Category row
    const row = document.createElement('div');
    row.className = 'cust-cat' + (catHidden ? ' cust-dimmed' : '');

    const catCb = document.createElement('input');
    catCb.type = 'checkbox';
    catCb.checked = !catHidden;
    catCb.className = 'cust-cb';

    const swatch = document.createElement('span');
    swatch.className = 'cust-swatch';
    if (cat.colour) {
      swatch.style.background = `hsl(${cat.colour}, 60%, 50%)`;
    } else {
      swatch.style.background = 'var(--text-muted)';
    }

    const label = document.createElement('span');
    label.className = 'cust-cat-label';
    label.textContent = cat.name;

    const hasBlocks = cat.contents && cat.contents.length > 0;

    const toggle = document.createElement('button');
    toggle.className = 'cust-expand';
    toggle.innerHTML = '&#9656;';
    toggle.title = 'Expand blocks';

    row.appendChild(catCb);
    row.appendChild(swatch);
    row.appendChild(label);
    if (hasBlocks) row.appendChild(toggle);
    treeEl.appendChild(row);

    // Block list (collapsed by default)
    const blockList = document.createElement('div');
    blockList.className = 'cust-blocks hidden';

    if (hasBlocks) {
      for (const block of cat.contents) {
        if (!block.type) continue;

        const bRow = document.createElement('div');
        const bHidden = catHidden || hiddenBlocks.has(block.type);
        bRow.className = 'cust-block-row' + (bHidden ? ' cust-dimmed' : '');

        const bCb = document.createElement('input');
        bCb.type = 'checkbox';
        bCb.checked = !catHidden && !hiddenBlocks.has(block.type);
        bCb.disabled = catHidden;
        bCb.className = 'cust-cb';

        const bLabel = document.createElement('span');
        bLabel.className = 'cust-block-label';
        bLabel.textContent = block.type.replace(/_/g, ' ');

        bRow.appendChild(bCb);
        bRow.appendChild(bLabel);
        blockList.appendChild(bRow);

        bCb.addEventListener('change', () => {
          const f = currentFilter();
          if (bCb.checked) {
            f.hiddenBlocks.delete(block.type);
          } else {
            f.hiddenBlocks.add(block.type);
          }
          saveFilter(f.hiddenCategories, f.hiddenBlocks);
          bRow.classList.toggle('cust-dimmed', !bCb.checked);
        });
      }
    }
    treeEl.appendChild(blockList);

    // Expand toggle
    if (hasBlocks) {
      const toggleExpanded = () => {
        blockList.classList.toggle('hidden');
        toggle.innerHTML = blockList.classList.contains('hidden') ? '&#9656;' : '&#9662;';
      };

      toggle.addEventListener('click', (event) => {
        event.stopPropagation();
        toggleExpanded();
      });

      row.addEventListener('click', (event) => {
        if (event.target instanceof Element && event.target.closest('.cust-cb')) return;
        toggleExpanded();
      });
    }

    // Category checkbox
    catCb.addEventListener('change', () => {
      const f = currentFilter();
      if (catCb.checked) {
        f.hiddenCategories.delete(cat.name);
      } else {
        f.hiddenCategories.add(cat.name);
      }
      saveFilter(f.hiddenCategories, f.hiddenBlocks);
      row.classList.toggle('cust-dimmed', !catCb.checked);

      const childCbs = blockList.querySelectorAll('.cust-cb');
      childCbs.forEach(cb => {
        cb.disabled = !catCb.checked;
        if (!catCb.checked) {
          cb.checked = false;
          cb.closest('.cust-block-row')?.classList.add('cust-dimmed');
        } else {
          const type = cb.closest('.cust-block-row')
            ?.querySelector('.cust-block-label')?.textContent.replace(/ /g, '_');
          const isHidden = f.hiddenBlocks.has(type);
          cb.checked = !isHidden;
          cb.closest('.cust-block-row')?.classList.toggle('cust-dimmed', isHidden);
        }
      });
    });
  }
}
