/* eslint-disable @typescript-eslint/ban-ts-comment */
// @ts-nocheck
import {
  buildEngineOverrideEntry,
  describeEngineOverrideValue,
  ENGINE_OVERRIDE_SPECS,
  getDefaultEngineOverrideValue,
  getEngineOverrideSpec,
  getFirstUnusedEngineOverrideKey,
  normalizeEngineOverrideEntries,
  normalizeEngineOverrideValue,
} from "./engineOverrides";
import { clampFloatingWindowRect } from "./floatingWindowUtils";

const ENGINE_OVERRIDE_WINDOW_KEY = "engineOverrides";
const DEFAULT_WIDTH = 620;
const DEFAULT_HEIGHT = 420;
const MIN_WIDTH = 420;
const MIN_HEIGHT = 260;

function clampWindowRect(layerRect, left, top, width, height) {
  return clampFloatingWindowRect(layerRect, left, top, width, height, MIN_WIDTH, MIN_HEIGHT, DEFAULT_WIDTH, DEFAULT_HEIGHT);
}

export function createEngineOverrideWindowController(scope) {
  let initialized = false;
  const uiScope = scope.uiScope || scope;
  const sessionScope = scope.sessionScope || scope;
  const persistedState = typeof sessionScope.getPersistedToolWindowState === "function"
    ? sessionScope.getPersistedToolWindowState(ENGINE_OVERRIDE_WINDOW_KEY)
    : null;
  const state = {
    visible: persistedState?.visible === true,
    x: Number(persistedState?.x) || 116,
    y: Number(persistedState?.y) || 88,
    width: Number(persistedState?.width) || DEFAULT_WIDTH,
    height: Number(persistedState?.height) || DEFAULT_HEIGHT,
    shellEl: null,
    titleEl: null,
    metaEl: null,
    listEl: null,
    emptyEl: null,
    addBtnEl: null,
    resizeEl: null,
    nextZIndex: 136,
  };

  function getLayerRect() {
    return uiScope.toolWindowLayerEl?.getBoundingClientRect() || uiScope.editorBodyEl?.getBoundingClientRect() || {
      left: 0,
      top: 0,
      width: DEFAULT_WIDTH,
      height: DEFAULT_HEIGHT,
    };
  }

  function persistState() {
    if (typeof sessionScope.setPersistedToolWindowState === "function") {
      sessionScope.setPersistedToolWindowState(ENGINE_OVERRIDE_WINDOW_KEY, {
        visible: state.visible === true,
        mode: "floating",
        x: state.x,
        y: state.y,
        width: state.width,
        height: state.height,
        order: 997,
      });
    }
    scope.persistPopupSessionLayout?.();
    sessionScope.persistPopupSessionLayout?.();
  }

  function focusWindow() {
    if (!state.shellEl || state.visible !== true) {
      return;
    }
    state.nextZIndex += 1;
    state.shellEl.style.zIndex = String(state.nextZIndex);
    state.shellEl.classList.add("is-focused");
  }

  function clearFocus() {
    state.shellEl?.classList.remove("is-focused");
  }

  function applyWindowRect() {
    if (!state.shellEl) {
      return;
    }
    state.shellEl.style.left = Math.round(state.x) + "px";
    state.shellEl.style.top = Math.round(state.y) + "px";
    state.shellEl.style.width = Math.round(state.width) + "px";
    state.shellEl.style.height = Math.round(state.height) + "px";
  }

  function updateSummary() {
    const entries = normalizeEngineOverrideEntries(scope.getEditorEngineOverrides?.() || []);
    const summary = entries.length <= 0
      ? "No engine overrides active."
      : `${entries.length} override${entries.length === 1 ? "" : "s"} active`;
    if (uiScope.engineOverridesSummaryEl) {
      uiScope.engineOverridesSummaryEl.textContent = summary;
      uiScope.engineOverridesSummaryEl.title = entries.length > 0
        ? entries.map((entry) => {
          const spec = getEngineOverrideSpec(entry.key);
          return `${spec?.label || entry.key}: ${describeEngineOverrideValue(entry)}`;
        }).join("\n")
        : summary;
    }
  }

  async function saveEntries(nextEntries, successMessage) {
    const normalizedEntries = normalizeEngineOverrideEntries(nextEntries);
    try {
      await scope.saveEditorEngineOverrides?.(normalizedEntries);
      if (successMessage) {
        scope.setStatus?.(successMessage, false);
      }
      refresh();
      return true;
    } catch (error) {
      scope.setStatus?.(String(error), true);
      refresh();
      return false;
    }
  }

  function handleAddEntry() {
    const currentEntries = normalizeEngineOverrideEntries(scope.getEditorEngineOverrides?.() || []);
    const nextKey = getFirstUnusedEngineOverrideKey(currentEntries);
    if (!nextKey) {
      scope.setStatus?.("All available engine overrides already exist.", false);
      refresh();
      return;
    }
    const nextEntry = buildEngineOverrideEntry(nextKey, currentEntries);
    if (!nextEntry) {
      scope.setStatus?.("Unable to create that engine override.", true);
      return;
    }
    void saveEntries([...currentEntries, nextEntry], "Added engine override.");
  }

  function handleDeleteEntry(entryId) {
    const currentEntries = normalizeEngineOverrideEntries(scope.getEditorEngineOverrides?.() || []);
    const nextEntries = currentEntries.filter((entry) => String(entry.id || "").trim() !== String(entryId || "").trim());
    void saveEntries(nextEntries, "Removed engine override.");
  }

  function handleEntryKeyChange(entryId, nextKey) {
    const currentEntries = normalizeEngineOverrideEntries(scope.getEditorEngineOverrides?.() || []);
    const normalizedKey = String(nextKey || "").trim();
    const duplicate = currentEntries.find((entry) => entry.key === normalizedKey && String(entry.id || "").trim() !== String(entryId || "").trim());
    if (duplicate) {
      scope.setStatus?.("That engine override already exists.", true);
      refresh();
      return;
    }
    const spec = getEngineOverrideSpec(normalizedKey);
    if (!spec) {
      scope.setStatus?.("Unknown engine override selected.", true);
      refresh();
      return;
    }
    const nextEntries = currentEntries.map((entry) => {
      if (String(entry.id || "").trim() !== String(entryId || "").trim()) {
        return entry;
      }
      return {
        ...entry,
        key: spec.key,
        value: getDefaultEngineOverrideValue(spec.key),
      };
    });
    void saveEntries(nextEntries, "Updated engine override type.");
  }

  function handleEntryValueChange(entryId, rawValue) {
    const currentEntries = normalizeEngineOverrideEntries(scope.getEditorEngineOverrides?.() || []);
    const currentEntry = currentEntries.find((entry) => String(entry.id || "").trim() === String(entryId || "").trim()) || null;
    if (!currentEntry) {
      return;
    }
    const normalizedValue = normalizeEngineOverrideValue(currentEntry.key, rawValue);
    if (normalizedValue == null) {
      scope.setStatus?.("That override value was invalid.", true);
      refresh();
      return;
    }
    const nextEntries = currentEntries.map((entry) => {
      if (String(entry.id || "").trim() !== String(entryId || "").trim()) {
        return entry;
      }
      return {
        ...entry,
        value: normalizedValue,
      };
    });
    void saveEntries(nextEntries, "Updated engine override.");
  }

  function renderEntryRow(entry) {
    const spec = getEngineOverrideSpec(entry.key);
    if (!spec || !state.listEl) {
      return;
    }
    const rowEl = document.createElement("div");
    rowEl.className = "engine-override-row";

    const headEl = document.createElement("div");
    headEl.className = "engine-override-row-head";

    const selectEl = document.createElement("select");
    selectEl.className = "engine-override-select";
    ENGINE_OVERRIDE_SPECS.forEach((candidate) => {
      const optionEl = document.createElement("option");
      optionEl.value = candidate.key;
      optionEl.textContent = candidate.label;
      selectEl.appendChild(optionEl);
    });
    selectEl.value = spec.key;
    selectEl.addEventListener("change", () => {
      handleEntryKeyChange(entry.id, selectEl.value);
    });

    const deleteBtnEl = document.createElement("button");
    deleteBtnEl.type = "button";
    deleteBtnEl.className = "icon-action-btn danger";
    deleteBtnEl.textContent = "X";
    deleteBtnEl.title = "Remove override";
    deleteBtnEl.addEventListener("click", () => {
      handleDeleteEntry(entry.id);
    });

    headEl.appendChild(selectEl);
    headEl.appendChild(deleteBtnEl);

    const descriptionEl = document.createElement("div");
    descriptionEl.className = "engine-override-description";
    descriptionEl.textContent = spec.description;

    const valueRowEl = document.createElement("div");
    valueRowEl.className = "engine-override-value-row";

    const valueLabelEl = document.createElement("label");
    valueLabelEl.className = "engine-override-value-label";
    valueLabelEl.textContent = "Value";
    valueRowEl.appendChild(valueLabelEl);

    if (spec.type === "boolean") {
      const toggleWrapEl = document.createElement("label");
      toggleWrapEl.className = "engine-override-toggle";
      const checkboxEl = document.createElement("input");
      checkboxEl.type = "checkbox";
      checkboxEl.checked = Boolean(entry.value);
      checkboxEl.addEventListener("change", () => {
        handleEntryValueChange(entry.id, checkboxEl.checked);
      });
      const copyEl = document.createElement("span");
      copyEl.textContent = checkboxEl.checked ? "On" : "Off";
      checkboxEl.addEventListener("change", () => {
        copyEl.textContent = checkboxEl.checked ? "On" : "Off";
      });
      toggleWrapEl.appendChild(checkboxEl);
      toggleWrapEl.appendChild(copyEl);
      valueRowEl.appendChild(toggleWrapEl);
    } else {
      const inputEl = document.createElement("input");
      inputEl.className = "engine-override-number-input";
      inputEl.type = "number";
      if (Number.isFinite(Number(spec.min))) {
        inputEl.min = String(Number(spec.min));
      }
      if (Number.isFinite(Number(spec.max))) {
        inputEl.max = String(Number(spec.max));
      }
      if (Number.isFinite(Number(spec.step))) {
        inputEl.step = String(Number(spec.step));
      }
      inputEl.value = String(entry.value);
      inputEl.addEventListener("change", () => {
        handleEntryValueChange(entry.id, inputEl.value);
      });
      valueRowEl.appendChild(inputEl);
    }

    rowEl.appendChild(headEl);
    rowEl.appendChild(descriptionEl);
    rowEl.appendChild(valueRowEl);
    state.listEl.appendChild(rowEl);
  }

  function refresh() {
    const entries = normalizeEngineOverrideEntries(scope.getEditorEngineOverrides?.() || []);
    updateSummary();
    if (state.titleEl) {
      state.titleEl.textContent = "Engine Overrides";
    }
    if (state.metaEl) {
      state.metaEl.textContent = entries.length <= 0
        ? "No overrides"
        : entries.length === 1
          ? "1 override"
          : `${entries.length} overrides`;
    }
    if (state.addBtnEl) {
      state.addBtnEl.disabled = !getFirstUnusedEngineOverrideKey(entries);
    }
    if (!state.listEl) {
      return;
    }
    state.listEl.innerHTML = "";
    if (entries.length <= 0) {
      if (state.emptyEl) {
        state.emptyEl.classList.remove("hidden");
        state.listEl.appendChild(state.emptyEl);
      }
      return;
    }
    if (state.emptyEl) {
      state.emptyEl.classList.add("hidden");
    }
    entries.forEach((entry) => {
      renderEntryRow(entry);
    });
  }

  function ensureShell() {
    if (state.shellEl && state.shellEl.isConnected) {
      return state.shellEl;
    }
    const shellEl = document.createElement("div");
    shellEl.className = "tool-popout-window engine-override-window hidden";
    const titlebarEl = document.createElement("div");
    titlebarEl.className = "tool-popout-titlebar";
    titlebarEl.innerHTML =
      '<div class="tool-popout-title">Engine Overrides</div>' +
      '<div class="tool-popout-hint">Danger zone</div>' +
      '<button class="tool-popout-close-btn" type="button" aria-label="Close engine overrides">X</button>';
    const bodyEl = document.createElement("div");
    bodyEl.className = "tool-popout-body";
    const cardEl = document.createElement("div");
    cardEl.className = "engine-override-card";
    const headEl = document.createElement("div");
    headEl.className = "engine-override-head";
    const titleEl = document.createElement("div");
    titleEl.className = "engine-override-title";
    const metaEl = document.createElement("div");
    metaEl.className = "engine-override-meta";
    const addBtnEl = document.createElement("button");
    addBtnEl.type = "button";
    addBtnEl.className = "mini-btn";
    addBtnEl.textContent = "Add";
    addBtnEl.addEventListener("click", () => {
      handleAddEntry();
    });
    const listEl = document.createElement("div");
    listEl.className = "engine-override-list";
    const emptyEl = document.createElement("div");
    emptyEl.className = "engine-override-empty";
    emptyEl.textContent = "No overrides yet. Add one to override engine behavior.";
    headEl.appendChild(titleEl);
    headEl.appendChild(metaEl);
    headEl.appendChild(addBtnEl);
    listEl.appendChild(emptyEl);
    cardEl.appendChild(headEl);
    cardEl.appendChild(listEl);
    bodyEl.appendChild(cardEl);
    const resizeEl = document.createElement("div");
    resizeEl.className = "tool-popout-resize";
    const closeBtnEl = titlebarEl.querySelector(".tool-popout-close-btn");
    shellEl.appendChild(titlebarEl);
    shellEl.appendChild(bodyEl);
    shellEl.appendChild(resizeEl);
    shellEl.addEventListener("pointerdown", () => {
      focusWindow();
    });
    titlebarEl.addEventListener("pointerdown", (event) => {
      if (closeBtnEl && closeBtnEl.contains(event.target)) {
        return;
      }
      if (event.button !== 0) {
        return;
      }
      event.preventDefault();
      focusWindow();
      const layerRect = getLayerRect();
      const originLeft = Number(state.x) || 0;
      const originTop = Number(state.y) || 0;
      const startX = event.clientX;
      const startY = event.clientY;
      const move = (moveEvent) => {
        const nextRect = clampWindowRect(
          layerRect,
          originLeft + (moveEvent.clientX - startX),
          originTop + (moveEvent.clientY - startY),
          state.width,
          state.height,
        );
        state.x = nextRect.left;
        state.y = nextRect.top;
        applyWindowRect();
      };
      const up = () => {
        window.removeEventListener("pointermove", move);
        window.removeEventListener("pointerup", up);
        persistState();
      };
      window.addEventListener("pointermove", move);
      window.addEventListener("pointerup", up);
    });
    closeBtnEl?.addEventListener("click", (event) => {
      event.preventDefault();
      event.stopPropagation();
      close();
    });
    resizeEl.addEventListener("pointerdown", (event) => {
      if (event.button !== 0) {
        return;
      }
      event.preventDefault();
      focusWindow();
      const layerRect = getLayerRect();
      const startX = event.clientX;
      const startY = event.clientY;
      const originWidth = Number(state.width) || DEFAULT_WIDTH;
      const originHeight = Number(state.height) || DEFAULT_HEIGHT;
      const move = (moveEvent) => {
        const nextRect = clampWindowRect(
          layerRect,
          state.x,
          state.y,
          Math.max(MIN_WIDTH, originWidth + (moveEvent.clientX - startX)),
          Math.max(MIN_HEIGHT, originHeight + (moveEvent.clientY - startY)),
        );
        state.width = nextRect.width;
        state.height = nextRect.height;
        applyWindowRect();
      };
      const up = () => {
        window.removeEventListener("pointermove", move);
        window.removeEventListener("pointerup", up);
        persistState();
      };
      window.addEventListener("pointermove", move);
      window.addEventListener("pointerup", up);
    });
    state.shellEl = shellEl;
    state.titleEl = titleEl;
    state.metaEl = metaEl;
    state.listEl = listEl;
    state.emptyEl = emptyEl;
    state.addBtnEl = addBtnEl;
    state.resizeEl = resizeEl;
    uiScope.toolWindowLayerEl?.appendChild(shellEl);
    applyWindowRect();
    shellEl.classList.toggle("hidden", state.visible !== true);
    refresh();
    return shellEl;
  }

  function open() {
    ensureShell();
    const nextRect = clampWindowRect(getLayerRect(), state.x, state.y, state.width, state.height);
    state.x = nextRect.left;
    state.y = nextRect.top;
    state.width = nextRect.width;
    state.height = nextRect.height;
    state.visible = true;
    refresh();
    state.shellEl?.classList.remove("hidden");
    applyWindowRect();
    focusWindow();
    persistState();
    return true;
  }

  function close() {
    state.visible = false;
    clearFocus();
    state.shellEl?.classList.add("hidden");
    persistState();
    return true;
  }

  function initialize() {
    if (initialized) {
      return;
    }
    initialized = true;
    ensureShell();
    updateSummary();
    window.addEventListener("resize", () => {
      const nextRect = clampWindowRect(getLayerRect(), state.x, state.y, state.width, state.height);
      state.x = nextRect.left;
      state.y = nextRect.top;
      state.width = nextRect.width;
      state.height = nextRect.height;
      applyWindowRect();
      persistState();
    });
    if (state.visible) {
      open();
    } else {
      state.visible = false;
      state.shellEl?.classList.add("hidden");
    }
  }

  return {
    initialize,
    open,
    close,
    refresh,
    updateSummary,
    isOpen: () => state.visible === true,
  };
}
