import { describe, expect, it } from "vitest";
import {
  aspectRatioLabel,
  detailCropRects,
  inventoryCountCropRect,
  inventoryGrid,
  inventoryRect,
  isSixteenNine,
  layoutSupportWarning,
  profileDetailRect,
} from "./layoutProfile";

const HD = { width: 1920, height: 1080 };
const QHD = { width: 2560, height: 1440 };
const ULTRAWIDE = { width: 3440, height: 1440 };

describe("layoutProfile", () => {
  it("detects 16:9 across common resolutions and rejects ultrawide", () => {
    expect(isSixteenNine(HD)).toBe(true);
    expect(isSixteenNine(QHD)).toBe(true);
    expect(isSixteenNine({ width: 3840, height: 2160 })).toBe(true);
    expect(isSixteenNine(ULTRAWIDE)).toBe(false);
    expect(isSixteenNine({ width: 1920, height: 1200 })).toBe(false); // 16:10
  });

  it("labels the aspect ratio", () => {
    expect(aspectRatioLabel(HD)).toBe("1.78:1");
    expect(aspectRatioLabel({ width: 0, height: 0 })).toBe("unknown");
  });

  it("warns only for non-16:9 resolutions", () => {
    expect(layoutSupportWarning(HD)).toBe("");
    expect(layoutSupportWarning(QHD)).toBe("");
    expect(layoutSupportWarning(ULTRAWIDE)).toContain("nicht 16:9");
    expect(layoutSupportWarning({ width: 0, height: 0 })).toBe("");
  });

  it("keeps the detail rect inside the image and on the right half", () => {
    const rect = profileDetailRect(QHD);
    expect(rect.x).toBeGreaterThanOrEqual(QHD.width * 0.45);
    expect(rect.x + rect.width).toBeLessThanOrEqual(QHD.width);
    expect(rect.y + rect.height).toBeLessThanOrEqual(QHD.height);
  });

  it("matches the calibrated 1080p artifact detail panel", () => {
    expect(profileDetailRect(HD)).toEqual({ x: 1308, y: 120, width: 492, height: 838 });
  });

  it("produces the split artifact crops in top-to-bottom order, all clamped", () => {
    const detail = profileDetailRect(QHD);
    const crops = detailCropRects(detail, QHD);
    expect(crops.map((crop) => crop.id)).toEqual([
      "artifact-name",
      "artifact-slot",
      "artifact-main-stat-label",
      "artifact-main-stat-value",
      "artifact-level",
      "artifact-substats",
      "artifact-set-effects",
      "artifact-footer",
    ]);
    let previousY = -1;
    for (const crop of crops) {
      expect(crop.rect.x).toBeGreaterThanOrEqual(0);
      expect(crop.rect.y).toBeGreaterThan(previousY);
      expect(crop.rect.x + crop.rect.width).toBeLessThanOrEqual(QHD.width);
      expect(crop.rect.y + crop.rect.height).toBeLessThanOrEqual(QHD.height);
      previousY = crop.rect.y;
    }
  });

  it("matches 1080p artifact field crops", () => {
    const detail = profileDetailRect(HD);
    const crops = Object.fromEntries(detailCropRects(detail, HD).map((crop) => [crop.id, crop.rect]));
    expect(crops["artifact-slot"]).toEqual({ x: 1328, y: 185, width: 234, height: 40 });
    expect(crops["artifact-main-stat-label"]).toEqual({ x: 1328, y: 264, width: 224, height: 35 });
    expect(crops["artifact-level"]).toEqual({ x: 1333, y: 425, width: 70, height: 35 });
    expect(crops["artifact-substats"]).toEqual({ x: 1338, y: 473, width: 408, height: 193 });
  });

  it("uses a tighter substat crop in the fast auto-scan profile", () => {
    const detail = profileDetailRect(HD);
    const crops = Object.fromEntries(detailCropRects(detail, HD, { fastProfile: true }).map((crop) => [crop.id, crop.rect]));
    expect(crops["artifact-substats"]).toEqual({ x: 1338, y: 473, width: 408, height: 154 });
  });

  it("shifts level and substat crops for sanctified artifacts", () => {
    const detail = profileDetailRect(HD);
    const crops = Object.fromEntries(detailCropRects(detail, HD, { sanctified: true }).map((crop) => [crop.id, crop.rect]));
    expect(crops["artifact-level"]).toEqual({ x: 1333, y: 468, width: 70, height: 35 });
    expect(crops["artifact-substats"]).toEqual({ x: 1338, y: 517, width: 408, height: 193 });
  });

  it("places the inventory count crop inside the inventory panel", () => {
    const detail = profileDetailRect(QHD);
    const inv = inventoryRect(QHD, detail);
    const count = inventoryCountCropRect(inv, QHD);
    expect(count.x).toBeGreaterThan(QHD.width * 0.75);
    expect(count.x + count.width).toBeLessThanOrEqual(QHD.width);
  });

  it("builds the calibrated 8-column inventory grid on the left", () => {
    const detail = profileDetailRect(QHD);
    const grid = inventoryGrid(QHD, detail);
    expect(grid.cols).toBe(8);
    expect(grid.rows).toBe(4);
    expect(grid.source).toBe("detected");
    expect(grid.centers).toHaveLength(32);
    expect(grid.centers.every((center) => center.x < detail.x)).toBe(true);
  });

  it("matches the live 1080p artifact grid centers", () => {
    const detail = profileDetailRect(HD);
    const grid = inventoryGrid(HD, detail);
    expect(grid.centers[0]).toEqual({ x: 179, y: 254, row: 0, col: 0 });
    expect(grid.centers[7]).toEqual({ x: 1201, y: 254, row: 0, col: 7 });
    expect(grid.centers.at(-1)).toEqual({ x: 1201, y: 782, row: 3, col: 7 });
  });

  it("reports a missing grid when the inventory panel is too small", () => {
    const tiny = { width: 320, height: 180 };
    const grid = inventoryGrid(tiny, profileDetailRect(tiny));
    expect(grid.source).toBe("missing");
    expect(grid.centers).toHaveLength(0);
  });
});
