/**
 * Turn Status Parser Tests (Tier 2.5 Phases 1-2)
 *
 * Validates that turn_status markers are correctly extracted and parsed
 * from agent output.
 */

import { mkdirSync, mkdtempSync, rmSync, writeFileSync } from "node:fs";
import { tmpdir } from "node:os";
import { join } from "node:path";
import { afterEach, describe, expect, it } from "vitest";
import {
	checkTurnStatusPrompts,
	describeTurnStatus,
	extractTurnStatus,
	isValidTurnStatus,
	parseTurnStatusFull,
	resolveSignalFromStatus,
} from "../turn-status-parser.js";

const tmpRoots: string[] = [];

afterEach(() => {
	for (const dir of tmpRoots.splice(0)) {
		rmSync(dir, { recursive: true, force: true });
	}
});

function makePromptRoot() {
	const root = mkdtempSync(join(tmpdir(), "sf-turn-status-"));
	tmpRoots.push(root);
	const prompts = join(root, "src/resources/extensions/sf/prompts");
	mkdirSync(prompts, { recursive: true });
	for (const name of [
		"execute-task.md",
		"complete-slice.md",
		"research-slice.md",
		"plan-slice.md",
		"research-milestone.md",
		"plan-milestone.md",
	]) {
		writeFileSync(
			join(prompts, name),
			"Finish with <turn_status>complete</turn_status>\n",
			"utf-8",
		);
	}
	return root;
}

describe("Turn Status Parser (Tier 2.5)", () => {
	describe("extractTurnStatus", () => {
		it("when_complete_marker_present_extracts_status", () => {
			const output = "Task done.\n\n<turn_status>complete</turn_status>";

			const result = extractTurnStatus(output);

			expect(result.status).toBe("complete");
			expect(result.markerFound).toBe(true);
		});

		it("when_blocked_marker_present_extracts_status", () => {
			const output = "Cannot proceed.\n\n<turn_status>blocked</turn_status>";

			const result = extractTurnStatus(output);

			expect(result.status).toBe("blocked");
		});

		it("when_giving_up_marker_present_extracts_status", () => {
			const output =
				"Tried all approaches.\n\n<turn_status>giving_up</turn_status>";

			const result = extractTurnStatus(output);

			expect(result.status).toBe("giving_up");
		});

		it("when_no_marker_returns_null_status", () => {
			const output = "Task completed successfully.";

			const result = extractTurnStatus(output);

			expect(result.status).toBeNull();
			expect(result.markerFound).toBeUndefined();
		});

		it("removes_marker_from_clean_output", () => {
			const output =
				"Final summary here.\n\n<turn_status>complete</turn_status>";

			const result = extractTurnStatus(output);

			expect(result.cleanOutput).toBe("Final summary here.");
			expect(result.cleanOutput).not.toContain("turn_status");
		});

		it("handles_whitespace_around_marker", () => {
			const output = "Done.\n\n\n<turn_status>complete</turn_status>  \n\n";

			const result = extractTurnStatus(output);

			expect(result.status).toBe("complete");
			expect(result.cleanOutput).toBe("Done.");
		});

		it("is_case_insensitive", () => {
			const outputs = [
				"<turn_status>COMPLETE</turn_status>",
				"<turn_status>Complete</turn_status>",
				"<turn_status>cOmPlEtE</turn_status>",
			];

			for (const output of outputs) {
				const result = extractTurnStatus(output);
				expect(result.status).toBe("complete");
			}
		});

		it("handles_null_or_empty_input", () => {
			expect(extractTurnStatus(null).status).toBeNull();
			expect(extractTurnStatus("").status).toBeNull();
			expect(extractTurnStatus(undefined).status).toBeNull();
		});

		it("handles_non_string_input_gracefully", () => {
			const result = extractTurnStatus(123);
			expect(result.status).toBeNull();
			expect(result.cleanOutput).toBe(123);
		});

		it("ignores_marker_not_at_end", () => {
			const output =
				"Found <turn_status>complete</turn_status> in middle\nmore text here";

			const result = extractTurnStatus(output);

			expect(result.status).toBeNull();
		});
	});

	describe("isValidTurnStatus", () => {
		it("accepts_all_valid_statuses", () => {
			expect(isValidTurnStatus("complete")).toBe(true);
			expect(isValidTurnStatus("blocked")).toBe(true);
			expect(isValidTurnStatus("giving_up")).toBe(true);
		});

		it("rejects_invalid_statuses", () => {
			expect(isValidTurnStatus("error")).toBe(false);
			expect(isValidTurnStatus("failed")).toBe(false);
			expect(isValidTurnStatus("unknown")).toBe(false);
		});

		it("is_case_insensitive", () => {
			expect(isValidTurnStatus("COMPLETE")).toBe(true);
			expect(isValidTurnStatus("Blocked")).toBe(true);
			expect(isValidTurnStatus("GIVING_UP")).toBe(true);
		});

		it("handles_null_or_empty", () => {
			expect(isValidTurnStatus(null)).toBe(false);
			expect(isValidTurnStatus("")).toBe(false);
		});
	});

	describe("describeTurnStatus", () => {
		it("provides_human_readable_descriptions", () => {
			expect(describeTurnStatus("complete")).toContain("complete");
			expect(describeTurnStatus("blocked")).toContain("blocked");
			expect(describeTurnStatus("giving_up")).toContain("giving");
		});

		it("handles_invalid_status_gracefully", () => {
			const desc = describeTurnStatus("unknown");
			expect(desc).toContain("Unknown");
		});
	});

	describe("resolveSignalFromStatus", () => {
		it("complete_returns_continue_action", () => {
			const result = resolveSignalFromStatus("complete");

			expect(result.action).toBe("continue");
			expect(result.reason).toBeDefined();
		});

		it("blocked_returns_pause_with_signal_pause", () => {
			const result = resolveSignalFromStatus("blocked");

			expect(result.action).toBe("pause");
			expect(result.signal).toBe("SignalPause");
		});

		it("giving_up_returns_reassess_with_phase_reassess", () => {
			const result = resolveSignalFromStatus("giving_up");

			expect(result.action).toBe("reassess");
			expect(result.signal).toBe("PhaseReassess");
		});

		it("null_returns_continue_with_reason", () => {
			const result = resolveSignalFromStatus(null);

			expect(result.action).toBe("continue");
		});

		it("is_case_insensitive", () => {
			expect(resolveSignalFromStatus("COMPLETE").action).toBe("continue");
			expect(resolveSignalFromStatus("Blocked").action).toBe("pause");
			expect(resolveSignalFromStatus("GIVING_UP").action).toBe("reassess");
		});
	});

	describe("parseTurnStatusFull", () => {
		it("extracts_and_resolves_complete_marker", () => {
			const output = "Done!\n\n<turn_status>complete</turn_status>";

			const result = parseTurnStatusFull(output);

			expect(result.status).toBe("complete");
			expect(result.action).toBe("continue");
			expect(result.cleanOutput).toBe("Done!");
		});

		it("extracts_and_resolves_blocked_marker", () => {
			const output = "Cannot find file.\n\n<turn_status>blocked</turn_status>";

			const result = parseTurnStatusFull(output);

			expect(result.status).toBe("blocked");
			expect(result.action).toBe("pause");
			expect(result.signal).toBe("SignalPause");
		});

		it("extracts_and_resolves_giving_up_marker", () => {
			const output =
				"Multiple attempts failed.\n\n<turn_status>giving_up</turn_status>";

			const result = parseTurnStatusFull(output);

			expect(result.status).toBe("giving_up");
			expect(result.action).toBe("reassess");
			expect(result.signal).toBe("PhaseReassess");
		});

		it("defaults_to_continue_when_no_marker", () => {
			const output = "Completed successfully.";

			const result = parseTurnStatusFull(output);

			expect(result.status).toBeNull();
			expect(result.action).toBe("continue");
		});

		it("includes_all_relevant_fields", () => {
			const output = "Task done.\n\n<turn_status>complete</turn_status>";

			const result = parseTurnStatusFull(output);

			expect(result).toHaveProperty("status");
			expect(result).toHaveProperty("action");
			expect(result).toHaveProperty("cleanOutput");
			expect(result).toHaveProperty("reason");
		});
	});

	describe("checkTurnStatusPrompts", () => {
		it("validates_marker_presence_in_prompts_without_commonjs_require", () => {
			const result = checkTurnStatusPrompts(makePromptRoot());

			expect(result).toHaveProperty("issues");
			expect(result).toHaveProperty("allGood");
			expect(result).toHaveProperty("promptsChecked");
			expect(result.allGood).toBe(true);
			expect(result.promptsChecked).toBe(6);
			expect(result.issues).toEqual([]);
		});
	});

	describe("Semantics and Signal Mapping", () => {
		it("complete_enables_immediate_transition", () => {
			const result = resolveSignalFromStatus("complete");

			// Should not require pause or reassess
			expect(result.signal).toBeUndefined();
			expect(result.action).not.toBe("pause");
		});

		it("blocked_pauses_for_user_interaction", () => {
			const result = resolveSignalFromStatus("blocked");

			// Should pause, allowing user to intervene
			expect(result.action).toBe("pause");
			expect(result.signal).toBe("SignalPause");
		});

		it("giving_up_triggers_reassessment", () => {
			const result = resolveSignalFromStatus("giving_up");

			// Should trigger phase reassessment
			expect(result.action).toBe("reassess");
			expect(result.signal).toBe("PhaseReassess");
		});
	});

	describe("Integration", () => {
		it("full_pipeline_from_output_to_action", () => {
			const agentOutputs = [
				{
					output: "Task complete.\n\n<turn_status>complete</turn_status>",
					expectedAction: "continue",
				},
				{
					output: "Blocker found.\n\n<turn_status>blocked</turn_status>",
					expectedAction: "pause",
				},
				{
					output: "Out of ideas.\n\n<turn_status>giving_up</turn_status>",
					expectedAction: "reassess",
				},
				{
					output: "No marker here",
					expectedAction: "continue",
				},
			];

			for (const test of agentOutputs) {
				const result = parseTurnStatusFull(test.output);
				expect(result.action).toBe(test.expectedAction);
			}
		});
	});
});
