"use client";

import { useState, useEffect, useMemo, useCallback } from "react";
import {
  Table,
  TableBody,
  TableCell,
  TableHead,
  TableHeader,
  TableRow,
} from "@/components/ui/table";
import { Button } from "@/components/ui/button";
import { useSession } from "next-auth/react";
import { Input } from "@/components/ui/input";
import { MoreHorizontal, Trash, Edit, UserPlus, Key, Lock, Unlock } from "lucide-react";
import {
  DropdownMenu,
  DropdownMenuContent,
  DropdownMenuItem,
  DropdownMenuLabel,
  DropdownMenuSeparator,
  DropdownMenuTrigger,
} from "@/components/ui/dropdown-menu";
import { toast } from "@/components/ui/use-toast";
import {
  Dialog,
  DialogContent,
  DialogHeader,
  DialogTitle,
  DialogTrigger,
} from "@/components/ui/dialog";
import { Label } from "@/components/ui/label";
import {
  Select,
  SelectContent,
  SelectItem,
  SelectTrigger,
  SelectValue,
} from "@/components/ui/select";
import { Checkbox } from "@/components/ui/checkbox";

interface User {
  id: string;
  username: string;
  firstName: string;
  lastName: string;
  email: string;
  createdTimestamp: number;
  roles: string[];
  enabled: boolean;
}

interface Role {
  id: string;
  name: string;
  description: string;
  composite: boolean;
  clientRole: boolean;
  containerId: string;
}

interface UsersTableProps {
  userRole?: string[];
}

const ITEMS_PER_PAGE = 10;

// DialogWrapper component to better handle dialog state
function DialogWrapper({ 
  open, 
  onOpenChange, 
  onAfterClose,
  triggerComponent,
  children, 
  className 
}: {
  open: boolean;
  onOpenChange: (open: boolean) => void;
  onAfterClose?: () => void;
  triggerComponent?: React.ReactNode;
  children: React.ReactNode;
  className?: string;
}) {
  const handleOpenChange = useCallback((open: boolean) => {
    onOpenChange(open);
    
    if (!open && onAfterClose) {
      // Use a longer timeout to ensure all animations are complete
      setTimeout(onAfterClose, 300);
    }
  }, [onOpenChange, onAfterClose]);

  return (
    <Dialog open={open} onOpenChange={handleOpenChange}>
      {triggerComponent && <DialogTrigger asChild>{triggerComponent}</DialogTrigger>}
      <DialogContent className={className}>
        {children}
      </DialogContent>
    </Dialog>
  );
}

export function UsersTable({ userRole = [] }: UsersTableProps) {
  const { data: session, status } = useSession();
  const [users, setUsers] = useState<User[]>([]);
  const [roles, setRoles] = useState<Role[]>([]);
  const [loading, setLoading] = useState(true);
  const [currentPage, setCurrentPage] = useState(1);
  const [searchTerm, setSearchTerm] = useState("");
  const [newUserDialog, setNewUserDialog] = useState(false);
  const [editUserDialog, setEditUserDialog] = useState(false);
  const [manageRolesDialog, setManageRolesDialog] = useState(false);
  const [selectedUser, setSelectedUser] = useState<User | null>(null);
  const [formData, setFormData] = useState({
    username: "",
    lastName: "",
    firstName: "",
    email: "",
    password: "",
    roles: [] as string[],
    enabled: true,
  });

  useEffect(() => {
    fetchUsers();
    fetchRoles();
  }, []);

  const fetchRoles = async () => {
    try {
      const response = await fetch("/api/roles");
      if (!response.ok) {
        throw new Error("Failed to fetch roles");
      }
      const data = await response.json();
      setRoles(data);
    } catch (error) {
      console.error("Error fetching roles:", error);
      toast({
        title: "Erreur",
        description: "Erreur lors de la récupération des rôles",
        variant: "destructive",
      });
    }
  };

  const fetchUsers = async () => {
    try {
      setLoading(true);
      const response = await fetch("/api/users");
      const data = await response.json();
      setUsers(data);
    } catch (error) {
      console.error("Error fetching users:", error);
      toast({
        title: "Erreur",
        description: "Erreur lors de la récupération des utilisateurs",
        variant: "destructive",
      });
    } finally {
      setLoading(false);
    }
  };

  const handleAddUser = async (e: React.FormEvent) => {
    e.preventDefault();
    try {
      const response = await fetch("/api/users", {
        method: "POST",
        headers: {
          "Content-Type": "application/json",
        },
        body: JSON.stringify({
          ...formData,
          firstName: formData.firstName,
          lastName: formData.lastName,
        }),
      });

      const data = await response.json();

      if (!response.ok) {
        throw new Error(data.error || "Erreur lors de la création de l'utilisateur");
      }

      setUsers(prev => [...prev, data.user]);
      setNewUserDialog(false);
      setFormData({
        username: "",
        firstName: "",
        lastName: "",
        email: "",
        password: "",
        roles: [],
        enabled: true,
      });
      
      toast({
        title: "Succès",
        description: "L'utilisateur a été créé avec succès",
      });
    } catch (error) {
      toast({
        title: "Erreur",
        description: error instanceof Error ? error.message : "Une erreur est survenue",
        variant: "destructive",
      });
    }
  };

  const handleEdit = async (userId: string) => {
    const user = users.find(u => u.id === userId);
    if (!user) return;

    setSelectedUser(user);
    setFormData({
      username: user.username,
      firstName: user.firstName || "",
      lastName: user.lastName || "",
      email: user.email || "",
      password: "",
      roles: [],
      enabled: user.enabled,
    });
    setEditUserDialog(true);
  };

  const handleManageRoles = async (userId: string) => {
    const user = users.find(u => u.id === userId);
    if (!user) return;

    setSelectedUser(user);
    setFormData(prev => ({ 
      ...prev,
      roles: user.roles || [],
      username: user.username,
      firstName: user.firstName || "",
      lastName: user.lastName || "",
      email: user.email || "",
    }));
    setManageRolesDialog(true);
  };

  const handleUpdateRoles = async () => {
    if (!selectedUser) return;

    try {
      const response = await fetch(`/api/users/${selectedUser.id}/roles`, {
        method: "PUT",
        headers: {
          "Content-Type": "application/json",
        },
        body: JSON.stringify({
          roles: formData.roles,
        }),
      });

      if (!response.ok) {
        throw new Error("Erreur lors de la mise à jour des rôles");
      }

      await fetchUsers();

      setManageRolesDialog(false);
      setSelectedUser(null);
      setFormData(prev => ({ ...prev, roles: [] }));
      
      toast({
        title: "Succès",
        description: "Les rôles ont été mis à jour avec succès",
      });
    } catch (error) {
      toast({
        title: "Erreur",
        description: error instanceof Error ? error.message : "Une erreur est survenue",
        variant: "destructive",
      });
    }
  };

  const handleUpdateUser = async (e: React.FormEvent) => {
    e.preventDefault();
    if (!selectedUser) return;

    try {
      const response = await fetch(`/api/users/${selectedUser.id}`, {
        method: "PUT",
        headers: {
          "Content-Type": "application/json",
        },
        body: JSON.stringify({
          firstName: formData.firstName,
          lastName: formData.lastName,
          email: formData.email,
        }),
      });

      if (!response.ok) {
        throw new Error("Erreur lors de la modification de l'utilisateur");
      }

      await fetchUsers();
      
      setFormData({
        username: "",
        lastName: "",
        firstName: "",
        email: "",
        password: "",
        roles: [],
        enabled: true,
      });
      setEditUserDialog(false);
      setSelectedUser(null);
      
      toast({
        title: "Succès",
        description: "L'utilisateur a été modifié avec succès",
      });
    } catch (error) {
      toast({
        title: "Erreur",
        description: error instanceof Error ? error.message : "Une erreur est survenue",
        variant: "destructive",
      });
    }
  };

  const handleDelete = async (userId: string, email: string) => {
    try {
      const response = await fetch(`/api/users?id=${userId}&email=${encodeURIComponent(email)}`, {
        method: "DELETE",
      });

      const data = await response.json();

      if (!response.ok) {
        throw new Error(data.error || "Erreur lors de la suppression de l'utilisateur");
      }

      setUsers(prevUsers => prevUsers.filter(user => user.id !== userId));
      
      toast({
        title: "Succès",
        description: "L'utilisateur a été supprimé avec succès",
      });
    } catch (error) {
      toast({
        title: "Erreur",
        description: error instanceof Error ? error.message : "Une erreur est survenue",
        variant: "destructive",
      });
    }
  };

  const handleChangePassword = async (userId: string) => {
    const newPassword = prompt("Entrez le nouveau mot de passe temporaire:");
    if (!newPassword) return;

    try {
      const response = await fetch(`/api/users/${userId}/password`, {
        method: "PUT",
        headers: {
          "Content-Type": "application/json",
        },
        body: JSON.stringify({ 
          password: newPassword,
          temporary: true
        }),
      });

      if (!response.ok) {
        throw new Error("Erreur lors du changement de mot de passe");
      }

      toast({
        title: "Succès",
        description: "Le mot de passe temporaire a été défini avec succès. L'utilisateur devra le changer à sa première connexion.",
      });
    } catch (error) {
      toast({
        title: "Erreur",
        description: error instanceof Error ? error.message : "Une erreur est survenue",
        variant: "destructive",
      });
    }
  };

  const handleToggleUserStatus = async (userId: string, currentStatus: boolean) => {
    try {
      const response = await fetch(`/api/users/${userId}`, {
        method: "PUT",
        headers: {
          "Content-Type": "application/json",
        },
        body: JSON.stringify({ enabled: !currentStatus }),
      });

      if (!response.ok) {
        throw new Error("Erreur lors de la modification du statut de l'utilisateur");
      }

      setUsers(prevUsers => prevUsers.map(u => 
        u.id === userId ? { ...u, enabled: !currentStatus } : u
      ));

      toast({
        title: "Succès",
        description: `L'utilisateur a été ${!currentStatus ? "activé" : "désactivé"} avec succès`,
      });
    } catch (error) {
      toast({
        title: "Erreur",
        description: error instanceof Error ? error.message : "Une erreur est survenue",
        variant: "destructive",
      });
    }
  };

  const filteredUsers = useMemo(() => {
    let filtered = users;
    
    if (searchTerm) {
      filtered = filtered.filter(user => 
        user.username.toLowerCase().includes(searchTerm.toLowerCase()) ||
        user.email?.toLowerCase().includes(searchTerm.toLowerCase()) ||
        user.firstName?.toLowerCase().includes(searchTerm.toLowerCase()) ||
        user.lastName?.toLowerCase().includes(searchTerm.toLowerCase())
      );
    }
    
    return filtered;
  }, [users, searchTerm]);

  const totalPages = Math.ceil(filteredUsers.length / ITEMS_PER_PAGE);
  const paginatedUsers = filteredUsers.slice(
    (currentPage - 1) * ITEMS_PER_PAGE,
    currentPage * ITEMS_PER_PAGE
  );

  // Define reset function callbacks
  const resetNewUserForm = useCallback(() => {
    setFormData({
      username: "",
      lastName: "",
      firstName: "",
      email: "",
      password: "",
      roles: [],
      enabled: true,
    });
  }, []);

  const resetEditForm = useCallback(() => {
    setFormData({
      username: "",
      lastName: "",
      firstName: "",
      email: "",
      password: "",
      roles: [],
      enabled: true,
    });
    setSelectedUser(null);
  }, []);

  const resetRolesForm = useCallback(() => {
    setFormData(prev => ({ ...prev, roles: [] }));
    setSelectedUser(null);
  }, []);

  if (!session) return null;
  if (loading) return <div className="text-center p-4">Loading...</div>;

  return (
    <div className="space-y-4 p-6 bg-gray-100 rounded-lg">
      <div className="flex justify-between items-center">
        <Input
          type="text"
          placeholder="Rechercher un utilisateur..."
          value={searchTerm}
          onChange={(e) => setSearchTerm(e.target.value)}
          className="max-w-sm bg-white text-gray-900 border-gray-300"
        />
        <DialogWrapper
          open={newUserDialog}
          onOpenChange={setNewUserDialog}
          onAfterClose={resetNewUserForm}
          triggerComponent={
            <Button className="bg-blue-600 hover:bg-blue-700 text-white">
              Ajouter un utilisateur
            </Button>
          }
          className="max-h-[85vh] overflow-y-auto bg-white text-black border border-gray-300"
        >
          <DialogHeader>
            <DialogTitle className="text-gray-900">Nouvel Utilisateur</DialogTitle>
          </DialogHeader>
          <form onSubmit={handleAddUser} className="space-y-3">
            <div className="grid grid-cols-2 gap-3">
              <div className="space-y-2">
                <Label htmlFor="username" className="text-gray-900">Nom d'utilisateur</Label>
                <Input
                  id="username"
                  value={formData.username}
                  onChange={(e) => setFormData(prev => ({ ...prev, username: e.target.value.trim() }))}
                  required
                  className="bg-white text-gray-900 border-gray-300"
                />
              </div>
              <div className="space-y-2">
                <Label htmlFor="email" className="text-gray-900">Email</Label>
                <Input
                  id="email"
                  type="email"
                  value={formData.email}
                  onChange={(e) => setFormData(prev => ({ ...prev, email: e.target.value.trim() }))}
                  required
                  className="bg-white text-gray-900 border-gray-300"
                />
              </div>
            </div>
            <div className="grid grid-cols-2 gap-3">
              <div className="space-y-2">
                <Label htmlFor="firstName" className="text-gray-900">Prénom</Label>
                <Input
                  id="firstName"
                  value={formData.firstName}
                  onChange={(e) => setFormData(prev => ({ ...prev, firstName: e.target.value.trim() }))}
                  required
                  className="bg-white text-gray-900 border-gray-300"
                />
              </div>
              <div className="space-y-2">
                <Label htmlFor="lastName" className="text-gray-900">Nom</Label>
                <Input
                  id="lastName"
                  value={formData.lastName}
                  onChange={(e) => setFormData(prev => ({ ...prev, lastName: e.target.value.trim() }))}
                  required
                  className="bg-white text-gray-900 border-gray-300"
                />
              </div>
            </div>
            <div className="space-y-2">
              <Label htmlFor="password" className="text-gray-900">Mot de passe</Label>
              <Input
                id="password"
                type="password"
                value={formData.password}
                onChange={(e) => setFormData(prev => ({ ...prev, password: e.target.value }))}
                required
                className="bg-white text-gray-900 border-gray-300"
              />
            </div>
            <div className="space-y-2">
              <Label className="text-gray-900">Rôles</Label>
              <div className="grid grid-cols-2 gap-2 max-h-[120px] overflow-y-auto border border-gray-300 rounded-md p-2 bg-white">
                {roles.map((role) => (
                  <div key={role.id} className="flex items-center space-x-2">
                    <Checkbox
                      id={`role-${role.id}`}
                      checked={formData.roles.includes(role.name)}
                      onCheckedChange={(checked) => {
                        setFormData(prev => ({
                          ...prev,
                          roles: checked
                            ? [...prev.roles, role.name]
                            : prev.roles.filter(r => r !== role.name)
                        }));
                      }}
                      className="border-gray-500"
                    />
                    <Label htmlFor={`role-${role.id}`} className="text-sm text-gray-900">{role.name}</Label>
                  </div>
                ))}
              </div>
            </div>
            <Button type="submit" className="w-full bg-blue-600 hover:bg-blue-700 text-white">Créer Utilisateur</Button>
          </form>
        </DialogWrapper>
      </div>

      <Table className="bg-white border border-gray-300 rounded-md">
        <TableHeader className="bg-gray-50">
          <TableRow>
            <TableHead className="text-gray-900">Username</TableHead>
            <TableHead className="text-gray-900">First Name</TableHead>
            <TableHead className="text-gray-900">Last Name</TableHead>
            <TableHead className="text-gray-900">Email</TableHead>
            <TableHead className="text-gray-900">Created At</TableHead>
            <TableHead className="text-gray-900">Roles</TableHead>
            <TableHead className="text-gray-900 text-right">Actions</TableHead>
          </TableRow>
        </TableHeader>
        <TableBody>
          {paginatedUsers.map((user) => (
            <TableRow key={user.id} className="hover:bg-gray-50 border-t border-gray-200">
              <TableCell className="text-gray-900">{user.username}</TableCell>
              <TableCell className="text-gray-900">{user.firstName || "-"}</TableCell>
              <TableCell className="text-gray-900">{user.lastName || "-"}</TableCell>
              <TableCell className="text-gray-900">{user.email || "-"}</TableCell>
              <TableCell className="text-gray-900">
                {new Date(user.createdTimestamp).toLocaleDateString()}
              </TableCell>
              <TableCell className="text-gray-900">
                <div className="flex flex-wrap gap-1">
                  {(user.roles || []).map((role) => (
                    <span key={role} className="inline-flex items-center rounded-full bg-blue-50 px-2 py-1 text-xs font-medium text-blue-700 ring-1 ring-inset ring-blue-700/10">
                      {role}
                    </span>
                  ))}
                </div>
              </TableCell>
              <TableCell className="text-gray-900 text-right">
                <DropdownMenu>
                  <DropdownMenuTrigger asChild>
                    <Button 
                      variant="ghost" 
                      className="h-8 w-8 p-0"
                    >
                      <span className="sr-only">Open menu</span>
                      <MoreHorizontal className="h-4 w-4" />
                    </Button>
                  </DropdownMenuTrigger>
                  <DropdownMenuContent align="end" className="bg-white border border-gray-300">
                    <DropdownMenuLabel className="text-gray-900">Actions</DropdownMenuLabel>
                    <DropdownMenuItem 
                      onClick={() => handleEdit(user.id)}
                      className="text-gray-900 hover:bg-gray-100"
                    >
                      <Edit className="mr-2 h-4 w-4" />
                      Modifier
                    </DropdownMenuItem>
                    <DropdownMenuItem 
                      onClick={() => handleManageRoles(user.id)}
                      className="text-gray-900 hover:bg-gray-100"
                    >
                      <UserPlus className="mr-2 h-4 w-4" />
                      Gérer les rôles
                    </DropdownMenuItem>
                    <DropdownMenuItem 
                      onClick={() => handleChangePassword(user.id)}
                      className="text-gray-900 hover:bg-gray-100"
                    >
                      <Key className="mr-2 h-4 w-4" />
                      Changer le mot de passe
                    </DropdownMenuItem>
                    <DropdownMenuItem 
                      onClick={() => handleToggleUserStatus(user.id, user.enabled)}
                      className="text-gray-900 hover:bg-gray-100"
                    >
                      {user.enabled ? (
                        <>
                          <Lock className="mr-2 h-4 w-4" />
                          Désactiver
                        </>
                      ) : (
                        <>
                          <Unlock className="mr-2 h-4 w-4" />
                          Activer
                        </>
                      )}
                    </DropdownMenuItem>
                    <DropdownMenuSeparator />
                    <DropdownMenuItem
                      className="text-red-600 hover:bg-red-50 hover:text-red-700"
                      onClick={() => handleDelete(user.id, user.email)}
                    >
                      <Trash className="mr-2 h-4 w-4" />
                      Supprimer
                    </DropdownMenuItem>
                  </DropdownMenuContent>
                </DropdownMenu>
              </TableCell>
            </TableRow>
          ))}
        </TableBody>
      </Table>

      <DialogWrapper
        open={editUserDialog}
        onOpenChange={setEditUserDialog}
        onAfterClose={resetEditForm}
        className="bg-white text-black border border-gray-300"
      >
        <DialogHeader>
          <DialogTitle className="text-gray-900">Modifier l'utilisateur</DialogTitle>
        </DialogHeader>
        <form onSubmit={handleUpdateUser} className="space-y-4">
          <div className="space-y-2">
            <Label htmlFor="edit-firstName" className="text-gray-900">Prénom</Label>
            <Input
              id="edit-firstName"
              value={formData.firstName}
              onChange={(e) => setFormData(prev => ({ ...prev, firstName: e.target.value }))}
              className="bg-white text-gray-900 border-gray-300"
              autoFocus
            />
          </div>
          <div className="space-y-2">
            <Label htmlFor="edit-lastName" className="text-gray-900">Nom</Label>
            <Input
              id="edit-lastName"
              value={formData.lastName}
              onChange={(e) => setFormData(prev => ({ ...prev, lastName: e.target.value }))}
              className="bg-white text-gray-900 border-gray-300"
            />
          </div>
          <div className="space-y-2">
            <Label htmlFor="edit-email" className="text-gray-900">Email</Label>
            <Input
              id="edit-email"
              type="email"
              value={formData.email}
              onChange={(e) => setFormData(prev => ({ ...prev, email: e.target.value }))}
              className="bg-white text-gray-900 border-gray-300"
            />
          </div>
          <div className="flex justify-end space-x-2">
            <Button
              type="button"
              variant="outline"
              onClick={() => {
                setEditUserDialog(false);
                setSelectedUser(null);
                setFormData({
                  username: "",
                  lastName: "",
                  firstName: "",
                  email: "",
                  password: "",
                  roles: [],
                  enabled: true,
                });
              }}
              className="border-gray-300 text-gray-800 hover:bg-gray-100"
            >
              Annuler
            </Button>
            <Button type="submit" className="bg-blue-600 hover:bg-blue-700 text-white">
              Modifier
            </Button>
          </div>
        </form>
      </DialogWrapper>

      <DialogWrapper
        open={manageRolesDialog}
        onOpenChange={setManageRolesDialog}
        onAfterClose={resetRolesForm}
        className="bg-white text-black border border-gray-300"
      >
        <DialogHeader>
          <DialogTitle className="text-gray-900">Gérer les rôles pour {selectedUser?.username}</DialogTitle>
        </DialogHeader>
        <div className="space-y-4">
          <div className="space-y-2">
            <Label className="text-gray-900">Rôles disponibles</Label>
            <div className="grid grid-cols-2 gap-2 max-h-[200px] overflow-y-auto border border-gray-300 rounded-md p-2 bg-white">
              {roles.map((role) => (
                <div key={role.id} className="flex items-center space-x-2 p-2 rounded-md hover:bg-gray-100">
                  <Checkbox
                    id={`manage-role-${role.id}`}
                    checked={formData.roles.includes(role.name)}
                    onCheckedChange={(checked) => {
                      setFormData(prev => ({
                        ...prev,
                        roles: checked
                          ? [...prev.roles, role.name]
                          : prev.roles.filter(r => r !== role.name)
                      }));
                    }}
                    className="border-gray-500"
                  />
                  <Label 
                    htmlFor={`manage-role-${role.id}`}
                    className="text-sm text-gray-900"
                  >
                    {role.name}
                  </Label>
                </div>
              ))}
            </div>
          </div>
          <div className="flex justify-end space-x-2">
            <Button
              variant="outline"
              onClick={() => {
                setManageRolesDialog(false);
                setSelectedUser(null);
                setFormData(prev => ({ ...prev, roles: [] }));
              }}
              className="border-gray-300 text-gray-800 hover:bg-gray-100"
            >
              Annuler
            </Button>
            <Button onClick={handleUpdateRoles} className="bg-blue-600 hover:bg-blue-700 text-white">
              Mettre à jour les rôles
            </Button>
          </div>
        </div>
      </DialogWrapper>
    </div>
  );
}
