// Resolution-anchored layout geometry for the artifact inventory screen
// (ADR-009). Inventory Kamera's proven approach is to require borderless 16:9 and
// derive crop/grid coordinates from the client rectangle instead of detecting the
// panel by colour each frame. This module is the single, pure, unit-tested source
// of that geometry; electron/main.ts consumes it for cropping and keeps a
// colour-based detail-rect detector only as a fallback for off-profile setups.
//
// NOTE: the per-field detail crop fractions below are the current working values.
// True IK-style fixed coordinates need calibration against a reference 16:9
// screenshot; the structure here is what those calibrated numbers slot into.

export interface LayoutRect {
  x: number;
  y: number;
  width: number;
  height: number;
}

export interface CropTemplateRect {
  id: string;
  label: string;
  rect: LayoutRect;
}

export interface InventoryGridLayout {
  centers: Array<{ x: number; y: number; row: number; col: number }>;
  rows: number;
  cols: number;
  confidence: number;
  source: "detected" | "missing";
}

const SIXTEEN_NINE = 16 / 9;

export function aspectRatio(size: { width: number; height: number }): number {
  if (!size.height) return 0;
  return size.width / size.height;
}

export function aspectRatioLabel(size: { width: number; height: number }): string {
  const ratio = aspectRatio(size);
  if (ratio === 0) return "unknown";
  return `${ratio.toFixed(2)}:1`;
}

// Genshin's UI is authored for 16:9; other aspect ratios letterbox or reflow and
// the anchored crops no longer line up. Allow a small tolerance for rounding.
export function isSixteenNine(size: { width: number; height: number }, tolerance = 0.02): boolean {
  const ratio = aspectRatio(size);
  if (ratio === 0) return false;
  return Math.abs(ratio - SIXTEEN_NINE) <= SIXTEEN_NINE * tolerance;
}

// Empty when the client is a supported 16:9; otherwise a warning explaining that
// the anchored crops are unreliable off-profile (ADR-009: non-16:9 is explicitly
// unsupported for the auto scanner).
export function layoutSupportWarning(size: { width: number; height: number }): string {
  if (size.width <= 0 || size.height <= 0) return "";
  if (isSixteenNine(size)) return "";
  return `Aufloesung ${size.width}x${size.height} ist nicht 16:9 (${aspectRatioLabel(size)}). Der Auto-Scan ist auf 16:9 im randlosen Fenstermodus ausgelegt; die Erkennung kann daneben liegen.`;
}

export function clampRect(rect: LayoutRect, imageSize: { width: number; height: number }): LayoutRect {
  const x = Math.max(0, Math.min(imageSize.width - 1, rect.x));
  const y = Math.max(0, Math.min(imageSize.height - 1, rect.y));
  const maxWidth = Math.max(1, imageSize.width - x);
  const maxHeight = Math.max(1, imageSize.height - y);
  return {
    x,
    y,
    width: Math.max(1, Math.min(maxWidth, rect.width)),
    height: Math.max(1, Math.min(maxHeight, rect.height)),
  };
}

// Anchored guess for the artifact detail panel on the right of the screen. Used
// as the primary rect for a clean 16:9 client and as the fallback when colour
// detection cannot find the panel.
export function profileDetailRect(imageSize: { width: number; height: number }): LayoutRect {
  const { width, height } = imageSize;
  if (width <= 0 || height <= 0) return { x: 0, y: 0, width: Math.max(1, width), height: Math.max(1, height) };
  return clampRect(
    {
      x: Math.round(width * 0.5),
      y: Math.round(height * 0.08),
      width: Math.round(width * 0.46),
      height: Math.round(height * 0.74),
    },
    imageSize,
  );
}

// The four OCR crops inside the detail panel, as fractions of the detail rect.
export function detailCropRects(detailRect: LayoutRect, imageSize: { width: number; height: number }): CropTemplateRect[] {
  const templates: CropTemplateRect[] = [
    {
      id: "artifact-title",
      label: "Artifact title",
      rect: {
        x: Math.round(detailRect.x + detailRect.width * 0.055),
        y: Math.round(detailRect.y + detailRect.height * 0.05),
        width: Math.round(detailRect.width * 0.82),
        height: Math.round(detailRect.height * 0.16),
      },
    },
    {
      id: "artifact-main-stat",
      label: "Main stat",
      rect: {
        x: Math.round(detailRect.x + detailRect.width * 0.055),
        y: Math.round(detailRect.y + detailRect.height * 0.2),
        width: Math.round(detailRect.width * 0.82),
        height: Math.round(detailRect.height * 0.18),
      },
    },
    {
      id: "artifact-substats",
      label: "Substats",
      rect: {
        x: Math.round(detailRect.x + detailRect.width * 0.055),
        y: Math.round(detailRect.y + detailRect.height * 0.41),
        width: Math.round(detailRect.width * 0.82),
        height: Math.round(detailRect.height * 0.25),
      },
    },
    {
      id: "artifact-footer",
      label: "Footer",
      rect: {
        x: Math.round(detailRect.x + detailRect.width * 0.055),
        y: Math.round(detailRect.y + detailRect.height * 0.78),
        width: Math.round(detailRect.width * 0.82),
        height: Math.round(detailRect.height * 0.16),
      },
    },
  ];

  return templates.map((template) => ({ ...template, rect: clampRect(template.rect, imageSize) }));
}

export function inventoryCountCropRect(inventoryRect: LayoutRect, imageSize: { width: number; height: number }): LayoutRect {
  return clampRect(
    {
      x: Math.round(inventoryRect.x + inventoryRect.width * 0.62),
      y: Math.round(inventoryRect.y + inventoryRect.height * 0.02),
      width: Math.round(inventoryRect.width * 0.34),
      height: Math.round(inventoryRect.height * 0.09),
    },
    imageSize,
  );
}

export function inventoryRect(imageSize: { width: number; height: number }, detailRect: LayoutRect): LayoutRect {
  const { width, height } = imageSize;
  const preferredWidth = Math.max(140, Math.round(width * 0.48));
  const x = Math.round(width * 0.03);
  const y = Math.round(detailRect.y + detailRect.height * 0.09);
  const availableWidth = Math.max(100, detailRect.x - Math.round(width * 0.04));
  const panelWidth = Math.max(100, Math.min(preferredWidth, availableWidth));
  const safeWidth = panelWidth > width * 0.85 ? Math.round(width * 0.55) : panelWidth;
  return clampRect(
    {
      x,
      y,
      width: Math.min(safeWidth, Math.max(width - x - Math.round(width * 0.02), 100)),
      height: Math.max(140, Math.round(height * 0.7)),
    },
    imageSize,
  );
}

export function inventoryGrid(imageSize: { width: number; height: number }, detailRect: LayoutRect): InventoryGridLayout {
  const rect = inventoryRect(imageSize, detailRect);
  const cols = 5;
  if (rect.width < 160 || rect.height < 140) {
    return { centers: [], rows: 0, cols: 0, confidence: 0, source: "missing" };
  }

  const cellWidth = Math.max(56, Math.round(rect.width / cols));
  const stepX = Math.round(cellWidth * 0.96);
  const stepY = Math.round(cellWidth * 1.03);
  const visibleRows = Math.max(2, Math.min(6, Math.round(rect.height / Math.max(stepY, 1))));

  const startX = rect.x + Math.max(6, Math.round(stepX * 0.45));
  const startY = rect.y + Math.max(6, Math.round(stepY * 0.45));
  const centers: InventoryGridLayout["centers"] = [];
  for (let row = 0; row < visibleRows; row++) {
    for (let col = 0; col < cols; col++) {
      const x = startX + col * stepX;
      const y = startY + row * stepY;
      if (x < imageSize.width && y < imageSize.height) {
        centers.push({ x, y, row, col });
      }
    }
  }

  const trimmed = centers.filter((center) => center.x > 0 && center.y > 0);
  return {
    centers: trimmed,
    rows: visibleRows,
    cols,
    confidence: trimmed.length >= cols * 2 ? 76 : trimmed.length >= cols ? 58 : 36,
    source: "detected",
  };
}
