import { readFileSync } from "node:fs";
import { dirname, join } from "node:path";
import { fileURLToPath } from "node:url";
import { describe, expect, it } from "vitest";
import { runAbb120Suite } from "../../src/suites/abb120Suite.js";
import { parseGrl } from "../../src/grl/parser/index.js";
import { compileSemanticProgram } from "../../src/grl/semantic/index.js";
import { ABB_IRB120_ZERO_JOINTS } from "../fixtures/abbIrb120.js";

const WEB_ROOT = join(dirname(fileURLToPath(import.meta.url)), "../..");
const PROGRAM_DIR = join(WEB_ROOT, "tests", "fixtures", "abb120", "programs");
const APP_DIR = join(WEB_ROOT, "app");
const PROGRAM_NAMES = [
  "A120_00_Smoke.grl",
  "A120_10_JointPickPlace.grl",
  "A120_20_CartesianBlend.grl",
  "A120_30_IOWaitPulse.grl",
  "A120_40_ErrorDiagnostics.grl",
  "A120_50_OperationProcess.grl"
];

function loadPrograms() {
  return PROGRAM_NAMES.map((name) => ({
    name,
    text: readFileSync(join(PROGRAM_DIR, name), "utf8")
  }));
}

describe("ABB120 suite artifacts", () => {
  it("ships six parseable GRL programs with source maps and KDL bridge requests", () => {
    for (const program of loadPrograms()) {
      const ast = parseGrl(program.text);
      const ir = compileSemanticProgram(ast, {
        startJoints: [...ABB_IRB120_ZERO_JOINTS],
        sampleTime: 0.02
      });
      expect(ast.kind).toBe("Program");
      expect(ir.moduleName).toMatch(/^A120/);
      expect(ir.sourceMap.length + ir.kdlBridge.motionRequests.length + ir.kdlBridge.pathRequests.length).toBeGreaterThan(0);
    }
  });

  it("creates job, post, roundtrip, report, delivery, and screenshot evidence paths", () => {
    const job = runAbb120Suite(loadPrograms(), { now: "2026-06-27T12:00:00.000Z" });

    expect(job.job_id).toBe("A120-JOB-20260627120000-doc");
    expect(job.robot.robotId).toBe("abb_irb120_3_58");
    expect(job.programs.map((program) => program.name)).toEqual(PROGRAM_NAMES);
    expect(job.post.filenames).toEqual(expect.arrayContaining([
      "A120Smoke.mod",
      "A120Smoke.ls",
      "A120Smoke.src"
    ]));
    expect(job.roundtrip.status).toMatch(/pass|warn/);
    expect(job.report_id).toBe("A120-REPORT-20260627120000");
    expect(job.artifacts).toMatchObject({
      jobJson: "A120-JOB-20260627120000-doc/job.json",
      reportHtml: "A120-JOB-20260627120000-doc/reports/A120-REPORT-20260627120000.html",
      deliveryPackageJson: "A120-JOB-20260627120000-doc/delivery/package.json",
      desktopScreenshot: "A120-JOB-20260627120000-doc/screenshots/virtual-controller-desktop.png",
      mobileScreenshot: "A120-JOB-20260627120000-doc/screenshots/virtual-controller-mobile.png"
    });
  });

  it("has an HTML virtual controller entry with required panels", () => {
    const html = readFileSync(join(APP_DIR, "virtual-controller.html"), "utf8");
    const css = readFileSync(join(APP_DIR, "virtual-controller.css"), "utf8");
    const js = readFileSync(join(APP_DIR, "virtual-controller.js"), "utf8");

    expect(html).toContain("ABB120 Station");
    expect(html).toContain("Path: pick_place");
    expect(html).toContain("Controller");
    expect(html).toContain("Motion Queue");
    expect(html).toContain("Reports");
    expect(html).toContain('src="./virtual-controller.js"');
    expect(html).not.toContain('src="./virtual-controller.ts"');
    expect(css).toContain(".viewport");
    expect(css).toContain("@media");
    expect(js).toContain("data-command");
    expect(js).toContain("data-tab");
  });
});
