/** Привязка нормализованных координат токена к центру ячейки сетки сцены. */

import type { SceneGrid } from './sceneGrid';

function clamp01(n: number): number {
  return Math.max(0, Math.min(1, n));
}

function cellPx(sizeN: number, contentW: number, contentH: number): number {
  const minDim = Math.min(contentW, contentH);
  return Math.max(4, sizeN * minDim);
}

function snapSquare(
  nx: number,
  ny: number,
  contentW: number,
  contentH: number,
  sizeN: number,
): { nx: number; ny: number } {
  const cell = cellPx(sizeN, contentW, contentH);
  const px = nx * contentW;
  const py = ny * contentH;
  const col = Math.round(px / cell - 0.5);
  const row = Math.round(py / cell - 0.5);
  return {
    nx: clamp01(((col + 0.5) * cell) / contentW),
    ny: clamp01(((row + 0.5) * cell) / contentH),
  };
}

/**
 * Flat-top hex, как в `SceneGridOverlay.drawHexGrid`:
 * центры `(col * horiz, row * vert + (col % 2 === 0 ? 0 : vert/2))`.
 */
function snapHex(
  nx: number,
  ny: number,
  contentW: number,
  contentH: number,
  sizeN: number,
): { nx: number; ny: number } {
  const cell = cellPx(sizeN, contentW, contentH);
  const hexW = cell;
  const vert = (Math.sqrt(3) / 2) * hexW;
  const horiz = hexW * 0.75;
  const px = nx * contentW;
  const py = ny * contentH;
  const col0 = Math.round(px / horiz);
  const row0 = Math.round(py / vert);

  let bestNx = nx;
  let bestNy = ny;
  let bestD = Number.POSITIVE_INFINITY;
  for (let col = col0 - 2; col <= col0 + 2; col++) {
    for (let row = row0 - 2; row <= row0 + 2; row++) {
      const cx = col * horiz;
      const cy = row * vert + (col % 2 === 0 ? 0 : vert / 2);
      const d = (cx - px) * (cx - px) + (cy - py) * (cy - py);
      if (d < bestD) {
        bestD = d;
        bestNx = cx / contentW;
        bestNy = cy / contentH;
      }
    }
  }
  return { nx: clamp01(bestNx), ny: clamp01(bestNy) };
}

/**
 * Snap центра токена к ближайшему центру ячейки.
 * Если сетка выключена / нет размеров — координаты без изменений.
 */
export function snapNormToGridCell(
  nx: number,
  ny: number,
  grid: Pick<SceneGrid, 'enabled' | 'type' | 'sizeN'> | null | undefined,
  contentW: number,
  contentH: number,
): { nx: number; ny: number } {
  if (!grid?.enabled) return { nx, ny };
  if (!(contentW > 0) || !(contentH > 0)) return { nx, ny };
  if (!Number.isFinite(nx) || !Number.isFinite(ny)) return { nx, ny };
  if (grid.type === 'hex') {
    return snapHex(nx, ny, contentW, contentH, grid.sizeN);
  }
  return snapSquare(nx, ny, contentW, contentH, grid.sizeN);
}
