import { createHash } from "node:crypto";
import { beforeAll, describe, expect, test } from "vitest";
import type { Core } from "../src/platform/core/index";
import { loadWasmCoreForTest } from "./setup-wasm";

let core: Core;

beforeAll(async () => {
	core = await loadWasmCoreForTest();
});

describe("WasmCore.signRequest", () => {
	test("returns canonical bytes that lead with the v1 domain marker", () => {
		const fields = {
			protocolVersion: "v1",
			deviceSessionId: "device-session-1",
			messageType: "user.account.get",
			timestampMs: 1700000000000n,
			requestId: "req-1",
			payloadHash: sha256("payload"),
		};
		const canonical = core.signRequest(fields);
		const marker = "galaxy-request-v1";
		expect(canonical.length).toBeGreaterThan(marker.length);
		expect(new TextDecoder().decode(canonical.slice(1, 1 + marker.length))).toBe(
			marker,
		);
	});
});

describe("WasmCore.verifyResponse", () => {
	test("rejects a flipped-bit signature", () => {
		const publicKey = new Uint8Array(32);
		const signature = new Uint8Array(64);
		const fields = {
			protocolVersion: "v1",
			requestId: "req-1",
			timestampMs: 1700000000000n,
			resultCode: "ok",
			payloadHash: sha256("payload"),
		};
		expect(core.verifyResponse(publicKey, signature, fields)).toBe(false);
	});

	test("returns false for malformed key/signature lengths", () => {
		const fields = {
			protocolVersion: "v1",
			requestId: "req-1",
			timestampMs: 1700000000000n,
			resultCode: "ok",
			payloadHash: sha256("payload"),
		};
		expect(
			core.verifyResponse(new Uint8Array(8), new Uint8Array(64), fields),
		).toBe(false);
	});
});

describe("WasmCore.verifyEvent", () => {
	test("rejects an empty signature", () => {
		const fields = {
			eventType: "gateway.server_time",
			eventId: "evt-1",
			timestampMs: 1700000000000n,
			requestId: "req-1",
			traceId: "trace-1",
			payloadHash: sha256("event"),
		};
		expect(
			core.verifyEvent(new Uint8Array(32), new Uint8Array(0), fields),
		).toBe(false);
	});
});

describe("WasmCore.verifyPayloadHash", () => {
	test("accepts the SHA-256 of the supplied payload", () => {
		const payload = new TextEncoder().encode("hello");
		expect(core.verifyPayloadHash(payload, sha256("hello"))).toBe(true);
	});

	test("rejects a digest of unrelated bytes", () => {
		const payload = new TextEncoder().encode("hello");
		expect(core.verifyPayloadHash(payload, sha256("world"))).toBe(false);
	});

	test("rejects a payload_hash whose length is not 32", () => {
		const payload = new TextEncoder().encode("hello");
		expect(core.verifyPayloadHash(payload, new Uint8Array(16))).toBe(false);
	});
});

function sha256(value: string): Uint8Array {
	return new Uint8Array(createHash("sha256").update(value).digest());
}
