/* eslint-disable @typescript-eslint/ban-ts-comment */
// @ts-nocheck

export function createOverlayRenderer(scope, options) {
  const tileImages = options?.tileImages || {};
  const draw = typeof options?.draw === "function" ? options.draw : () => {};
  const rectIntersects = typeof options?.rectIntersects === "function"
    ? options.rectIntersects
    : () => true;
  const drawSelectionReticle = typeof options?.drawSelectionReticle === "function"
    ? options.drawSelectionReticle
    : () => {};

  function isNpcPlaced(npc) {
    if (!npc) {
      return false;
    }
    const x = Number(npc.x);
    const y = Number(npc.y);
    return Number.isFinite(x) && Number.isFinite(y) && x >= 0 && y >= 0;
  }

  function drawPlaceholderNpcMarker(drawX, drawY, destW, destH) {
    const markerSize = Math.max(scope.tileSize * 0.58, Math.min(Math.min(destW || scope.tileSize, destH || scope.tileSize), scope.tileSize));
    const radius = markerSize / 2;
    const centerX = drawX + (destW || scope.tileSize) / 2;
    const centerY = drawY + (destH || scope.tileSize) / 2;
    const outlineRadius = radius + Math.max(2, scope.tileSize * 0.08);
    const innerRadius = Math.max(3, radius * 0.72);
    const highlightRadius = Math.max(2, radius * 0.24);
    scope.ctx.save();
    scope.ctx.fillStyle = "rgba(15, 24, 36, 0.92)";
    scope.ctx.beginPath();
    scope.ctx.arc(centerX, centerY, outlineRadius, 0, Math.PI * 2);
    scope.ctx.fill();
    scope.ctx.fillStyle = "rgba(255, 74, 182, 0.98)";
    scope.ctx.beginPath();
    scope.ctx.arc(centerX, centerY, radius, 0, Math.PI * 2);
    scope.ctx.fill();
    scope.ctx.fillStyle = "rgba(255, 222, 66, 0.98)";
    scope.ctx.beginPath();
    scope.ctx.arc(centerX, centerY, innerRadius, 0, Math.PI * 2);
    scope.ctx.fill();
    scope.ctx.strokeStyle = "rgba(0, 245, 255, 0.98)";
    scope.ctx.lineWidth = Math.max(1.5, scope.tileSize * 0.09);
    scope.ctx.beginPath();
    scope.ctx.arc(centerX, centerY, radius * 0.92, 0, Math.PI * 2);
    scope.ctx.stroke();
    scope.ctx.fillStyle = "rgba(0, 245, 255, 0.98)";
    scope.ctx.beginPath();
    scope.ctx.arc(centerX - radius * 0.28, centerY - radius * 0.28, highlightRadius, 0, Math.PI * 2);
    scope.ctx.fill();
    scope.ctx.restore();
  }

  function drawNpcSprite(npc, drawX, drawY) {
    const img = npc.dataUrl ? scope.getCachedImage(npc.id, npc.dataUrl) : null;
    const destW = scope.getScaledSize(npc.spriteWidth, scope.baseTileSize);
    const destH = scope.getScaledSize(npc.spriteHeight, scope.baseTileSize);
    const offsetX = drawX !== undefined ? drawX : npc.x * scope.tileSize;
    const offsetY = drawY !== undefined ? drawY : npc.y * scope.tileSize;
    if (img && img.complete && img.naturalWidth > 0) {
      scope.ctx.drawImage(img, offsetX, offsetY, destW, destH);
    } else if (img) {
      img.onload = () => draw();
    } else {
      drawPlaceholderNpcMarker(offsetX, offsetY, destW, destH);
    }
  }

  function drawSelectedNpcHighlight(npc, drawX, drawY) {
    const offsetX = drawX !== undefined ? drawX : npc.x * scope.tileSize;
    const offsetY = drawY !== undefined ? drawY : npc.y * scope.tileSize;
    const destW = Math.max(scope.tileSize, scope.getScaledSize(npc.spriteWidth, scope.baseTileSize));
    const destH = Math.max(scope.tileSize, scope.getScaledSize(npc.spriteHeight, scope.baseTileSize));
    drawSelectionReticle(offsetX, offsetY, destW, destH);
  }

  function drawNpcUiOverlay(viewportRect) {
    scope.ctx.globalCompositeOperation = "source-over";
    const visibleNpcs = scope.getVisibleNpcOverlays();
    visibleNpcs.forEach((npc) => {
      const i = scope.npcOverlays.indexOf(npc);
      if (scope.draggingNpc && scope.draggingNpc.index === i) {
        const drawWidth = scope.getScaledSize(npc.spriteWidth, scope.baseTileSize);
        const drawHeight = scope.getScaledSize(npc.spriteHeight, scope.baseTileSize);
        if (!rectIntersects(viewportRect, scope.dragDrawX, scope.dragDrawY, drawWidth, drawHeight)) {
          return;
        }
        const snapX = Math.max(0, Math.min(scope.width - 1, Math.floor((scope.dragDrawX + scope.draggingNpc.offsetX + scope.tileSize / 2) / scope.tileSize)));
        const snapY = Math.max(0, Math.min(scope.height - 1, Math.floor((scope.dragDrawY + scope.draggingNpc.offsetY + scope.tileSize / 2) / scope.tileSize)));
        scope.ctx.strokeStyle = "rgba(255,220,50,0.85)";
        scope.ctx.lineWidth = 2;
        scope.ctx.strokeRect(snapX * scope.tileSize + 1, snapY * scope.tileSize + 1, scope.tileSize - 2, scope.tileSize - 2);
        scope.ctx.globalAlpha = 0.72;
        drawNpcSprite(npc, scope.dragDrawX, scope.dragDrawY);
        scope.ctx.globalAlpha = 1.0;
        if (npc.id === scope.selectedNpcId) {
          drawSelectedNpcHighlight(npc, scope.dragDrawX, scope.dragDrawY);
        }
        return;
      }
      if (npc.id !== scope.selectedNpcId) {
        return;
      }
      if (!(npc.x >= 0 && npc.x < scope.width && npc.y >= 0 && npc.y < scope.height)) {
        return;
      }
      const drawX = npc.x * scope.tileSize;
      const drawY = npc.y * scope.tileSize;
      const drawW = Math.max(scope.tileSize, scope.getScaledSize(npc.spriteWidth, scope.baseTileSize));
      const drawH = Math.max(scope.tileSize, scope.getScaledSize(npc.spriteHeight, scope.baseTileSize));
      if (!rectIntersects(viewportRect, drawX, drawY, drawW, drawH)) {
        return;
      }
      drawSelectedNpcHighlight(npc);
    });
  }

  function drawNpcHoverLabel() {
    if (!scope.hoveredNpcId) {
      return;
    }
    const hoveredNpc = scope.npcOverlays.find((entry) => entry.id === scope.hoveredNpcId) || null;
    if (!hoveredNpc) {
      return;
    }
    const label = (hoveredNpc.name || "NPC") + " [" + hoveredNpc.id + "]";
    scope.ctx.save();
    scope.ctx.font = "12px Segoe UI, Arial, sans-serif";
    const textWidth = Math.ceil(scope.ctx.measureText(label).width);
    const boxW = textWidth + 12;
    const boxH = 22;
    const margin = 10;
    let boxX = scope.hoverCanvasX + 14;
    let boxY = scope.hoverCanvasY - boxH - 10;
    if (boxX + boxW > scope.canvas.width - margin) {
      boxX = scope.canvas.width - boxW - margin;
    }
    if (boxY < margin) {
      boxY = scope.hoverCanvasY + 14;
    }
    scope.ctx.fillStyle = "rgba(6, 14, 28, 0.92)";
    scope.ctx.strokeStyle = "rgba(110, 160, 235, 0.9)";
    scope.ctx.lineWidth = 1;
    scope.ctx.beginPath();
    scope.ctx.rect(boxX, boxY, boxW, boxH);
    scope.ctx.fill();
    scope.ctx.stroke();
    scope.ctx.fillStyle = "#d9ebff";
    scope.ctx.fillText(label, boxX + 6, boxY + 15);
    scope.ctx.restore();
  }

  function drawGhostCursor() {
    if (scope.hoverTileX < 0 || scope.hoverTileY < 0 || scope.hoverTileX >= scope.width || scope.hoverTileY >= scope.height) {
      return;
    }
    const drawX = scope.hoverTileX * scope.tileSize;
    const drawY = scope.hoverTileY * scope.tileSize;

    if (scope.activeSidebarTab === "tiles" && scope.canvasToolMode !== "select" && scope.activeBrushTileId) {
      const tile = scope.getTileEntryById(scope.activeBrushTileId);
      const symbol = String(tile.symbol || "").charAt(0);
      const img = symbol ? tileImages[symbol] : null;
      scope.ctx.save();
      scope.ctx.globalAlpha = 0.55;
      if (img && img.complete && img.naturalWidth > 0) {
        scope.ctx.drawImage(img, drawX, drawY, scope.tileSize, scope.tileSize);
      } else {
        scope.ctx.fillStyle = tile.color || scope.defaultTileColor;
        scope.ctx.fillRect(drawX, drawY, scope.tileSize, scope.tileSize);
      }
      scope.ctx.globalAlpha = 1.0;
      scope.ctx.strokeStyle = "rgba(255,255,255,0.7)";
      scope.ctx.lineWidth = 1.5;
      scope.ctx.strokeRect(drawX + 0.5, drawY + 0.5, scope.tileSize - 1, scope.tileSize - 1);
      scope.ctx.restore();
      return;
    }

    if (scope.activeSidebarTab === "instances" && scope.activeInstanceBrushId) {
      const templateEntry = scope.getNpcCatalogRecords().find((entry) => entry.id === scope.activeInstanceBrushId);
      const dataUrl = templateEntry ? templateEntry.dataUrl : null;
      const spriteW = templateEntry
        ? scope.getScaledSize((scope.spriteCatalog[templateEntry.spriteId || ""] || {}).spriteWidth, scope.baseTileSize)
        : scope.tileSize;
      const spriteH = templateEntry
        ? scope.getScaledSize((scope.spriteCatalog[templateEntry.spriteId || ""] || {}).spriteHeight, scope.baseTileSize)
        : scope.tileSize;
      scope.ctx.save();
      scope.ctx.globalAlpha = 0.55;
      if (dataUrl) {
        const img = scope.getCachedImage("__ghost__" + scope.activeInstanceBrushId, dataUrl);
        if (img && !img.complete) {
          img.onload = () => draw();
        }
        if (img.complete && img.naturalWidth > 0) {
          scope.ctx.drawImage(img, drawX, drawY, spriteW, spriteH);
        }
      } else {
        drawPlaceholderNpcMarker(drawX, drawY, spriteW, spriteH);
      }
      scope.ctx.globalAlpha = 1.0;
      scope.ctx.strokeStyle = "rgba(100,220,100,0.8)";
      scope.ctx.lineWidth = 1.5;
      scope.ctx.strokeRect(drawX + 0.5, drawY + 0.5, scope.tileSize - 1, scope.tileSize - 1);
      scope.ctx.restore();
      return;
    }

    if (scope.activeSidebarTab !== "instances") {
      return;
    }
    const selectedNpc = scope.npcOverlays.find((entry) => entry.id === scope.selectedNpcId) || null;
    if (!selectedNpc || isNpcPlaced(selectedNpc)) {
      return;
    }
    const spriteW = Math.max(1, scope.getScaledSize(selectedNpc.spriteWidth, scope.baseTileSize));
    const spriteH = Math.max(1, scope.getScaledSize(selectedNpc.spriteHeight, scope.baseTileSize));
    scope.ctx.save();
    scope.ctx.globalAlpha = 0.55;
    if (selectedNpc.dataUrl) {
      const ghostImg = scope.getCachedImage("__ghost_selected__" + selectedNpc.id, selectedNpc.dataUrl);
      if (ghostImg && !ghostImg.complete) {
        ghostImg.onload = () => draw();
      }
      if (ghostImg && ghostImg.complete && ghostImg.naturalWidth > 0) {
        scope.ctx.drawImage(ghostImg, drawX, drawY, spriteW, spriteH);
      } else {
        drawPlaceholderNpcMarker(drawX, drawY, spriteW, spriteH);
      }
    } else {
      drawPlaceholderNpcMarker(drawX, drawY, spriteW, spriteH);
    }
    scope.ctx.globalAlpha = 1.0;
    scope.ctx.strokeStyle = "rgba(95,168,255,0.92)";
    scope.ctx.lineWidth = 1.5;
    scope.ctx.strokeRect(drawX + 0.5, drawY + 0.5, scope.tileSize - 1, scope.tileSize - 1);
    scope.ctx.restore();
  }

  return {
    drawNpcUiOverlay,
    drawNpcHoverLabel,
    drawGhostCursor,
  };
}
