import assert from "node:assert/strict";
import { test } from "node:test";
import { helloPayloadSchema, parse } from "../src/modules/trapos-cloud-gateway/protocol.js";

test("parses all four event types", () => {
  const cReq = parse(
    JSON.stringify({ event: "computer_request", traposSenderId: "7:", messageId: "m1", type: "health", payload: {} }),
  );
  assert.equal(cReq.event, "computer_request");

  const cRes = parse(
    JSON.stringify({ event: "computer_response", traposSenderId: "7:", messageId: "m1", type: "ping", ok: true, payload: { traposId: "7:" } }),
  );
  assert.equal(cRes.event, "computer_response");

  const gReq = parse(
    JSON.stringify({ event: "server_request", traposReceiverId: "7:", messageId: "m2", type: "ping", payload: {} }),
  );
  assert.equal(gReq.event, "server_request");

  const gRes = parse(
    JSON.stringify({ event: "server_response", traposReceiverId: "7:", messageId: "m2", type: "health", ok: true, payload: {} }),
  );
  assert.equal(gRes.event, "server_response");
});

test("parses an ok:false response with error", () => {
  const frame = parse(
    JSON.stringify({ event: "computer_response", traposSenderId: "7:", messageId: "m1", type: "ping", ok: false, error: { code: "internal", message: "boom" } }),
  );
  assert.equal(frame.event, "computer_response");
  if (frame.event === "computer_response") {
    assert.equal(frame.ok, false);
    assert.deepEqual(frame.error, { code: "internal", message: "boom" });
  }
});

test("normalizes empty-payload gotcha: [] / missing / non-object -> {}", () => {
  const fromArray = parse(
    JSON.stringify({ event: "computer_request", traposSenderId: "7:", messageId: "m1", type: "health", payload: [] }),
  );
  assert.deepEqual(fromArray.payload, {});

  const fromMissing = parse(
    JSON.stringify({ event: "computer_request", traposSenderId: "7:", messageId: "m1", type: "health" }),
  );
  assert.deepEqual(fromMissing.payload, {});

  const fromScalar = parse(
    JSON.stringify({ event: "computer_request", traposSenderId: "7:", messageId: "m1", type: "health", payload: 5 }),
  );
  assert.deepEqual(fromScalar.payload, {});
});

test("throws on malformed JSON", () => {
  assert.throws(() => parse("not json"));
});

test("throws on unknown event", () => {
  assert.throws(() =>
    parse(JSON.stringify({ event: "bogus", traposSenderId: "7:", messageId: "m1", type: "x", payload: {} })),
  );
});

test("throws on missing required fields", () => {
  assert.throws(() =>
    parse(JSON.stringify({ event: "computer_request", messageId: "m1", type: "x", payload: {} })),
  );
  assert.throws(() =>
    parse(JSON.stringify({ event: "computer_request", traposSenderId: "7:", type: "x", payload: {} })),
  );
});

test("does NOT validate type (unknown type is a dispatch concern)", () => {
  const frame = parse(
    JSON.stringify({ event: "computer_request", traposSenderId: "7:", messageId: "m1", type: "totally_made_up", payload: {} }),
  );
  assert.equal(frame.type, "totally_made_up");
});

test("hello payload schema: requires non-empty traposId, secret optional", () => {
  assert.equal(helloPayloadSchema.safeParse({ traposId: "7:", secret: "x" }).success, true);
  assert.equal(helloPayloadSchema.safeParse({ traposId: "7:" }).success, true);
  assert.equal(helloPayloadSchema.safeParse({ traposId: "" }).success, false);
  assert.equal(helloPayloadSchema.safeParse({ secret: "x" }).success, false);
});
