/* eslint-disable @typescript-eslint/ban-ts-comment, no-empty */
// @ts-nocheck

export function createPersistenceController(scope) {
  const documentScope = scope.documentScope || scope;
  const historyScope = scope.historyScope || scope;
  const uiScope = scope.uiScope || scope;

  async function readErrorResponse(response) {
    try {
      const text = await response.text();
      const trimmed = String(text || "").trim();
      return trimmed ? `: ${trimmed.slice(0, 240)}` : "";
    } catch {
      return "";
    }
  }

  async function persistContentPayload(type, payload) {
    const normalizedType = String(type || "").trim();
    const response = await fetch(scope.apiBase + "/api/content/" + normalizedType, {
      method: "POST",
      headers: { "Content-Type": "application/json" },
      body: JSON.stringify(payload),
    });
    if (!response.ok) {
      const responseDetails = await readErrorResponse(response);
      if (normalizedType === "images" && response.status === 404 && /Unknown content type/i.test(responseDetails)) {
        throw new Error("Graphics save failed (404): API does not support images yet. Restart the server.");
      }
      throw new Error(getContentSaveLabel(normalizedType) + " save failed (" + response.status + ")" + responseDetails);
    }
    return response.json().catch(() => ({ ok: true }));
  }

  function getContentSaveLabel(type) {
    const labels = {
      npcs: "NPC",
      images: "Graphics",
      sprites: "Sprite",
      tiles: "Tile",
    };
    return labels[String(type || "").trim()] || "Content";
  }

  async function persistWorldChunkBatchPayload(worldId, payload) {
    const response = await fetch(
      scope.apiBase + "/api/world/" + encodeURIComponent(String(worldId || "").trim()) + "/chunks/batch-save",
      {
        method: "POST",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify(payload),
      },
    );
    if (!response.ok) {
      throw new Error("World save failed (" + response.status + ")" + await readErrorResponse(response));
    }
    return response.json().catch(() => ({ ok: true }));
  }

  async function saveCurrentWorldState() {
    const worldId = String(scope.worldId || scope.mapId || "").trim();
    if (!worldId) {
      uiScope.setStatus("World id missing. Cannot save.", true);
      return false;
    }
    if (typeof documentScope.ensureWorldDocumentCurrent === "function") {
      documentScope.ensureWorldDocumentCurrent();
    }
    if (typeof scope.syncCachedWorldHeightLayerMetadata === "function") {
      scope.syncCachedWorldHeightLayerMetadata();
    }
    const dirtyChunkKeys = typeof scope.getDirtyWorldChunkKeys === "function"
      ? scope.getDirtyWorldChunkKeys()
      : [];
    if (dirtyChunkKeys.length > 0 && typeof scope.rebuildVisibleWorldChunksFromDocument === "function") {
      scope.rebuildVisibleWorldChunksFromDocument(dirtyChunkKeys);
    }
    const chunksToSave = typeof scope.getDirtyWorldChunkPayloads === "function"
      ? scope.getDirtyWorldChunkPayloads()
      : [];
    historyScope.isSaving = true;
    historyScope.refreshToolbarState();
    let saveFailed = false;
    try {
      await persistWorldChunkBatchPayload(worldId, {
        world: {
          id: worldId,
          name: String(scope.worldName || documentScope.mapName || worldId).trim() || worldId,
          chunkWidth: Math.max(1, Number(scope.worldChunkWidth) || 32),
          chunkHeight: Math.max(1, Number(scope.worldChunkHeight) || 32),
          tileSize: Math.max(8, Number(documentScope.baseTileSize) || 32),
          backgroundColor: documentScope.normalizeMapBackgroundColor(documentScope.backgroundColor),
          defaultBackgroundTileId: documentScope.normalizeBackgroundTileId(documentScope.backgroundTileId),
          heightBlurStep: Math.max(0, Math.min(1, Number(documentScope.heightBlurStep ?? documentScope.heightDetailStep) || 0.1)),
          editorUi: documentScope.cloneEditorUiState(),
          spawn: {
            x: Math.floor(Number(scope.worldSpawnX) || 0),
            y: Math.floor(Number(scope.worldSpawnY) || 0),
          },
        },
        bookmarks: {
          schemaVersion: 1,
          worldId,
          bookmarks: typeof scope.getWorldBookmarks === "function"
            ? scope.getWorldBookmarks().map((entry) => ({
              id: String(entry?.id || "").trim(),
              label: String(entry?.label || entry?.id || "").trim(),
              x: Math.floor(Number(entry?.x) || 0),
              y: Math.floor(Number(entry?.y) || 0),
            })).filter((entry) => entry.id)
            : [],
        },
        chunks: chunksToSave,
      });
      if (typeof scope.cacheStandaloneMapBootstrap === "function") {
        scope.cacheStandaloneMapBootstrap(scope.mapId);
      }
      try {
        if (window.opener && !window.opener.closed) {
          window.opener.postMessage({ type: "map-editor-saved", mapId: worldId }, "*");
        }
      } catch {}
      historyScope.lastSavedHistoryId = historyScope.historyEntries[historyScope.historyIndex]
        ? historyScope.historyEntries[historyScope.historyIndex].id
        : historyScope.lastSavedHistoryId;
      historyScope.persistHistoryState();
      if (typeof scope.clearDirtyWorldChunks === "function" && chunksToSave.length > 0) {
        scope.clearDirtyWorldChunks(chunksToSave.map((chunk) => `${Math.floor(Number(chunk?.chunkX) || 0)}:${Math.floor(Number(chunk?.chunkY) || 0)}`));
      }
      uiScope.setStatus(chunksToSave.length > 0 ? ("Saved world chunks: " + chunksToSave.length + ".") : "Saved world metadata.", false);
      return true;
    } catch (error) {
      saveFailed = true;
      uiScope.setStatus(String(error), true);
      return false;
    } finally {
      historyScope.isSaving = false;
      historyScope.refreshToolbarState(saveFailed);
    }
  }

  async function saveCurrentState() {
    return saveCurrentWorldState();
  }

  return {
    persistContentPayload,
    saveCurrentState,
  };
}
