/* @vitest-environment node */

import { describe, it, expect } from "vitest";
import { ApiClientError } from "@/lib/frontend/apiClient";
import { SEARCH_SCOPE } from "@/lib/frontend/search/urlState";
import { buildSearchApiInput } from "./searchApiInput.js";

describe("lib/frontend/search/searchApiInput", () => {
	it("returns {input:null} when q is missing", () => {
		const { input, error } = buildSearchApiInput({
			urlState: {
				q: null,
				scope: SEARCH_SCOPE.SINGLE,
				branch: "NL01",
				branches: [],
				from: null,
				to: null,
			},
			routeBranch: "NL01",
			user: { role: "admin", branchId: null },
		});

		expect(input).toBe(null);
		expect(error).toBe(null);
	});

	it("branch users always use routeBranch (single) and ignore scope", () => {
		const { input, error } = buildSearchApiInput({
			urlState: {
				q: "x",
				scope: SEARCH_SCOPE.ALL,
				branch: "NL99",
				branches: ["NL06"],
				from: null,
				to: null,
			},
			routeBranch: "NL01",
			user: { role: "branch", branchId: "NL01" },
		});

		expect(error).toBe(null);
		expect(input).toEqual({ q: "x", limit: 100, branch: "NL01" });
	});

	it("admin-like: ALL uses scope=all (admin)", () => {
		const { input } = buildSearchApiInput({
			urlState: {
				q: "x",
				scope: SEARCH_SCOPE.ALL,
				branch: null,
				branches: [],
				from: null,
				to: null,
			},
			routeBranch: "NL01",
			user: { role: "admin", branchId: null },
		});

		expect(input).toEqual({ q: "x", limit: 100, scope: "all" });
	});

	it("admin-like: ALL uses scope=all (superadmin)", () => {
		const { input } = buildSearchApiInput({
			urlState: {
				q: "x",
				scope: SEARCH_SCOPE.ALL,
				branch: null,
				branches: [],
				from: null,
				to: null,
			},
			routeBranch: "NL01",
			user: { role: "superadmin", branchId: null },
		});

		expect(input).toEqual({ q: "x", limit: 100, scope: "all" });
	});

	it("admin-like: MULTI uses scope=multi + branches (dev)", () => {
		const { input, error } = buildSearchApiInput({
			urlState: {
				q: "x",
				scope: SEARCH_SCOPE.MULTI,
				branch: null,
				branches: ["NL06", "NL20"],
				from: null,
				to: null,
			},
			routeBranch: "NL01",
			user: { role: "dev", branchId: null },
			cursor: "abc",
			limit: 100,
		});

		expect(error).toBe(null);
		expect(input).toEqual({
			q: "x",
			limit: 100,
			cursor: "abc",
			scope: "multi",
			branches: ["NL06", "NL20"],
		});
	});

	it("admin-like: MULTI without branches is treated as not-ready (no error)", () => {
		const { input, error } = buildSearchApiInput({
			urlState: {
				q: "x",
				scope: SEARCH_SCOPE.MULTI,
				branch: null,
				branches: [],
				from: null,
				to: null,
			},
			routeBranch: "NL01",
			user: { role: "admin", branchId: null },
		});

		expect(input).toBe(null);
		expect(error).toBe(null);
	});

	it("admin-like: SINGLE uses routeBranch as branch param", () => {
		const { input } = buildSearchApiInput({
			urlState: {
				q: "x",
				scope: SEARCH_SCOPE.SINGLE,
				branch: "NL99",
				branches: [],
				from: null,
				to: null,
			},
			routeBranch: "NL01",
			user: { role: "admin", branchId: null },
		});

		expect(input).toEqual({ q: "x", limit: 100, branch: "NL01" });
	});

	it("includes from/to when valid", () => {
		const { input, error } = buildSearchApiInput({
			urlState: {
				q: "x",
				scope: SEARCH_SCOPE.SINGLE,
				branch: "NL01",
				branches: [],
				from: "2025-12-01",
				to: "2025-12-31",
			},
			routeBranch: "NL01",
			user: { role: "admin", branchId: null },
		});

		expect(error).toBe(null);
		expect(input).toEqual({
			q: "x",
			limit: 100,
			branch: "NL01",
			from: "2025-12-01",
			to: "2025-12-31",
		});
	});

	it("accepts from===to as a valid single-day search", () => {
		const { input, error } = buildSearchApiInput({
			urlState: {
				q: "x",
				scope: SEARCH_SCOPE.SINGLE,
				branch: "NL01",
				branches: [],
				from: "2025-12-01",
				to: "2025-12-01",
			},
			routeBranch: "NL01",
			user: { role: "admin", branchId: null },
		});

		expect(error).toBe(null);
		expect(input).toEqual({
			q: "x",
			limit: 100,
			branch: "NL01",
			from: "2025-12-01",
			to: "2025-12-01",
		});
	});

	it("returns a local validation error when from > to (no request should be sent)", () => {
		const { input, error } = buildSearchApiInput({
			urlState: {
				q: "x",
				scope: SEARCH_SCOPE.SINGLE,
				branch: "NL01",
				branches: [],
				from: "2025-12-31",
				to: "2025-12-01",
			},
			routeBranch: "NL01",
			user: { role: "admin", branchId: null },
		});

		expect(input).toBe(null);
		expect(error).toBeInstanceOf(ApiClientError);
		expect(error.code).toBe("VALIDATION_SEARCH_RANGE");
	});

	it("returns a local validation error for invalid date format", () => {
		const { input, error } = buildSearchApiInput({
			urlState: {
				q: "x",
				scope: SEARCH_SCOPE.SINGLE,
				branch: "NL01",
				branches: [],
				from: "2025/12/01",
				to: null,
			},
			routeBranch: "NL01",
			user: { role: "admin", branchId: null },
		});

		expect(input).toBe(null);
		expect(error).toBeInstanceOf(ApiClientError);
		expect(error.code).toBe("VALIDATION_SEARCH_DATE");
	});
});
