/* @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/files", () => {
	let tmpRoot;
	const originalNasRoot = process.env.NAS_ROOT_PATH;

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

		const dir = path.join(tmpRoot, "NL01", "2024", "10", "23");
		await fs.mkdir(dir, { recursive: true });
		await fs.writeFile(path.join(dir, "test.pdf"), "dummy-pdf-content");
	});

	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 req = new Request(
			"http://localhost/api/files?branch=NL01&year=2024&month=10&day=23"
		);

		const res = await GET(req);
		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 req = new Request(
			"http://localhost/api/files?branch=NL02&year=2024&month=10&day=23"
		);

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

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

		const req = new Request(
			"http://localhost/api/files?branch=NL01&year=2024&month=10&day=23"
		);

		const res = await GET(req);
		expect(res.status).toBe(200);

		const body = await res.json();
		expect(body.branch).toBe("NL01");
		expect(body.files).toHaveLength(1);
		expect(body.files[0]).toMatchObject({
			name: "test.pdf",
			relativePath: "NL01/2024/10/23/test.pdf",
		});
	});

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

		const req = new Request("http://localhost/api/files");

		const res = await GET(req);
		expect(res.status).toBe(400);

		const body = await res.json();
		expect(body).toEqual({
			error: {
				message: "Missing required query parameter(s)",
				code: "VALIDATION_MISSING_QUERY",
				details: { params: ["branch", "year", "month", "day"] },
			},
		});
	});

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

		const req = new Request(
			"http://localhost/api/files?branch=NL01&year=2024&month=10&day=99"
		);

		const res = await GET(req);
		expect(res.status).toBe(404);

		expect(await res.json()).toEqual({
			error: {
				message: "Not found",
				code: "FS_NOT_FOUND",
				details: { branch: "NL01", year: "2024", month: "10", day: "99" },
			},
		});
	});
});
