/**
 * uok-run-context.test.mjs — verify the schema-v2 run-context adapter
 * (slice 2 of "Make UOK the SF Control Plane").
 */
import { describe, expect, test } from "vitest";
import {
	buildUokRunContext,
	OPTIONAL_UOK_RUN_CONTEXT_KEYS,
	REQUIRED_UOK_RUN_CONTEXT_KEYS,
	uokRunContextToGateColumns,
	VALID_PERMISSION_PROFILES,
	VALID_RUN_CONTROLS,
	VALID_SURFACES,
} from "../uok/run-context.js";

const VALID_BASE = {
	surface: "headless",
	runControl: "supervised",
	permissionProfile: "high",
	traceId: "flow-123",
};

describe("buildUokRunContext", () => {
	test("returns_a_frozen_normalized_context_when_all_required_fields_are_present", () => {
		const ctx = buildUokRunContext({
			...VALID_BASE,
			parentTrace: "flow-100",
			unitType: "execute-task",
			unitId: "M001/S01/T02",
			milestoneId: "M001",
			sliceId: "S01",
			taskId: "T02",
		});
		expect(ctx).toBeTruthy();
		expect(Object.isFrozen(ctx)).toBe(true);
		expect(ctx.surface).toBe("headless");
		expect(ctx.runControl).toBe("supervised");
		expect(ctx.permissionProfile).toBe("high");
		expect(ctx.traceId).toBe("flow-123");
		expect(ctx.parentTrace).toBe("flow-100");
		expect(ctx.unitType).toBe("execute-task");
	});

	test("returns_null_when_any_required_key_is_missing", () => {
		for (const key of REQUIRED_UOK_RUN_CONTEXT_KEYS) {
			const opts = { ...VALID_BASE };
			delete opts[key];
			expect(
				buildUokRunContext(opts),
				`missing ${key} should return null`,
			).toBe(null);
		}
	});

	test("returns_null_on_invalid_surface_runControl_or_permissionProfile", () => {
		expect(buildUokRunContext({ ...VALID_BASE, surface: "rogue" })).toBe(null);
		expect(buildUokRunContext({ ...VALID_BASE, runControl: "rogue" })).toBe(
			null,
		);
		expect(
			buildUokRunContext({ ...VALID_BASE, permissionProfile: "rogue" }),
		).toBe(null);
	});

	test("treats_empty_string_required_fields_as_missing", () => {
		expect(buildUokRunContext({ ...VALID_BASE, surface: "   " })).toBe(null);
		expect(buildUokRunContext({ ...VALID_BASE, traceId: "" })).toBe(null);
	});

	test("omits_optional_keys_when_empty_or_absent", () => {
		const ctx = buildUokRunContext({
			...VALID_BASE,
			parentTrace: "",
			unitType: undefined,
		});
		expect(ctx).toBeTruthy();
		expect(ctx.parentTrace).toBeUndefined();
		expect(ctx.unitType).toBeUndefined();
	});

	test("rejects_non_object_input", () => {
		expect(buildUokRunContext(null)).toBe(null);
		expect(buildUokRunContext("not an object")).toBe(null);
		expect(buildUokRunContext(undefined)).toBe(null);
	});

	test("only_recognized_optional_keys_are_kept", () => {
		const ctx = buildUokRunContext({
			...VALID_BASE,
			randomField: "ignored",
			anotherJunk: "also ignored",
		});
		expect(ctx).toBeTruthy();
		for (const key of Object.keys(ctx)) {
			expect(
				[
					...REQUIRED_UOK_RUN_CONTEXT_KEYS,
					...OPTIONAL_UOK_RUN_CONTEXT_KEYS,
				].includes(key),
				`unexpected key in normalized ctx: ${key}`,
			).toBe(true);
		}
	});

	test("all_documented_enum_values_are_accepted", () => {
		for (const surface of VALID_SURFACES) {
			expect(buildUokRunContext({ ...VALID_BASE, surface })?.surface).toBe(
				surface,
			);
		}
		for (const runControl of VALID_RUN_CONTROLS) {
			expect(
				buildUokRunContext({ ...VALID_BASE, runControl })?.runControl,
			).toBe(runControl);
		}
		for (const permissionProfile of VALID_PERMISSION_PROFILES) {
			expect(
				buildUokRunContext({ ...VALID_BASE, permissionProfile })
					?.permissionProfile,
			).toBe(permissionProfile);
		}
	});
});

describe("uokRunContextToGateColumns", () => {
	test("translates_camelCase_to_snake_case_column_shape", () => {
		const ctx = buildUokRunContext({
			...VALID_BASE,
			parentTrace: "flow-100",
		});
		const cols = uokRunContextToGateColumns(ctx);
		expect(cols).toEqual({
			surface: "headless",
			run_control: "supervised",
			permission_profile: "high",
			trace_id: "flow-123",
			parent_trace: "flow-100",
		});
	});

	test("nulls_parent_trace_when_omitted", () => {
		const ctx = buildUokRunContext(VALID_BASE);
		const cols = uokRunContextToGateColumns(ctx);
		expect(cols.parent_trace).toBe(null);
	});

	test("returns_null_for_invalid_ctx", () => {
		expect(uokRunContextToGateColumns(null)).toBe(null);
		expect(uokRunContextToGateColumns({})).toBe(null);
		expect(uokRunContextToGateColumns({ surface: "headless" })).toBe(null);
	});
});
