"use client";

import { useState } from "react";
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card";
import { Checkbox } from "@/components/ui/checkbox";
import { Button } from "@/components/ui/button";
import { Input } from "@/components/ui/input";
import {
	Dialog,
	DialogContent,
	DialogHeader,
	DialogTitle,
	DialogTrigger,
	DialogFooter,
} from "@/components/ui/dialog";
import { ChevronDown, ChevronRight, Plus, Trash2 } from "lucide-react";
import { toTitleCase } from "@/lib/utils";
import { useApi } from "@/hooks/use-api";
import request from "@/lib/request";
import IUser from "@/interfaces/IUser";
import hasPermissions from "@/lib/hasPermissions";

type Action = string;

interface Permission {
	resource: string;
	action: Action;
}

interface Role {
	id: string;
	name: string;
	permissions?: Permission[];
}

interface PermissionsGrouped {
	[key: string]: string[];
}

export default function RolesAndPermissions({ user }: { user: IUser }) {
	const [newRoleName, setNewRoleName] = useState<string>("");
	const [isDialogOpen, setIsDialogOpen] = useState<boolean>(false);

	const { roles: rolesPerm } = hasPermissions(user.roles, {
		roles: ["insert"],
	} as const);

	const { data: permissions } = useApi<PermissionsGrouped>(
		"/permissions/grouped",
		{},
		true,
	);

	const { data: roles, mutate: rolesMutate } = useApi<Role[]>(
		"/roles",
		{},
		true,
	);

	const addNewRole = async () => {
		if (newRoleName.trim() === "") return;

		const res = await request("/roles/new", {
			requiresAuth: true,
			method: "POST",
			body: { name: newRoleName },
		});

		if (res.status === "Success") rolesMutate();

		setNewRoleName("");
		setIsDialogOpen(false);
	};

	const deleteRole = async (id: string) => {
		const res = await request(`/roles/${id}/delete`, {
			method: "DELETE",
			requiresAuth: true,
		});
		if (res.status === "Success") rolesMutate();
	};

	return (
		<div className="container mx-auto p-4 space-y-6">
			<div className="flex justify-between items-center">
				<h1 className="text-2xl font-bold">Rôles et Permissions</h1>
				{rolesPerm.insert && (
					<Dialog open={isDialogOpen} onOpenChange={setIsDialogOpen}>
						<DialogTrigger asChild>
							<Button>
								<Plus className="mr-2 h-4 w-4" /> Nouveau rôle
							</Button>
						</DialogTrigger>
						<DialogContent>
							<DialogHeader>
								<DialogTitle>Nouveau rôle</DialogTitle>
							</DialogHeader>
							<div className="py-4">
								<Input
									placeholder="Nom du rôle"
									value={newRoleName}
									onChange={(e) =>
										setNewRoleName(e.target.value)
									}
								/>
							</div>
							<DialogFooter>
								<Button
									onClick={addNewRole}
									disabled={newRoleName.trim() === ""}
								>
									Ajouter
								</Button>
							</DialogFooter>
						</DialogContent>
					</Dialog>
				)}
			</div>
			{permissions &&
				roles &&
				roles.map((role, index) => (
					<RoleCard
						user={user}
						key={index}
						role={role}
						permissions={permissions}
						onDelete={() => deleteRole(role.id)}
					/>
				))}
		</div>
	);
}

interface RoleCardProps {
	user: IUser;
	role: Role;
	onDelete: () => void;
	permissions: PermissionsGrouped;
}

function RoleCard({ role, onDelete, permissions, user }: RoleCardProps) {
	const { roles, permissions: permPerms } = hasPermissions(user.roles, {
		roles: ["delete", "update"],
		permissions: ["update"],
	} as const);

	return (
		<Card>
			<CardHeader className="flex flex-row items-center justify-between space-y-0 pb-2">
				<CardTitle>{toTitleCase(role.name)}</CardTitle>
				<Button
					disabled={!roles.delete}
					variant="destructive"
					size="icon"
					onClick={onDelete}
				>
					<Trash2 className="h-4 w-4" />
				</Button>
			</CardHeader>
			<CardContent>
				{Object.entries(permissions).map(([res, actions]) => {
					return (
						<ResourceSection
							disabled={
								!(roles.update && permPerms.update)
								// !hasPermissions(user.roles, {
								// 	permissions: ["update"],
								// 	roles: ["update"],
								// })
							}
							key={res}
							resource={res}
							defaultActions={actions}
							role={role}
						/>
					);
				})}
			</CardContent>
		</Card>
	);
}

interface ResourceSectionProps {
	disabled?: boolean;
	resource: string;
	defaultActions: string[];
	role: Role;
}

function ResourceSection({
	resource,
	defaultActions,
	role,
	disabled = false,
}: ResourceSectionProps) {
	const [isExpanded, setIsExpanded] = useState<boolean>(false);

	const a = (role.permissions ?? [])
		.map((p) => (p.resource === resource ? p.action : null))
		.filter((a) => a !== null);

	const ActionCheckbox = ({ action }: { action: Action }) => {
		const [checked, setChecked] = useState(a.includes(action));
		return (
			<div key={action} className="flex items-center space-x-2">
				<Checkbox
					disabled={disabled}
					onCheckedChange={async (e) => {
						if (typeof e === "boolean") {
							const res = await request(
								`/roles/${role.id}/permissions/${resource}/${action}/${e ? "add" : "remove"}`,
								{ method: "PATCH", requiresAuth: true },
							);
							if (res.status === "Success") setChecked(e);
						}
					}}
					checked={checked}
					id={`${resource}-${action}`}
				/>
				<label
					htmlFor={`${resource}-${action}`}
					className="text-sm font-medium leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70"
				>
					{action}
				</label>
			</div>
		);
	};

	return (
		<div className="mb-4">
			<button
				className="flex items-center text-lg font-semibold mb-2"
				onClick={() => setIsExpanded(!isExpanded)}
			>
				{isExpanded ? (
					<ChevronDown className="mr-2" />
				) : (
					<ChevronRight className="mr-2" />
				)}
				{toTitleCase(resource)}
			</button>
			{isExpanded && (
				<div className="grid grid-cols-2 sm:grid-cols-4 gap-2 ml-6">
					{defaultActions.map((action) => (
						<ActionCheckbox
							key={`${resource}:${action}`}
							action={action}
						/>
					))}
				</div>
			)}
		</div>
	);
}
