import { buildAuditEnvelope, emitUokAuditEvent } from "./audit.js";
import { ChaosMonkey } from "./chaos-monkey.js";
import {
	writeTurnCloseoutGitRecord,
	writeTurnGitTransaction,
} from "./gitops.js";
import {
	acquireWriterToken,
	nextWriteRecord,
	releaseWriterToken,
} from "./writer.js";
export function createTurnObserver(options) {
	let current = null;
	let writerToken = null;
	const phaseResults = [];
	const chaosMonkey = options.enableChaosMonkey ? new ChaosMonkey() : null;

	function nextSequenceMetadata(category, operation, metadata) {
		if (!writerToken) return metadata ?? {};
		const record = nextWriteRecord({
			basePath: options.basePath,
			token: writerToken,
			category,
			operation,
			metadata,
		});
		return {
			...(metadata ?? {}),
			writeSequence: record.sequence.sequence,
			writerTokenId: record.writerToken.tokenId,
		};
	}
	return {
		onTurnStart(contract) {
			if (chaosMonkey) chaosMonkey.strike("turn-start");
			current = {
				...contract,
				runControl: options.runControl,
				permissionProfile: options.permissionProfile,
			};
			phaseResults.length = 0;
			writerToken = acquireWriterToken({
				basePath: options.basePath,
				traceId: current.traceId,
				turnId: current.turnId,
			});
			if (options.enableGitops) {
				writeTurnGitTransaction({
					basePath: options.basePath,
					traceId: current.traceId,
					turnId: current.turnId,
					unitType: current.unitType,
					unitId: current.unitId,
					stage: "turn-start",
					action: options.gitAction,
					push: options.gitPush,
					status: "ok",
					metadata: nextSequenceMetadata("gitops", "insert", {
						iteration: current.iteration,
						sidecarKind: current.sidecarKind,
						runControl: current.runControl,
						permissionProfile: current.permissionProfile,
					}),
				});
			}
			if (options.enableAudit) {
				emitUokAuditEvent(
					options.basePath,
					buildAuditEnvelope({
						traceId: current.traceId,
						turnId: current.turnId,
						category: "orchestration",
						type: "turn-start",
						payload: nextSequenceMetadata("audit", "append", {
							iteration: current.iteration,
							unitType: current.unitType,
							unitId: current.unitId,
							sidecarKind: current.sidecarKind,
							runControl: current.runControl,
							permissionProfile: current.permissionProfile,
						}),
					}),
				);
			}
		},
		onPhaseResult(phase, action, data) {
			if (chaosMonkey) chaosMonkey.strike(`after-${phase}`);
			phaseResults.push({
				phase,
				action,
				ts: new Date().toISOString(),
				data,
			});
			if (!current || !options.enableGitops) return;
			if (phase === "dispatch") {
				writeTurnGitTransaction({
					basePath: options.basePath,
					traceId: current.traceId,
					turnId: current.turnId,
					unitType: data?.unitType,
					unitId: data?.unitId,
					stage: "stage",
					action: options.gitAction,
					push: options.gitPush,
					status: "ok",
					metadata: nextSequenceMetadata("gitops", "update", { action }),
				});
			}
			if (phase === "unit") {
				writeTurnGitTransaction({
					basePath: options.basePath,
					traceId: current.traceId,
					turnId: current.turnId,
					unitType: data?.unitType,
					unitId: data?.unitId,
					stage: "checkpoint",
					action: options.gitAction,
					push: options.gitPush,
					status: "ok",
					metadata: nextSequenceMetadata("gitops", "update", { action }),
				});
			}
			if (phase === "finalize") {
				writeTurnGitTransaction({
					basePath: options.basePath,
					traceId: current.traceId,
					turnId: current.turnId,
					unitType: data?.unitType,
					unitId: data?.unitId,
					stage: "publish",
					action: options.gitAction,
					push: options.gitPush,
					status: "ok",
					metadata: nextSequenceMetadata("gitops", "update", { action }),
				});
			}
		},
		onTurnResult(result) {
			const merged = {
				runControl: options.runControl,
				permissionProfile: options.permissionProfile,
				...result,
				phaseResults:
					result.phaseResults.length > 0
						? result.phaseResults
						: [...phaseResults],
			};
			if (options.enableAudit) {
				emitUokAuditEvent(
					options.basePath,
					buildAuditEnvelope({
						traceId: merged.traceId,
						turnId: merged.turnId,
						category: "orchestration",
						type: "turn-result",
						payload: nextSequenceMetadata("audit", "append", {
							unitType: merged.unitType,
							unitId: merged.unitId,
							status: merged.status,
							failureClass: merged.failureClass,
							error: merged.error,
							phaseCount: merged.phaseResults.length,
							runControl: merged.runControl,
							permissionProfile: merged.permissionProfile,
						}),
					}),
				);
			}
			if (options.enableGitops) {
				const closeout = merged.closeout ?? {
					traceId: merged.traceId,
					turnId: merged.turnId,
					unitType: merged.unitType,
					unitId: merged.unitId,
					status: merged.status,
					failureClass: merged.failureClass,
					gitAction: options.gitAction,
					gitPushed: options.gitPush,
					finishedAt: merged.finishedAt,
				};
				writeTurnCloseoutGitRecord(
					options.basePath,
					closeout,
					nextSequenceMetadata("gitops", "update", { action: "record" }),
				);
			}
			if (writerToken) {
				releaseWriterToken(options.basePath, writerToken);
			}
			writerToken = null;
			current = null;
			phaseResults.length = 0;
		},
	};
}
