"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 { request, useApi } from "@/hooks/use-api";

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() {
	const [newRoleName, setNewRoleName] = useState<string>("");
	const [isDialogOpen, setIsDialogOpen] = useState<boolean>(false);

	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>
				<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
						key={index}
						role={role}
						permissions={permissions}
						onDelete={() => deleteRole(role.id)}
					/>
				))}
		</div>
	);
}

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

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

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

function ResourceSection({
	resource,
	defaultActions,
	role,
}: 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
					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>
	);
}
