import { describe, expect, it } from "vitest";
import {
  automationBlockReason,
  buildInventoryPagePlan,
  buildGridModel,
  requiresAdminForAutomation,
} from "./automationPlanner";

describe("automationPlanner", () => {
  it("requires admin whenever this app's own process is not elevated", () => {
    expect(requiresAdminForAutomation({ ok: true, isElevated: false, platform: "win32" })).toBe(true);
    expect(requiresAdminForAutomation({ ok: true, isElevated: true, platform: "win32" })).toBe(false);
    expect(requiresAdminForAutomation({ ok: false, isElevated: false, platform: "win32" })).toBe(false);
    expect(requiresAdminForAutomation(null)).toBe(false);
  });

  it("returns a user-facing admin block reason when not elevated", () => {
    expect(automationBlockReason({ ok: true, isElevated: false, platform: "win32" })).toContain("Administrator");
    expect(automationBlockReason({ ok: true, isElevated: true, platform: "win32" })).toBe("");
  });

  it("builds a dense click grid from partial detected centers", () => {
    const grid = buildGridModel({
      rows: 3,
      cols: 4,
      confidence: 96,
      source: "detected",
      centers: [
        { row: 0, col: 0, x: 100, y: 200 },
        { row: 0, col: 1, x: 220, y: 200 },
        { row: 0, col: 3, x: 460, y: 200 },
        { row: 2, col: 0, x: 100, y: 500 },
        { row: 2, col: 3, x: 460, y: 500 },
      ],
    });

    expect(grid).not.toBeNull();
    expect(grid?.targets).toHaveLength(12);
    expect(grid?.stepX).toBe(120);
    expect(grid?.stepY).toBe(150);
    expect(grid?.targets.find((target) => target.row === 1 && target.col === 2)).toMatchObject({ x: 340, y: 350 });
  });

  it("plans overlapping inventory pages like Inventory Kamera for a partial final page", () => {
    const targets = Array.from({ length: 40 }, (_, index) => ({
      row: Math.floor(index / 8),
      col: index % 8,
      x: index * 10,
      y: index * 10,
    }));

    const firstPage = buildInventoryPagePlan({
      targets,
      cols: 8,
      rows: 5,
      totalTargetCount: 50,
      processedTargets: 0,
      rowsQueued: 0,
    });
    expect(firstPage.pageTargets).toHaveLength(40);
    expect(firstPage.startIndex).toBe(0);
    expect(firstPage.scrollRowsAfterPage).toBe(2);

    const finalPage = buildInventoryPagePlan({
      targets,
      cols: 8,
      rows: 5,
      totalTargetCount: 50,
      processedTargets: 40,
      rowsQueued: 5,
    });
    expect(finalPage.pageTargets).toHaveLength(10);
    expect(finalPage.startIndex).toBe(24);
    expect(finalPage.pageTargets[0]).toMatchObject({ row: 3, col: 0 });
    expect(finalPage.scrollRowsAfterPage).toBe(0);
  });

  it("keeps the first page top-aligned when the whole inventory fits inside one visible page", () => {
    const targets = Array.from({ length: 40 }, (_, index) => ({
      row: Math.floor(index / 8),
      col: index % 8,
      x: index * 10,
      y: index * 10,
    }));

    const singlePage = buildInventoryPagePlan({
      targets,
      cols: 8,
      rows: 5,
      totalTargetCount: 16,
      processedTargets: 0,
      rowsQueued: 0,
    });

    expect(singlePage.pageTargets).toHaveLength(16);
    expect(singlePage.startIndex).toBe(0);
    expect(singlePage.pageTargets[0]).toMatchObject({ row: 0, col: 0 });
    expect(singlePage.pageTargets[15]).toMatchObject({ row: 1, col: 7 });
    expect(singlePage.scrollRowsAfterPage).toBe(0);
  });
});
