import UserRolesAndSites from "@ax/components/UserRolesAndSites";
import { parseTheme } from "@ax/helpers";
import globalTheme from "@ax/themes/theme.json";
import type { IRole, ISite, ISiteRoles } from "@ax/types";

import { cleanup, render, screen } from "@testing-library/react";
import { ThemeProvider } from "styled-components";

afterEach(cleanup);

const mockRole = (overrides?: Partial<IRole>): IRole => ({
	id: 1,
	name: "Admin",
	hex: "#5057FF",
	description: "Admin role",
	permissions: {
		totalPermissions: "10",
		sitePermissions: [],
		globalPermissions: [],
	},
	active: true,
	users: null,
	editable: true,
	...overrides,
});

const mockSite = (overrides?: Partial<ISite>): ISite => ({
	author: "Test Author",
	id: 1,
	name: "Test Site",
	published: "2024-01-01",
	isPublished: true,
	updated: false,
	theme: "default",
	defaultLanguage: null,
	path: "/test",
	timezone: "UTC",
	favicon: "",
	smallAvatar: "",
	bigAvatar: "",
	thumbnail: "",
	domain: null,
	navigationModules: {},
	pages: [],
	...overrides,
});

const mockSiteRole = (siteId: number | string, roles: number[]): ISiteRoles => ({
	siteId,
	roles,
});

describe("UserRolesAndSites Component", () => {
	describe("Super Admin", () => {
		it("should render super admin message when isSuperAdmin is true", () => {
			const props = {
				isSuperAdmin: true,
				userRoles: [],
				sites: [],
				roles: [],
			};

			render(
				<ThemeProvider theme={parseTheme(globalTheme)}>
					<UserRolesAndSites {...props} />
				</ThemeProvider>,
			);

			const superAdminSection = screen.getByTestId("final-step-super-admin");
			expect(superAdminSection).toBeTruthy();
			expect(superAdminSection.textContent).toContain("You are a Super admin");
		});
	});

	describe("Global Roles", () => {
		it("should render global roles section when user has global role", () => {
			const role = mockRole({ id: 1, name: "Editor" });
			const props = {
				isSuperAdmin: false,
				userRoles: [mockSiteRole("global", [1])],
				sites: [],
				roles: [role],
			};

			render(
				<ThemeProvider theme={parseTheme(globalTheme)}>
					<UserRolesAndSites {...props} />
				</ThemeProvider>,
			);

			const globalRoleSection = screen.getByTestId("final-step-global-role");
			expect(globalRoleSection).toBeTruthy();
			expect(globalRoleSection.textContent).toContain("Global data permissions");
		});

		it("should not render global roles section when user has no global role", () => {
			const props = {
				isSuperAdmin: false,
				userRoles: [],
				sites: [],
				roles: [],
			};

			render(
				<ThemeProvider theme={parseTheme(globalTheme)}>
					<UserRolesAndSites {...props} />
				</ThemeProvider>,
			);

			const globalRoleSection = screen.queryByTestId("final-step-global-role");
			expect(globalRoleSection).toBeFalsy();
		});
	});

	describe("Site-Specific Roles", () => {
		it("should render sites content when user has site-specific roles", () => {
			const role = mockRole({ id: 1, name: "Editor" });
			const site = mockSite({ id: 1, name: "Test Site" });
			const props = {
				isSuperAdmin: false,
				userRoles: [mockSiteRole(1, [1])],
				sites: [site],
				roles: [role],
			};

			render(
				<ThemeProvider theme={parseTheme(globalTheme)}>
					<UserRolesAndSites {...props} />
				</ThemeProvider>,
			);

			const sitesContent = screen.getByTestId("final-step-sites-content");
			expect(sitesContent).toBeTruthy();
			expect(sitesContent.textContent).toContain("Test Site");
		});

		it("should display multiple site cards with role colors", () => {
			const roles = [
				mockRole({ id: 1, name: "Editor", hex: "#5057FF" }),
				mockRole({ id: 2, name: "Viewer", hex: "#FF0000" }),
			];
			const sites = [mockSite({ id: 1, name: "Site One" }), mockSite({ id: 2, name: "Site Two" })];
			const props = {
				isSuperAdmin: false,
				userRoles: [mockSiteRole(1, [1, 2]), mockSiteRole(2, [1])],
				sites,
				roles,
			};

			render(
				<ThemeProvider theme={parseTheme(globalTheme)}>
					<UserRolesAndSites {...props} />
				</ThemeProvider>,
			);

			expect(screen.getByText("Site One")).toBeTruthy();
			expect(screen.getByText("Site Two")).toBeTruthy();
		});

		it("should not render sites when user is super admin", () => {
			const role = mockRole({ id: 1, name: "Editor" });
			const site = mockSite({ id: 1, name: "Test Site" });
			const props = {
				isSuperAdmin: true,
				userRoles: [mockSiteRole(1, [1])],
				sites: [site],
				roles: [role],
			};

			render(
				<ThemeProvider theme={parseTheme(globalTheme)}>
					<UserRolesAndSites {...props} />
				</ThemeProvider>,
			);

			const sitesContent = screen.queryByTestId("final-step-sites-content");
			expect(sitesContent).toBeFalsy();
		});

		it("should filter out sites that do not exist in the sites list", () => {
			const role = mockRole({ id: 1, name: "Editor" });
			const site = mockSite({ id: 1, name: "Existing Site" });
			const props = {
				isSuperAdmin: false,
				userRoles: [mockSiteRole(1, [1]), mockSiteRole(999, [1])],
				sites: [site],
				roles: [role],
			};

			render(
				<ThemeProvider theme={parseTheme(globalTheme)}>
					<UserRolesAndSites {...props} />
				</ThemeProvider>,
			);

			expect(screen.getByText("Existing Site")).toBeTruthy();
		});
	});

	describe("All Sites Access", () => {
		it("should render 'Access to All Sites' section when user has all sites role", () => {
			const role = mockRole({ id: 1, name: "Editor" });
			const props = {
				isSuperAdmin: false,
				userRoles: [mockSiteRole("all", [1])],
				sites: [],
				roles: [role],
			};

			render(
				<ThemeProvider theme={parseTheme(globalTheme)}>
					<UserRolesAndSites {...props} />
				</ThemeProvider>,
			);

			const sitesContent = screen.getByTestId("final-step-sites-content");
			expect(sitesContent).toBeTruthy();
			expect(sitesContent.textContent).toContain("Access to All Sites");
		});

		it("should not show Access to Sites header when showRows is true or allRoles exist", () => {
			const role = mockRole({ id: 1, name: "Editor" });
			const props = {
				isSuperAdmin: false,
				userRoles: [mockSiteRole("all", [1])],
				sites: [],
				roles: [role],
				showRows: true,
			};

			render(
				<ThemeProvider theme={parseTheme(globalTheme)}>
					<UserRolesAndSites {...props} />
				</ThemeProvider>,
			);

			const sitesContent = screen.getByTestId("final-step-sites-content");
			expect(sitesContent?.textContent).not.toContain("Access to Sites");
		});
	});

	describe("ShowRows Behavior", () => {
		it("should show header when showRows is false and no allRoles", () => {
			const role = mockRole({ id: 1, name: "Editor" });
			const site = mockSite({ id: 1, name: "Test Site" });
			const props = {
				isSuperAdmin: false,
				userRoles: [mockSiteRole(1, [1])],
				sites: [site],
				roles: [role],
				showRows: false,
			};

			render(
				<ThemeProvider theme={parseTheme(globalTheme)}>
					<UserRolesAndSites {...props} />
				</ThemeProvider>,
			);

			const sitesContent = screen.getByTestId("final-step-sites-content");
			expect(sitesContent.textContent).toContain("Access to Sites");
		});

		it("should use default showRows logic when prop is not provided", () => {
			const role = mockRole({ id: 1, name: "Editor" });
			const site = mockSite({ id: 1, name: "Test Site" });
			const props = {
				isSuperAdmin: false,
				userRoles: [mockSiteRole(1, [1])],
				sites: [site],
				roles: [role],
			};

			render(
				<ThemeProvider theme={parseTheme(globalTheme)}>
					<UserRolesAndSites {...props} />
				</ThemeProvider>,
			);

			const sitesContent = screen.getByTestId("final-step-sites-content");
			expect(sitesContent).toBeTruthy();
		});

		it("should show header when superAdmin is false and no global role but has site roles", () => {
			const role = mockRole({ id: 1, name: "Editor" });
			const site = mockSite({ id: 1, name: "Test Site" });
			const props = {
				isSuperAdmin: false,
				userRoles: [mockSiteRole(1, [1])],
				sites: [site],
				roles: [role],
			};

			render(
				<ThemeProvider theme={parseTheme(globalTheme)}>
					<UserRolesAndSites {...props} />
				</ThemeProvider>,
			);

			const sitesContent = screen.getByTestId("final-step-sites-content");
			expect(sitesContent.textContent).toContain("Access to Sites");
		});

		it("should not show header when showRows is true", () => {
			const role = mockRole({ id: 1, name: "Editor" });
			const site = mockSite({ id: 1, name: "Test Site" });
			const props = {
				isSuperAdmin: false,
				userRoles: [mockSiteRole(1, [1])],
				sites: [site],
				roles: [role],
				showRows: true,
			};

			render(
				<ThemeProvider theme={parseTheme(globalTheme)}>
					<UserRolesAndSites {...props} />
				</ThemeProvider>,
			);

			const sitesContent = screen.getByTestId("final-step-sites-content");
			expect(sitesContent.textContent).not.toContain("Access to Sites");
		});
	});

	describe("Role Rendering with ElementsTooltip", () => {
		it("should render role names in site cards", () => {
			const roles = [
				mockRole({ id: 1, name: "Editor", hex: "#5057FF" }),
				mockRole({ id: 2, name: "Viewer", hex: "#FF0000" }),
			];
			const site = mockSite({ id: 1, name: "Test Site" });
			const props = {
				isSuperAdmin: false,
				userRoles: [mockSiteRole(1, [1, 2])],
				sites: [site],
				roles,
			};

			render(
				<ThemeProvider theme={parseTheme(globalTheme)}>
					<UserRolesAndSites {...props} />
				</ThemeProvider>,
			);

			expect(screen.getByText("Test Site")).toBeTruthy();
		});

		it("should handle empty roles array in site card", () => {
			const site = mockSite({ id: 1, name: "Test Site" });
			const props = {
				isSuperAdmin: false,
				userRoles: [mockSiteRole(1, [])],
				sites: [site],
				roles: [],
			};

			render(
				<ThemeProvider theme={parseTheme(globalTheme)}>
					<UserRolesAndSites {...props} />
				</ThemeProvider>,
			);

			expect(screen.getByText("Test Site")).toBeTruthy();
		});

		it("should map role ids to role names and colors correctly", () => {
			const roles = [
				mockRole({ id: 1, name: "Editor", hex: "#5057FF" }),
				mockRole({ id: 2, name: "Viewer", hex: "#FF0000" }),
				mockRole({ id: 3, name: "Admin", hex: "#00FF00" }),
			];
			const site = mockSite({ id: 1, name: "Test Site" });
			const props = {
				isSuperAdmin: false,
				userRoles: [mockSiteRole(1, [1, 3])],
				sites: [site],
				roles,
			};

			render(
				<ThemeProvider theme={parseTheme(globalTheme)}>
					<UserRolesAndSites {...props} />
				</ThemeProvider>,
			);

			expect(screen.getByText("Test Site")).toBeTruthy();
		});
	});

	describe("Edge Cases", () => {
		it("should handle user with no roles at all", () => {
			const props = {
				isSuperAdmin: false,
				userRoles: [],
				sites: [],
				roles: [],
			};

			render(
				<ThemeProvider theme={parseTheme(globalTheme)}>
					<UserRolesAndSites {...props} />
				</ThemeProvider>,
			);

			expect(screen.queryByTestId("final-step-sites-content")).toBeFalsy();
		});

		it("should handle multiple roles per site", () => {
			const roles = [
				mockRole({ id: 1, name: "Editor" }),
				mockRole({ id: 2, name: "Viewer" }),
				mockRole({ id: 3, name: "Manager" }),
			];
			const site = mockSite({ id: 1, name: "Test Site" });
			const props = {
				isSuperAdmin: false,
				userRoles: [mockSiteRole(1, [1, 2, 3])],
				sites: [site],
				roles,
			};

			render(
				<ThemeProvider theme={parseTheme(globalTheme)}>
					<UserRolesAndSites {...props} />
				</ThemeProvider>,
			);

			expect(screen.getByText("Test Site")).toBeTruthy();
		});

		it("should handle global and all sites roles together", () => {
			const role = mockRole({ id: 1, name: "Editor" });
			const site = mockSite({ id: 1, name: "Test Site" });
			const props = {
				isSuperAdmin: false,
				userRoles: [mockSiteRole("global", [1]), mockSiteRole("all", [1])],
				sites: [site],
				roles: [role],
			};

			render(
				<ThemeProvider theme={parseTheme(globalTheme)}>
					<UserRolesAndSites {...props} />
				</ThemeProvider>,
			);

			expect(screen.getByTestId("final-step-global-role")).toBeTruthy();
			expect(screen.getByTestId("final-step-sites-content")).toBeTruthy();
		});

		it("should not render sites content when super admin has site-specific roles", () => {
			const role = mockRole({ id: 1, name: "Editor" });
			const site = mockSite({ id: 1, name: "Test Site" });
			const props = {
				isSuperAdmin: true,
				userRoles: [mockSiteRole(1, [1])],
				sites: [site],
				roles: [role],
			};

			render(
				<ThemeProvider theme={parseTheme(globalTheme)}>
					<UserRolesAndSites {...props} />
				</ThemeProvider>,
			);

			expect(screen.queryByTestId("final-step-sites-content")).toBeFalsy();
		});
	});
});
