import { openCardModal } from 'ect/card-modal';
import { installStatsTooltip } from 'ect/stats-tooltip';
import { comboInputs, filterComboOptions } from './multi-combo.js';
import { clearViewportPanel, createActivationTracker, observeViewport, positionViewportPanel } from 'ect/viewport-ui';

const filterForm = document.querySelector('[data-meta-filter-form]');
const multiCombos = [...document.querySelectorAll('[data-meta-multi]')];
const cardFilterForms = [...document.querySelectorAll('[data-meta-card-filter-form]')];
const cardUpdateStatus = document.querySelector('[data-meta-card-update-status]');
const windowSelect = filterForm?.querySelector('[data-meta-window]');

function fitComboPanel(combo) {
  const panel = combo?.querySelector('.multi-combo-panel');
  const summary = combo?.querySelector('summary');
  if (!panel || !summary) return;
  if (!combo.open) { clearViewportPanel(panel); return; }
  positionViewportPanel(panel, summary);
}

function updateComboSummary(combo) {
  const inputs = comboInputs(combo);
  const selected = inputs.filter((input) => input.checked);
  const summary = combo.querySelector('[data-multi-summary]');
  if (!summary) return;
  if (!selected.length) {
    summary.textContent = combo.dataset.placeholder || 'Any';
    return;
  }
  if (selected.length === 1) {
    const label = selected[0].closest('label')?.querySelector('[data-option-label]');
    if (label?.querySelector('.mana-option-label,.card-type-line')) summary.innerHTML = label.innerHTML;
    else summary.textContent = label?.dataset.optionLabel || label?.textContent?.trim() || selected[0].value;
    return;
  }
  summary.textContent = selected.length === inputs.length ? `All ${selected.length} selected` : `${selected.length} selected`;
}

multiCombos.forEach((combo) => {
  const activation = createActivationTracker(combo.querySelector('summary'));
  updateComboSummary(combo);
  combo.querySelector('[data-multi-select-all]')?.addEventListener('click', () => {
    comboInputs(combo).filter((input) => !input.closest('label')?.hidden).forEach((input) => { input.checked = true; });
    updateComboSummary(combo);
  });
  combo.querySelector('[data-multi-clear]')?.addEventListener('click', () => {
    comboInputs(combo).forEach((input) => { input.checked = false; });
    updateComboSummary(combo);
  });
  combo.querySelector('[data-multi-search]')?.addEventListener('input', (event) => filterComboOptions(combo, event.target.value));
  combo.addEventListener('change', () => updateComboSummary(combo));
  combo.addEventListener('toggle', () => {
    if (!combo.open) { fitComboPanel(combo); return; }
    multiCombos.forEach((candidate) => { if (candidate !== combo) candidate.open = false; });
    requestAnimationFrame(() => {
      fitComboPanel(combo);
      if (activation.isKeyboard()) combo.querySelector('[data-multi-search]')?.focus({ preventScroll: true });
    });
  });
});

observeViewport(() => multiCombos.filter((combo) => combo.open).forEach(fitComboPanel));

document.addEventListener('click', (event) => {
  if (!event.target.closest('[data-meta-multi]')) multiCombos.forEach((combo) => { combo.open = false; });
});

function updateCustomDates() {
  const custom = windowSelect?.value === 'custom';
  filterForm?.querySelector('.meta-filter-grid')?.classList.toggle('is-custom-date-range', custom);
  filterForm?.querySelectorAll('[data-meta-custom-date]').forEach((field) => { field.hidden = !custom; });
  if (!custom) filterForm?.querySelectorAll('[data-meta-custom-date] input').forEach((input) => { input.value = ''; });
}
windowSelect?.addEventListener('change', updateCustomDates);
updateCustomDates();

document.querySelectorAll('[data-meta-list-expand]').forEach((button) => {
  const label = button.textContent;
  button.addEventListener('click', () => {
    const card = button.closest('.stats-graphic-card');
    if (!card) return;
    const expanded = card.classList.toggle('is-list-expanded');
    button.textContent = expanded ? 'Show fewer' : label;
    button.setAttribute('aria-expanded', String(expanded));
  });
});

let grid = document.querySelector('[data-meta-card-grid]');
let expandButton = document.querySelector('[data-meta-expand]');
let cardsExpanded = false;
function cardColumns() {
  if (!grid) return 1;
  const value = getComputedStyle(grid).gridTemplateColumns.trim();
  return Math.max(1, value ? value.split(/\s+/).length : 1);
}
function layoutCards() {
  if (!grid || !expandButton) return;
  const cards = [...grid.children];
  const visible = Math.min(cards.length, cardColumns() * 2);
  cards.forEach((card, index) => { card.dataset.metaCollapsed = !cardsExpanded && index >= visible ? '1' : '0'; });
  expandButton.hidden = cards.length <= visible;
  expandButton.textContent = cardsExpanded ? 'Show fewer' : `View all ${cards.length} cards`;
  expandButton.setAttribute('aria-expanded', String(cardsExpanded));
}
function bindCardExpansion() {
  grid = document.querySelector('[data-meta-card-grid]');
  expandButton = document.querySelector('[data-meta-expand]');
  cardsExpanded = false;
  expandButton?.addEventListener('click', () => { cardsExpanded = !cardsExpanded; layoutCards(); });
  layoutCards();
}
let resizeFrame = 0;
window.addEventListener('resize', () => {
  cancelAnimationFrame(resizeFrame);
  resizeFrame = requestAnimationFrame(() => {
    layoutCards();
    multiCombos.filter((combo) => combo.open).forEach(fitComboPanel);
  });
});
bindCardExpansion();

const metaApp = document.querySelector('#meta-app');
const cardSizeButtons = [...document.querySelectorAll('[data-meta-card-size]')];
function setCardSize(size) {
  if (!metaApp || !['small', 'medium', 'large'].includes(size)) return;
  metaApp.dataset.metaCardSize = size;
  cardSizeButtons.forEach((button) => button.setAttribute('aria-pressed', String(button.dataset.metaCardSize === size)));
  try { localStorage.setItem('ectmtg.cardSize', size); } catch {}
  requestAnimationFrame(layoutCards);
}
cardSizeButtons.forEach((button) => button.addEventListener('click', () => setCardSize(button.dataset.metaCardSize || 'medium')));
let preferredCardSize = window.ECTMTG_USER?.cardSize || 'medium';
try { preferredCardSize = localStorage.getItem('ectmtg.cardSize') || preferredCardSize; } catch {}
setCardSize(preferredCardSize);

const categorySizeButtons = [...document.querySelectorAll('[data-meta-category-size]')];
function setCategorySize(size) {
  if (!metaApp || !['small', 'medium', 'large'].includes(size)) return;
  metaApp.dataset.metaCategorySize = size;
  categorySizeButtons.forEach((button) => button.setAttribute('aria-pressed', String(button.dataset.metaCategorySize === size)));
  try { localStorage.setItem('ectmtg.metaCategoryCardSize', size); } catch {}
}
categorySizeButtons.forEach((button) => button.addEventListener('click', () => setCategorySize(button.dataset.metaCategorySize || 'medium')));
let preferredCategorySize = 'medium';
try { preferredCategorySize = localStorage.getItem('ectmtg.metaCategoryCardSize') || preferredCategorySize; } catch {}
setCategorySize(preferredCategorySize);

const statsTooltip = installStatsTooltip();
statsTooltip.refresh();

const cardFilterNames = ['cardTypeConfigured', 'cardZone', 'cardColor[]', 'cardColorMatch', 'cardType[]', 'cardSort'];
function syncCardFilterForm(source, target) {
  const data = new FormData(source);
  const sourceNames = new Set(Array.from(source.elements, (control) => control.name).filter(Boolean));
  Array.from(target.elements).forEach((control) => {
    if (!control.name || !sourceNames.has(control.name)) return;
    const values = data.getAll(control.name).map(String);
    if (control instanceof HTMLInputElement && ['checkbox', 'radio'].includes(control.type)) {
      control.checked = values.includes(control.value);
      return;
    }
    if (control instanceof HTMLSelectElement && control.multiple) {
      Array.from(control.options).forEach((option) => { option.selected = values.includes(option.value); });
      return;
    }
    control.value = values[0] || '';
  });
  target.querySelectorAll('[data-meta-multi]').forEach(updateComboSummary);
}
function syncPrimaryCardState(source) {
  if (!filterForm) return;
  const data = new FormData(source);
  filterForm.querySelectorAll('[data-meta-card-state]').forEach((input) => input.remove());
  cardFilterNames.forEach((name) => {
    data.getAll(name).forEach((value) => {
      if (typeof value !== 'string') return;
      const input = document.createElement('input');
      input.type = 'hidden';
      input.name = name;
      input.value = value;
      input.dataset.metaCardState = '';
      filterForm.append(input);
    });
  });
}
function setCardFiltersBusy(busy) {
  cardFilterForms.forEach((form) => {
    form.setAttribute('aria-busy', String(busy));
    const button = form.querySelector('button[type="submit"]');
    if (!button) return;
    if (busy) button.dataset.idleLabel = button.textContent || 'Update cards';
    button.disabled = busy;
    button.textContent = busy ? 'Updating…' : (button.dataset.idleLabel || 'Update cards');
  });
}
async function updateCardResults(form) {
  const anchorTop = form.getBoundingClientRect().top;
  cardFilterForms.forEach((target) => syncCardFilterForm(form, target));
  syncPrimaryCardState(form);
  multiCombos.forEach((combo) => { combo.open = false; });
  const url = new URL(form.action, window.location.href);
  url.search = new URLSearchParams(new FormData(form)).toString();
  setCardFiltersBusy(true);
  if (cardUpdateStatus) cardUpdateStatus.textContent = 'Updating card results.';
  try {
    const response = await fetch(url, { headers: { Accept: 'text/html', 'X-Requested-With': 'XMLHttpRequest' } });
    if (!response.ok) throw new Error(`Card results could not be updated (${response.status}).`);
    const nextDocument = new DOMParser().parseFromString(await response.text(), 'text/html');
    const selectors = ['.meta-category-panel', '.meta-card-usage-panel'];
    if (selectors.some((selector) => !nextDocument.querySelector(selector))) throw new Error('The updated card results were incomplete.');
    statsTooltip.close();
    selectors.forEach((selector) => {
      const current = document.querySelector(selector);
      const incoming = nextDocument.querySelector(selector);
      if (current && incoming) current.innerHTML = incoming.innerHTML;
    });
    const currentZone = document.querySelector('.meta-zone-chip');
    const incomingZone = nextDocument.querySelector('.meta-zone-chip');
    if (currentZone && incomingZone) currentZone.textContent = incomingZone.textContent;
    bindCardExpansion();
    statsTooltip.refresh();
    const historyUrl = new URL(url);
    historyUrl.hash = window.location.hash;
    window.history.replaceState(window.history.state, '', historyUrl.href);
    if (cardUpdateStatus) cardUpdateStatus.textContent = 'Card results updated.';
    requestAnimationFrame(() => {
      const delta = form.getBoundingClientRect().top - anchorTop;
      if (Math.abs(delta) > 0.5) window.scrollBy(0, delta);
    });
  } catch (error) {
    if (cardUpdateStatus) cardUpdateStatus.textContent = error?.message || 'Card results could not be updated.';
  } finally {
    setCardFiltersBusy(false);
  }
}
cardFilterForms.forEach((form) => form.addEventListener('submit', (event) => {
  event.preventDefault();
  void updateCardResults(form);
}));

const sectionLinks = [...document.querySelectorAll('.meta-section-nav a[href^="#"]')];
const sections = sectionLinks.map((link) => document.querySelector(link.getAttribute('href'))).filter(Boolean);
function activateSection(id) {
  sectionLinks.forEach((link) => {
    if (link.getAttribute('href') === `#${id}`) link.setAttribute('aria-current', 'true');
    else link.removeAttribute('aria-current');
  });
}
sectionLinks.forEach((link) => link.addEventListener('click', () => activateSection(link.hash.slice(1))));
if ('IntersectionObserver' in window && sections.length) {
  const visible = new Map();
  const observer = new IntersectionObserver((entries) => {
    entries.forEach((entry) => { if (entry.isIntersecting) visible.set(entry.target.id, entry.boundingClientRect.top); else visible.delete(entry.target.id); });
    const active = [...visible.entries()].sort((a, b) => Math.abs(a[1]) - Math.abs(b[1]))[0];
    if (active) activateSection(active[0]);
  }, { rootMargin: '-18% 0px -68% 0px', threshold: 0 });
  sections.forEach((section) => observer.observe(section));
  activateSection(sections[0].id);
}

const cardDialog = document.querySelector('#meta-card-dialog');
const cardDialogContent = document.querySelector('#meta-card-dialog-content');
document.addEventListener('click', async (event) => {
  const trigger = event.target.closest?.('[data-meta-card-details]');
  if (!trigger || !trigger.dataset.oracleId) return;
  try {
    await openCardModal({
      dialog: cardDialog,
      content: cardDialogContent,
      oracleId: trigger.dataset.oracleId,
      readOnlyPrintings: true,
    });
  } catch (error) {
    if (cardDialogContent) {
      cardDialogContent.replaceChildren();
      const message = document.createElement('p');
      message.className = 'empty-state';
      message.textContent = error?.message || 'The card details could not be loaded.';
      cardDialogContent.appendChild(message);
    }
    if (cardDialog && !cardDialog.open) cardDialog.showModal();
  }
});
cardDialog?.querySelector('.dialog-close')?.addEventListener('click', () => cardDialog.close());
cardDialog?.addEventListener('click', (event) => { if (event.target === cardDialog) cardDialog.close(); });
