/** Run with a sandbox key and synthetic PDF bytes. Never prints credentials or signed URLs. */
export async function runSandboxWorkflow(input: {
	baseUrl: string;
	apiKey: string;
	resume: Uint8Array<ArrayBuffer>;
}): Promise<{
	reportId: string;
	interviewId: string;
	resultRevision: string | null;
}> {
	const base = new URL(input.baseUrl);
	if (
		!input.apiKey.startsWith("probb_test_") ||
		(base.protocol !== "https:" &&
			!["localhost", "127.0.0.1"].includes(base.hostname))
	)
		throw new Error("Use a sandbox origin and sandbox key.");
	const run = crypto.randomUUID();
	async function call<T>(
		path: string,
		body?: unknown,
		requestKey?: string,
	): Promise<T> {
		const response = await fetch(new URL(`/api/v1${path}`, base), {
			method: body === undefined ? "GET" : "POST",
			headers: {
				Authorization: `Bearer ${input.apiKey}`,
				...(body === undefined ? {} : { "Content-Type": "application/json" }),
				...(requestKey ? { "Idempotency-Key": requestKey } : {}),
			},
			...(body === undefined ? {} : { body: JSON.stringify(body) }),
			redirect: "error",
			signal: AbortSignal.timeout(120000),
		});
		const payload = (await response.json()) as {
			data?: T;
			error?: { code: string; reason?: string };
		};
		if (!response.ok || payload.data === undefined)
			throw new Error(
				`API ${response.status}: ${payload.error?.reason ?? payload.error?.code ?? "INVALID_RESPONSE"}; request ${response.headers.get("X-Request-Id")}`,
			);
		return payload.data;
	}
	const jobs = await call<{ items: { id: string }[] }>("/job-descriptions");
	const jobId = jobs.items[0]?.id;
	if (!jobId) throw new Error("Create sandbox sample data first.");
	const job = await call<{ revision: string }>(
		`/job-descriptions/${encodeURIComponent(jobId)}`,
	);
	const preparation = {
		fileName: "sandbox-resume.pdf",
		mimeType: "application/pdf",
		fileSize: input.resume.byteLength,
		externalReference: { source: "sandbox-example", id: run },
		jobDescription: {
			kind: "existing",
			id: jobId,
			expectedRevision: job.revision,
		},
	};
	type Upload = { reportId: string; upload: { url: string } | null };
	const prepared = await call<Upload>(
		"/uploads",
		preparation,
		`${run}:prepare`,
	);
	const replay = await call<Upload>("/uploads", preparation, `${run}:prepare`);
	if (replay.reportId !== prepared.reportId || !prepared.upload)
		throw new Error("Preparation replay mismatch");
	const put = await fetch(prepared.upload.url, {
		method: "PUT",
		headers: { "Content-Type": "application/pdf" },
		body: input.resume,
		redirect: "error",
		signal: AbortSignal.timeout(30000),
	});
	if (!put.ok) throw new Error(`Storage PUT failed: ${put.status}`);
	const quote = await call<{ fingerprint: string }>("/analysis-quotes", {
		reportId: prepared.reportId,
	});
	const submission = {
		reportId: prepared.reportId,
		quoteFingerprint: quote.fingerprint,
	};
	const accepted = await call<{ attemptId: string }>(
		"/analyses",
		submission,
		`${run}:analyse`,
	);
	const acceptedReplay = await call<{ attemptId: string }>(
		"/analyses",
		submission,
		`${run}:analyse`,
	);
	if (accepted.attemptId !== acceptedReplay.attemptId)
		throw new Error("Admission replay mismatch");
	let completed = false;
	for (let poll = 0; poll < 60; poll++) {
		const status = await call<{ status: string }>(
			`/reports/${prepared.reportId}/status`,
		);
		if (status.status === "completed") {
			completed = true;
			break;
		}
		if (["failed", "requires_action"].includes(status.status))
			throw new Error(`Analysis outcome: ${status.status}`);
		await new Promise((resolve) => setTimeout(resolve, 2000));
	}
	if (!completed)
		throw new Error(
			"Analysis did not complete within the sample's polling window.",
		);
	const result = await call<{
		schemaVersion: number;
		resultRevision: string | null;
		result: unknown;
	}>(`/reports/${prepared.reportId}/result?schemaVersion=1`);
	if (result.schemaVersion !== 1 || !result.result)
		throw new Error("Versioned result unavailable");
	const invitation = {
		reportId: prepared.reportId,
		candidateEmail: "alex@example.test",
		sendEmail: true,
	};
	const interviewQuote = await call<{ fingerprint: string }>(
		"/interview-quotes",
		invitation,
	);
	const interview = await call<{ interviewId: string }>(
		"/interviews",
		{ ...invitation, quoteFingerprint: interviewQuote.fingerprint },
		`${run}:invite`,
	);
	await call(`/interviews/${interview.interviewId}/status`);
	await call(`/events?reportId=${prepared.reportId}`);
	return {
		reportId: prepared.reportId,
		interviewId: interview.interviewId,
		resultRevision: result.resultRevision,
	};
}
