import type { SavedFilter } from "@olenbetong/appframe-core";
import { render, screen } from "@testing-library/react";
import userEvent from "@testing-library/user-event";
import { describe, expect, it, vi } from "vitest";

import { SavedFilterTree } from "./SavedFilterTree.js";

function savedFilter(overrides: Partial<SavedFilter> & Pick<SavedFilter, "filterId" | "name">): SavedFilter {
	return {
		primKey: `pk-${overrides.filterId}`,
		criteria: "",
		dbObjectId: "aviw_Test_View",
		accessLevel: "Manager",
		createdByUser: true,
		createdBy: "bvh",
		domain: "OB",
		crossDomain: false,
		isPersonallyShared: false,
		hideCriteria: false,
		headerText: null,
		comment: null,
		parameters: null,
		reportTitle: null,
		created: null,
		updated: null,
		...overrides,
	};
}

const MINE = [savedFilter({ filterId: 1, name: "Agder" })];
const SHARED = [
	savedFilter({ filterId: 2, name: "Alle ledere", createdByUser: false, createdBy: "ola", accessLevel: "Reader" }),
];

function renderTree(props: Partial<React.ComponentProps<typeof SavedFilterTree>> = {}) {
	let onChange = vi.fn();
	render(<SavedFilterTree mine={MINE} shared={SHARED} value={null} onChange={onChange} {...props} />);

	return { onChange };
}

describe("SavedFilterTree", () => {
	it("renders the three fixed nodes and their filters", () => {
		renderTree();

		expect(screen.getByRole("button", { name: "New Filter" })).toBeTruthy();
		expect(screen.getByRole("button", { name: /My Filters/ })).toBeTruthy();
		expect(screen.getByRole("button", { name: /Shared With Me/ })).toBeTruthy();
		expect(screen.getByRole("button", { name: "Agder" })).toBeTruthy();
		expect(screen.getByRole("button", { name: "Alle ledere" })).toBeTruthy();
	});

	it("reports the selected filter id", async () => {
		let { onChange } = renderTree();
		await userEvent.click(screen.getByRole("button", { name: "Agder" }));

		expect(onChange).toHaveBeenCalledWith(1);
	});

	it("reports null when the new filter node is selected", async () => {
		let { onChange } = renderTree({ value: 1 });
		await userEvent.click(screen.getByRole("button", { name: "New Filter" }));

		expect(onChange).toHaveBeenCalledWith(null);
	});

	it("collapses a branch", async () => {
		renderTree();
		await userEvent.click(screen.getByRole("button", { name: /My Filters/ }));

		expect(screen.queryByRole("button", { name: "Agder" })).toBeNull();
	});

	it("offers rename and delete for the user's own filters", async () => {
		let onRename = vi.fn();
		renderTree({ onRename, onDelete: vi.fn() });
		await userEvent.click(screen.getByRole("button", { name: "Options for Agder" }));
		await userEvent.click(screen.getByRole("button", { name: "Rename" }));

		expect(onRename).toHaveBeenCalledWith(MINE[0]);
	});

	it("does not offer rename or delete for filters created by someone else", () => {
		renderTree({ onRename: vi.fn(), onDelete: vi.fn() });

		expect(screen.queryByRole("button", { name: "Options for Alle ledere" })).toBeNull();
	});

	it("still offers info for filters created by someone else", () => {
		renderTree({ onShowInfo: vi.fn() });

		expect(screen.getByRole("button", { name: "Options for Alle ledere" })).toBeTruthy();
	});
});
