/* eslint-disable @typescript-eslint/ban-ts-comment */
// @ts-nocheck
import { copyTextWithClipboardFallback } from "./textTransferUtils";
import { clampFloatingWindowRect } from "./floatingWindowUtils";

const STATUS_LOG_WINDOW_KEY = "statusLog";
const DEFAULT_WIDTH = 540;
const DEFAULT_HEIGHT = 420;
const MIN_WIDTH = 360;
const MIN_HEIGHT = 240;

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

export function createStatusLogWindowController(scope) {
  let initialized = false;
  const uiScope = scope.uiScope || scope;
  const sessionScope = scope.sessionScope || scope;
  const persistedState = typeof sessionScope.getPersistedToolWindowState === "function"
    ? sessionScope.getPersistedToolWindowState(STATUS_LOG_WINDOW_KEY)
    : null;
  const state = {
    visible: persistedState?.visible === true,
    x: Number(persistedState?.x) || 96,
    y: Number(persistedState?.y) || 72,
    width: Number(persistedState?.width) || DEFAULT_WIDTH,
    height: Number(persistedState?.height) || DEFAULT_HEIGHT,
    shellEl: null,
    titleEl: null,
    metaEl: null,
    listEl: null,
    emptyEl: null,
    copyBtnEl: null,
    clearBtnEl: null,
    resizeEl: null,
    nextZIndex: 126,
  };

  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(STATUS_LOG_WINDOW_KEY, {
        visible: state.visible === true,
        mode: "floating",
        x: state.x,
        y: state.y,
        width: state.width,
        height: state.height,
        order: 996,
      });
    }
    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 buildExportText() {
    const entries = scope.getEditorLogEntries?.() || [];
    return entries.map((entry) => `[${entry.timestampLabel}] [${entry.level}] ${entry.message}`).join("\n");
  }

  async function copyLog() {
    const exportText = buildExportText();
    if (!exportText.trim()) {
      scope.setStatus?.("Status log is empty.", false, { skipLogEntry: true });
      return false;
    }
    return copyTextWithClipboardFallback(
      exportText,
      "Copy status log",
      () => scope.setStatus?.("Copied status log to clipboard.", false, { skipLogEntry: true }),
      () => scope.setStatus?.("Clipboard unavailable. Status log opened for manual copy.", false, { skipLogEntry: true }),
    );
  }

  function refresh() {
    const entries = scope.getEditorLogEntries?.() || [];
    if (state.titleEl) {
      state.titleEl.textContent = "Status Log";
    }
    if (state.metaEl) {
      state.metaEl.textContent = entries.length === 1 ? "1 entry" : `${entries.length} entries`;
    }
    if (!state.listEl) {
      return;
    }
    state.listEl.innerHTML = "";
    if (entries.length <= 0) {
      if (state.emptyEl) {
        state.emptyEl.classList.remove("hidden");
      }
      return;
    }
    if (state.emptyEl) {
      state.emptyEl.classList.add("hidden");
    }
    entries
      .slice()
      .reverse()
      .forEach((entry) => {
        const rowEl = document.createElement("div");
        rowEl.className = "status-log-row";
        rowEl.innerHTML =
          '<div class="status-log-row-head">' +
          '<span class="status-log-row-level status-log-row-level-' + String(entry.level || "information").toLowerCase() + '">' + String(entry.level || "Information") + '</span>' +
          '<span class="status-log-row-time">' + String(entry.timestampLabel || "") + "</span>" +
          "</div>" +
          '<div class="status-log-row-message">' + scope.runtimeEscapeHtml(String(entry.message || "")) + "</div>";
        state.listEl.appendChild(rowEl);
      });
    state.listEl.scrollTop = 0;
  }

  function ensureShell() {
    if (state.shellEl && state.shellEl.isConnected) {
      return state.shellEl;
    }
    const shellEl = document.createElement("div");
    shellEl.className = "tool-popout-window status-log-window hidden";
    const titlebarEl = document.createElement("div");
    titlebarEl.className = "tool-popout-titlebar";
    titlebarEl.innerHTML =
      '<div class="tool-popout-title">Status Log</div>' +
      '<div class="tool-popout-hint">Right-click the top-right status to reopen</div>' +
      '<button class="tool-popout-close-btn" type="button" aria-label="Close status log">X</button>';
    const bodyEl = document.createElement("div");
    bodyEl.className = "tool-popout-body";
    const cardEl = document.createElement("div");
    cardEl.className = "status-log-card";
    const headEl = document.createElement("div");
    headEl.className = "status-log-head";
    const titleEl = document.createElement("div");
    titleEl.className = "status-log-title";
    const metaEl = document.createElement("div");
    metaEl.className = "status-log-meta";
    headEl.appendChild(titleEl);
    headEl.appendChild(metaEl);
    const actionsEl = document.createElement("div");
    actionsEl.className = "status-log-actions";
    const copyBtnEl = document.createElement("button");
    copyBtnEl.type = "button";
    copyBtnEl.className = "mini-btn";
    copyBtnEl.textContent = "Copy";
    copyBtnEl.addEventListener("click", () => {
      void copyLog();
    });
    const clearBtnEl = document.createElement("button");
    clearBtnEl.type = "button";
    clearBtnEl.className = "mini-btn danger";
    clearBtnEl.textContent = "Clear";
    clearBtnEl.addEventListener("click", () => {
      scope.clearEditorLogEntries?.();
      refresh();
      scope.setStatus?.("Status log cleared.", false, { skipLogEntry: true });
    });
    actionsEl.appendChild(copyBtnEl);
    actionsEl.appendChild(clearBtnEl);
    const listEl = document.createElement("div");
    listEl.className = "status-log-list";
    const emptyEl = document.createElement("div");
    emptyEl.className = "status-log-empty";
    emptyEl.textContent = "No log entries yet.";
    listEl.appendChild(emptyEl);
    cardEl.appendChild(headEl);
    cardEl.appendChild(actionsEl);
    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.copyBtnEl = copyBtnEl;
    state.clearBtnEl = clearBtnEl;
    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();
    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,
    isOpen: () => state.visible === true,
  };
}
