/* @vitest-environment node */

import { describe, it, expect, vi, beforeEach, afterEach } from "vitest";
import fs from "node:fs/promises";
import os from "node:os";
import path from "node:path";

vi.mock("@/lib/auth/session", () => ({
	getSession: vi.fn(),
}));

import { getSession } from "@/lib/auth/session";
import { GET, dynamic } from "./route.js";

describe("GET /api/branches/[branch]/years", () => {
	let tmpRoot;
	const originalNasRoot = process.env.NAS_ROOT_PATH;

	beforeEach(async () => {
		vi.clearAllMocks();
		tmpRoot = await fs.mkdtemp(path.join(os.tmpdir(), "api-years-"));
		process.env.NAS_ROOT_PATH = tmpRoot;

		// Minimal structure for NL01
		await fs.mkdir(path.join(tmpRoot, "NL01", "2024"), { recursive: true });
	});

	afterEach(async () => {
		process.env.NAS_ROOT_PATH = originalNasRoot;
		if (tmpRoot) await fs.rm(tmpRoot, { recursive: true, force: true });
	});

	it('exports dynamic="force-dynamic" (RHL-006)', () => {
		expect(dynamic).toBe("force-dynamic");
	});

	it("returns 401 when unauthenticated", async () => {
		getSession.mockResolvedValue(null);

		const res = await GET(
			new Request("http://localhost/api/branches/NL01/years"),
			{ params: Promise.resolve({ branch: "NL01" }) }
		);

		expect(res.status).toBe(401);
		expect(await res.json()).toEqual({
			error: { message: "Unauthorized", code: "AUTH_UNAUTHENTICATED" },
		});
	});

	it("returns 403 when branch user accesses a different branch", async () => {
		getSession.mockResolvedValue({
			role: "branch",
			branchId: "NL01",
			userId: "u1",
		});

		const res = await GET(
			new Request("http://localhost/api/branches/NL02/years"),
			{ params: Promise.resolve({ branch: "NL02" }) }
		);

		expect(res.status).toBe(403);
		expect(await res.json()).toEqual({
			error: { message: "Forbidden", code: "AUTH_FORBIDDEN_BRANCH" },
		});
	});

	it("returns years for a valid branch when allowed", async () => {
		getSession.mockResolvedValue({
			role: "branch",
			branchId: "NL01",
			userId: "u1",
		});

		const res = await GET(
			new Request("http://localhost/api/branches/NL01/years"),
			{ params: Promise.resolve({ branch: "NL01" }) }
		);

		expect(res.status).toBe(200);
		expect(await res.json()).toEqual({ branch: "NL01", years: ["2024"] });
	});

	it("returns 400 when branch param is missing (authenticated)", async () => {
		getSession.mockResolvedValue({
			role: "admin",
			branchId: null,
			userId: "u2",
		});

		const res = await GET(new Request("http://localhost/api/branches//years"), {
			params: Promise.resolve({ branch: undefined }),
		});

		expect(res.status).toBe(400);
		expect(await res.json()).toEqual({
			error: {
				message: "Missing required route parameter(s)",
				code: "VALIDATION_MISSING_PARAM",
				details: { params: ["branch"] },
			},
		});
	});

	it("returns 404 when the branch folder does not exist (authorized)", async () => {
		getSession.mockResolvedValue({
			role: "admin",
			branchId: null,
			userId: "u2",
		});

		const res = await GET(
			new Request("http://localhost/api/branches/NL99/years"),
			{ params: Promise.resolve({ branch: "NL99" }) }
		);

		expect(res.status).toBe(404);
		expect(await res.json()).toEqual({
			error: {
				message: "Not found",
				code: "FS_NOT_FOUND",
				details: { branch: "NL99" },
			},
		});
	});

	it("returns 500 when NAS_ROOT_PATH is invalid (authenticated)", async () => {
		getSession.mockResolvedValue({
			role: "admin",
			branchId: null,
			userId: "u2",
		});

		process.env.NAS_ROOT_PATH = path.join(tmpRoot, "does-not-exist");

		const res = await GET(
			new Request("http://localhost/api/branches/NL01/years"),
			{ params: Promise.resolve({ branch: "NL01" }) }
		);

		expect(res.status).toBe(500);
		expect(await res.json()).toEqual({
			error: { message: "Internal server error", code: "FS_STORAGE_ERROR" },
		});
	});
});
