import { mkdirSync, mkdtempSync, rmSync, writeFileSync } from "node:fs";
import { tmpdir } from "node:os";
import { join } from "node:path";
import { afterEach, beforeEach, describe, expect, it } from "vitest";
import {
	readUnitRuntimeRecord,
	reconcileDurableCompleteUnitRuntimeRecords,
	reconcileStaleCompleteSliceRecords,
	writeUnitRuntimeRecord,
} from "../resources/extensions/sf/uok/unit-runtime.js";

describe("reconcileStaleCompleteSliceRecords", () => {
	let basePath: string;

	beforeEach(() => {
		basePath = mkdtempSync(join(tmpdir(), "sf-reconcile-test-"));
		mkdirSync(join(basePath, ".sf", "runtime", "units"), { recursive: true });
	});

	afterEach(() => {
		rmSync(basePath, { recursive: true, force: true });
	});

	it("clears a cancelled complete-slice record when DB and artifact say complete", () => {
		// Write a stale cancelled runtime record
		writeUnitRuntimeRecord(basePath, "complete-slice", "M001/S01", Date.now(), {
			status: "cancelled",
		});

		// Write a SUMMARY.md with completed_at
		const sliceDir = join(
			basePath,
			".sf",
			"milestones",
			"M001",
			"slices",
			"S01",
		);
		mkdirSync(sliceDir, { recursive: true });
		writeFileSync(
			join(sliceDir, "S01-SUMMARY.md"),
			`---\ncompleted_at: 2026-05-04T17:09:15Z\n---\n# S01 Summary\n`,
			"utf-8",
		);

		// DB is not available in this test environment, so the function will
		// skip the DB check and NOT clear the record (dbComplete will be false).
		// This tests the artifact-only path when DB is unavailable.
		const result = reconcileStaleCompleteSliceRecords(basePath);

		// Since isDbAvailable() returns false in this test (no sf.db),
		// dbComplete is false, so nothing should be cleared.
		expect(result.cleared).toBe(0);
		expect(
			readUnitRuntimeRecord(basePath, "complete-slice", "M001/S01"),
		).not.toBeNull();
	});

	it("leaves a non-complete-slice record untouched", () => {
		writeUnitRuntimeRecord(
			basePath,
			"execute-task",
			"M001/S01/T01",
			Date.now(),
			{
				status: "cancelled",
			},
		);

		const result = reconcileStaleCompleteSliceRecords(basePath);
		expect(result.cleared).toBe(0);
		expect(
			readUnitRuntimeRecord(basePath, "execute-task", "M001/S01/T01"),
		).not.toBeNull();
	});

	it("leaves a completed complete-slice record untouched", () => {
		writeUnitRuntimeRecord(basePath, "complete-slice", "M001/S01", Date.now(), {
			status: "completed",
		});

		const result = reconcileStaleCompleteSliceRecords(basePath);
		expect(result.cleared).toBe(0);
		expect(
			readUnitRuntimeRecord(basePath, "complete-slice", "M001/S01"),
		).not.toBeNull();
	});

	it("returns empty when runtime dir does not exist", () => {
		const emptyBase = mkdtempSync(join(tmpdir(), "sf-empty-"));
		try {
			const result = reconcileStaleCompleteSliceRecords(emptyBase);
			expect(result.cleared).toBe(0);
			expect(result.details).toEqual([]);
		} finally {
			rmSync(emptyBase, { recursive: true, force: true });
		}
	});

	it("clears a stale execute-task record when durable task artifacts prove completion", async () => {
		writeUnitRuntimeRecord(
			basePath,
			"execute-task",
			"M001/S01/T01",
			Date.now(),
			{
				status: "running",
			},
		);

		const sliceDir = join(
			basePath,
			".sf",
			"milestones",
			"M001",
			"slices",
			"S01",
		);
		const taskDir = join(sliceDir, "tasks");
		mkdirSync(taskDir, { recursive: true });
		writeFileSync(
			join(sliceDir, "S01-PLAN.md"),
			"# S01 Plan\n\n- [x] **T01:** Durable completion\n",
			"utf-8",
		);
		writeFileSync(
			join(taskDir, "T01-PLAN.md"),
			"# T01 Plan\n\n## Must-Haves\n\n- Durable summary\n",
			"utf-8",
		);
		writeFileSync(
			join(taskDir, "T01-SUMMARY.md"),
			"# T01 Summary\n\nDurable summary.\n",
			"utf-8",
		);
		writeFileSync(
			join(basePath, ".sf", "STATE.md"),
			"**Next Action:** Complete S01\n",
			"utf-8",
		);

		const result = await reconcileDurableCompleteUnitRuntimeRecords(basePath);

		expect(result).toEqual({
			cleared: 1,
			details: ["execute-task M001/S01/T01 (was running)"],
		});
		expect(
			readUnitRuntimeRecord(basePath, "execute-task", "M001/S01/T01"),
		).toBeNull();
	});
});
