import { describe, expect, it } from "vitest";
import { postProcessAllBrands } from "../../src/grl/post/index.js";
import { parseGrl } from "../../src/grl/parser/index.js";
import { compileSemanticProgram } from "../../src/grl/semantic/index.js";

const PROGRAM = `language grl 0.1
module PostDemo
  post_hint abb
  const speed vj = joint(50 %)
  const speed vl = linear(200 mm/s)
  const zone z10 = z(10 mm)
  target home = joint_target { joints: [0 deg] }
  target pick = pose_target { pose: pose(500 mm, 0 mm, 0 mm, 0 deg, 0 deg, 0 deg) }
  target mid = pose_target { pose: pose(550 mm, 50 mm, 0 mm, 0 deg, 0 deg, 0 deg) }
  target place = pose_target { pose: pose(600 mm, 0 mm, 0 mm, 0 deg, 0 deg, 0 deg) }
  proc main()
    set_speed vl
    set_zone z10
    movej home speed vj zone fine
    movel pick speed vl zone z10
    movec via mid target place speed vl zone fine
    io.do[1] = true
    wait io.di[1] == true timeout 1 s
    pulse io.do[2] duration 100 ms
    alarm DONE "done"
  end
end
`;

function postAll() {
  const ir = compileSemanticProgram(parseGrl(PROGRAM), {
    startJoints: [0],
    sampleTime: 0.004
  });
  return postProcessAllBrands(ir);
}

describe("GRL multi-brand postprocessor", () => {
  it("emits stable ABB, FANUC, and KUKA golden text", () => {
    const result = postAll();

    expect(result.outputs.abb.text).toBe(`MODULE PostDemo
  PROC main()
    MoveJ home,v50,fine,tool0;
    MoveL pick,v200,z10,tool0;
    MoveC mid,place,v200,fine,tool0;
    SetDO io.do[1],TRUE;
    WaitUntil io . di [ 1 ] == true;
    PulseDO io.do[2],0.100;
    ! unsupported ALARM
  ENDPROC
ENDMODULE`);
    expect(result.outputs.fanuc.text).toBe(`/PROG MAIN
/MN
  1: J home 50% FINE ;
  2: L pick 200mm/sec CNT10 ;
  3: C mid place 200mm/sec FINE ;
  4: DO[1]=TRUE ;
  5: WAIT (io . di [ 1 ] == true) ;
  6: PULSE DO[2] 100ms ;
  7: ! unsupported ALARM ;
/END`);
    expect(result.outputs.kuka.text).toBe(`DEF Main()
  PTP home Vel=50%
  LIN pick Vel=0.200m/s C_DIS
  CIRC mid, place Vel=0.200m/s
  $OUT[1] = TRUE
  WAIT FOR io . di [ 1 ] == true
  PULSE $OUT[2] 0.100
  ! unsupported ALARM
END`);
  });

  it("reports unsupported semantics and ignored brand hints", () => {
    const result = postAll();

    expect(result.outputs.abb.filename).toBe("PostDemo.mod");
    expect(result.outputs.fanuc.filename).toBe("PostDemo.ls");
    expect(result.outputs.kuka.filename).toBe("PostDemo.src");
    expect(result.report).toEqual([
      expect.objectContaining({ brand: "abb", code: "GRL_POST_UNSUPPORTED", message: expect.stringContaining("ALARM") }),
      expect.objectContaining({ brand: "fanuc", code: "GRL_POST_HINT_IGNORED" }),
      expect.objectContaining({ brand: "fanuc", code: "GRL_POST_UNSUPPORTED", message: expect.stringContaining("ALARM") }),
      expect.objectContaining({ brand: "kuka", code: "GRL_POST_HINT_IGNORED" }),
      expect.objectContaining({ brand: "kuka", code: "GRL_POST_UNSUPPORTED", message: expect.stringContaining("ALARM") })
    ]);
  });
});
