import { DEFAULT_SHORTCUT_BINDINGS, KEYBOARD_SHORTCUTS, KEYBOARD_SHORTCUT_BINDINGS_LS } from '../config/constants.js';
import { $ } from '../core/dom.js';
import { readLs, writeLs } from '../core/storage.js';
import { openFolder } from '../services/batch.js';
import { scheduleUserPreferencesSave } from '../services/preferences.js';
import { runtime } from '../state/app-state.js';
import { clearShortcutRebindLivePreview, endShortcutRebindSession, findShortcutBindingConflict, formatBindingDisplay, formatModifierPartsFromEvent, normalizeBindingFromEvent, onShortcutsListActivateRow, positionShortcutRebindPopoverNear, shortcutEventIsModifierOnly, validateCapturedShortcutBinding } from './events.js';

export function loadShortcutBindingOverrides() {
  runtime.shortcutBindingsOverrides = {};
  try {
    const raw = readLs(KEYBOARD_SHORTCUT_BINDINGS_LS);
    if (!raw) return;
    const parsed = JSON.parse(raw);
    if (!parsed || typeof parsed !== "object") return;
    Object.keys(DEFAULT_SHORTCUT_BINDINGS).forEach((id) => {
      const o = parsed[id];
      if (!o || typeof o !== "object") return;
      const code = typeof o.code === "string" ? o.code : "";
      if (!code) return;
      const key = typeof o.key === "string" ? o.key.trim().toLowerCase() : "";
      runtime.shortcutBindingsOverrides[id] = {
        ctrl: !!o.ctrl,
        alt: !!o.alt,
        shift: !!o.shift,
        meta: !!o.meta,
        code,
        ...(key.length === 1 && /^[a-z0-9]$/.test(key) ? { key } : {}),
      };
    });
  } catch (_) {
    runtime.shortcutBindingsOverrides = {};
  }
}


export function persistShortcutBindingOverrides() {
  try {
    const keys = Object.keys(runtime.shortcutBindingsOverrides);
    if (!keys.length) {
      writeLs(KEYBOARD_SHORTCUT_BINDINGS_LS, null);
      scheduleUserPreferencesSave({ keyboard_shortcut_bindings: {} });
      return;
    }
    writeLs(KEYBOARD_SHORTCUT_BINDINGS_LS, JSON.stringify(runtime.shortcutBindingsOverrides));
    scheduleUserPreferencesSave({ keyboard_shortcut_bindings: runtime.shortcutBindingsOverrides });
  } catch (_) {
    /* ignore */
  }
}


export function getEffectiveShortcutBinding(bindId) {
  if (!bindId || !DEFAULT_SHORTCUT_BINDINGS[bindId]) return null;
  const ovr = runtime.shortcutBindingsOverrides[bindId];
  return ovr || DEFAULT_SHORTCUT_BINDINGS[bindId];
}


export function updateShortcutRebindLiveFromKeydown(e) {
  const live = $("shortcutRebindLiveKeys");
  if (!live) return;
  if (!runtime.shortcutRebindState.active || runtime.shortcutRebindState.mode !== "capture") return;
  if (shortcutEventIsModifierOnly(e)) {
    const parts = formatModifierPartsFromEvent(e);
    live.textContent = parts.length ? `${parts.join("+")}+…` : "";
    return;
  }
  live.textContent = formatBindingDisplay(normalizeBindingFromEvent(e));
}


export function updateShortcutRebindLiveFromKeyup(e) {
  const live = $("shortcutRebindLiveKeys");
  if (!live) return;
  if (!runtime.shortcutRebindState.active || runtime.shortcutRebindState.mode !== "capture") return;
  if (!e.ctrlKey && !e.altKey && !e.shiftKey && !e.metaKey) {
    live.textContent = "";
    return;
  }
  const parts = formatModifierPartsFromEvent(e);
  live.textContent = parts.length ? `${parts.join("+")}+…` : "";
}


export function showUiFloatingToast(message, durationMs) {
  const el = $("uiToastMessage");
  if (!el) return;
  el.textContent = String(message || "");
  el.hidden = false;
  if (runtime.uiToastHideTimer) clearTimeout(runtime.uiToastHideTimer);
  const ms = typeof durationMs === "number" && isFinite(durationMs) ? durationMs : 2800;
  runtime.uiToastHideTimer = setTimeout(() => {
    el.hidden = true;
    runtime.uiToastHideTimer = null;
  }, Math.max(1400, ms));
}


export function hideShortcutRebindPopover() {
  const el = $("shortcutRebindPopover");
  if (el) {
    el.hidden = true;
    el.style.left = "";
    el.style.top = "";
  }
  const fb = $("shortcutRebindFeedback");
  if (fb) {
    fb.textContent = "";
    fb.hidden = true;
  }
  clearShortcutRebindLivePreview();
}


export function openNonRebindableShortcutNotice(shortcut, anchorRow) {
  endShortcutRebindSession();
  const titleEl = $("shortcutRebindTitle");
  const hintEl = $("shortcutRebindHint");
  if (titleEl) titleEl.textContent = shortcut.action || "Raccourci";
  if (hintEl) {
    hintEl.textContent =
      "Ce raccourci est intégré au comportement de l'application et ne peut pas être modifié ici.";
  }
  runtime.shortcutRebindState = {
    active: true,
    mode: "info",
    bindId: null,
    onKeyDoc: null,
    onKeyUpDoc: null,
    onMouseDoc: null,
  };
  const onKeyDoc = (e) => {
    if (e.key === "Escape") {
      e.preventDefault();
      e.stopPropagation();
      endShortcutRebindSession();
    }
  };
  const onMouseDoc = (e) => {
    const pop = $("shortcutRebindPopover");
    if (pop && pop.contains(e.target)) return;
    endShortcutRebindSession();
  };
  runtime.shortcutRebindState.onKeyDoc = onKeyDoc;
  runtime.shortcutRebindState.onMouseDoc = onMouseDoc;
  window.addEventListener("keydown", onKeyDoc, true);
  document.addEventListener("mousedown", onMouseDoc, true);
  positionShortcutRebindPopoverNear(anchorRow);
  const cancelBtn = $("shortcutRebindCancel");
  if (cancelBtn) cancelBtn.focus();
}


export function openShortcutRebindCapture(bindId, anchorRow) {
  endShortcutRebindSession();
  const titleEl = $("shortcutRebindTitle");
  const hintEl = $("shortcutRebindHint");
  const fb = $("shortcutRebindFeedback");
  const sc = KEYBOARD_SHORTCUTS.find((s) => s.bindId === bindId);
  if (titleEl) titleEl.textContent = sc && sc.action ? sc.action : "Nouveau raccourci";
  if (hintEl) {
    hintEl.textContent =
      "Enfoncez la nouvelle combinaison (par ex. Ctrl+Maj+P). ?chap : annuler.";
  }
  if (fb) {
    fb.textContent = "";
    fb.hidden = true;
  }
  clearShortcutRebindLivePreview();
  runtime.shortcutRebindState = {
    active: true,
    mode: "capture",
    bindId,
    onKeyDoc: null,
    onKeyUpDoc: null,
    onMouseDoc: null,
  };
  const onKeyDoc = (e) => {
    if (!runtime.shortcutRebindState.active || runtime.shortcutRebindState.mode !== "capture") return;
    if (e.key === "Escape") {
      e.preventDefault();
      e.stopPropagation();
      endShortcutRebindSession();
      return;
    }
    updateShortcutRebindLiveFromKeydown(e);
    if (shortcutEventIsModifierOnly(e)) return;
    if (e.repeat) return;

    const b = normalizeBindingFromEvent(e);
    const err = validateCapturedShortcutBinding(b);
    if (err) {
      if (fb) {
        fb.textContent = err;
        fb.hidden = false;
      }
      e.preventDefault();
      e.stopPropagation();
      return;
    }
    const conflict = findShortcutBindingConflict(bindId, b);
    if (conflict) {
      if (fb) {
        fb.textContent =
          "Cette combinaison est déjà utilisée pour un autre raccourci. Choisissez-en une autre.";
        fb.hidden = false;
      }
      e.preventDefault();
      e.stopPropagation();
      return;
    }
    runtime.shortcutBindingsOverrides[bindId] = b;
    persistShortcutBindingOverrides();
    renderShortcutLists();
    e.preventDefault();
    e.stopPropagation();
    endShortcutRebindSession();
  };
  const onMouseDoc = (e) => {
    const pop = $("shortcutRebindPopover");
    if (pop && pop.contains(e.target)) return;
    endShortcutRebindSession();
  };
  const onKeyUpDoc = (e) => {
    if (!runtime.shortcutRebindState.active || runtime.shortcutRebindState.mode !== "capture") return;
    updateShortcutRebindLiveFromKeyup(e);
  };
  runtime.shortcutRebindState.onKeyDoc = onKeyDoc;
  runtime.shortcutRebindState.onKeyUpDoc = onKeyUpDoc;
  runtime.shortcutRebindState.onMouseDoc = onMouseDoc;
  window.addEventListener("keydown", onKeyDoc, true);
  window.addEventListener("keyup", onKeyUpDoc, true);
  document.addEventListener("mousedown", onMouseDoc, true);
  positionShortcutRebindPopoverNear(anchorRow);
  const cancelBtn = $("shortcutRebindCancel");
  if (cancelBtn) cancelBtn.focus();
}


export function syncMenuShortcutLabels() {
  const pairs = [
    ["menuShortcutOpenFolder", "openFolder"],
    ["menuShortcutCloseFolder", "closeFolder"],
    ["menuShortcutImporter", "openImporter"],
    ["menuShortcutSettings", "openSettings"],
  ];
  pairs.forEach(([elemId, bindId]) => {
    const el = $(elemId);
    const b = getEffectiveShortcutBinding(bindId);
    if (el && b) el.textContent = formatBindingDisplay(b);
  });
}


export function renderShortcutsList(hostId) {
  const host = $(hostId);
  if (!host) return;
  host.innerHTML = "";

  const head = document.createElement("div");
  head.className = "shortcuts-list__row shortcuts-list__row--head";
  head.innerHTML = "<div>Raccourci</div><div>Action</div><div>Contexte</div>";
  host.appendChild(head);

  KEYBOARD_SHORTCUTS.forEach((shortcut) => {
    const row = document.createElement("div");
    row.className = "shortcuts-list__row";
    if (shortcut.bindId) row.classList.add("shortcuts-list__row--rebindable");
    const keys = document.createElement("div");
    keys.className = "shortcuts-list__keys";
    const keyCode = document.createElement("code");
    keyCode.textContent = shortcut.bindId
      ? formatBindingDisplay(getEffectiveShortcutBinding(shortcut.bindId))
      : shortcut.keys;
    keys.appendChild(keyCode);

    const action = document.createElement("div");
    action.className = "shortcuts-list__action";
    action.textContent = shortcut.action;

    const context = document.createElement("div");
    context.className = "shortcuts-list__context";
    context.textContent = shortcut.context;

    row.appendChild(keys);
    row.appendChild(action);
    row.appendChild(context);
    if (shortcut.bindId) {
      row.dataset.shortcutBindId = shortcut.bindId;
      row.tabIndex = 0;
      row.setAttribute("role", "button");
      row.setAttribute(
        "aria-label",
        `${shortcut.action} — cliquer pour changer le raccourci`
      );
    } else {
      row.tabIndex = 0;
      row.setAttribute("role", "button");
      row.setAttribute("aria-label", `${shortcut.action} — raccourci non modifiable`);
    }
    row.addEventListener("click", () => onShortcutsListActivateRow(shortcut, row));
    row.addEventListener("keydown", (e) => {
      if (e.key === "Enter" || e.key === " ") {
        e.preventDefault();
        onShortcutsListActivateRow(shortcut, row);
      }
    });
    host.appendChild(row);
  });
}


export function renderShortcutLists() {
  renderShortcutsList("shortcutsFloatingList");
  renderShortcutsList("shortcutsSettingsList");
  syncMenuShortcutLabels();
}


export function toggleShortcutsPanel(open) {
  const panel = $("shortcutsFloatingPanel");
  const backdrop = $("shortcutsFloatingBackdrop");
  if (!panel) return;
  panel.hidden = !open;
  if (backdrop) backdrop.hidden = !open;
}


export function openShortcutsPanel() {
  toggleShortcutsPanel(true);
}


export function closeShortcutsPanel() {
  toggleShortcutsPanel(false);
}
