"use client";

import { useState, useEffect, useCallback } from "react";
import {
  Table,
  TableBody,
  TableCell,
  TableHead,
  TableHeader,
  TableRow,
} from "@/components/ui/table";
import { Button } from "@/components/ui/button";
import { Input } from "@/components/ui/input";
import { Plus, MoreHorizontal, Trash, Edit, Users, Palette } from "lucide-react";
import {
  Dialog,
  DialogContent,
  DialogHeader,
  DialogTitle,
  DialogTrigger,
} from "@/components/ui/dialog";
import {
  DropdownMenu,
  DropdownMenuContent,
  DropdownMenuItem,
  DropdownMenuLabel,
  DropdownMenuSeparator,
  DropdownMenuTrigger,
} from "@/components/ui/dropdown-menu";
import { Label } from "@/components/ui/label";
import { toast } from "@/components/ui/use-toast";

interface Group {
  id: string;
  name: string;
  path: string;
  membersCount: number;
  calendarColor?: string;
}

interface User {
  id: string;
  username: string;
  email: string;
  lastName: string;
  firstName: string;
}

interface ApiError {
  message: string;
}

interface GroupsTableProps {
  userRole?: string[];
}

// 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 GroupsTable({ userRole = [] }: GroupsTableProps) {
  const [groups, setGroups] = useState<Group[]>([]);
  const [loading, setLoading] = useState(true);
  const [searchTerm, setSearchTerm] = useState("");
  const [newGroupDialog, setNewGroupDialog] = useState(false);
  const [newGroupName, setNewGroupName] = useState("");
  const [modifyGroupDialog, setModifyGroupDialog] = useState(false);
  const [selectedGroup, setSelectedGroup] = useState<Group | null>(null);
  const [modifiedGroupName, setModifiedGroupName] = useState("");
  const [manageMembersDialog, setManageMembersDialog] = useState(false);
  const [groupMembers, setGroupMembers] = useState<User[]>([]);
  const [availableUsers, setAvailableUsers] = useState<User[]>([]);
  const [colorPickerDialog, setColorPickerDialog] = useState(false);
  const [selectedGroupForColor, setSelectedGroupForColor] = useState<Group | null>(null);
  const [selectedColor, setSelectedColor] = useState("#4f46e5");

  useEffect(() => {
    fetchGroups();
  }, []);

  const fetchGroups = async () => {
    try {
      setLoading(true);
      const response = await fetch("/api/groups");
      const data = await response.json();

      if (!response.ok) {
        throw new Error(data.message || "Erreur lors de la récupération des groupes");
      }

      const groupsWithCounts = await Promise.all(
        (Array.isArray(data) ? data : []).map(async (group) => {
          try {
            // Fetch members count
            const membersResponse = await fetch(`/api/groups/${group.id}/members`);
            let membersCount = 0;
            if (membersResponse.ok) {
              const members = await membersResponse.json();
              membersCount = Array.isArray(members) ? members.length : 0;
            }

            // Fetch calendar color
            let calendarColor = "#4f46e5"; // Default color
            try {
              const calendarResponse = await fetch(`/api/groups/${group.id}/calendar`);
              if (calendarResponse.ok) {
                const calendar = await calendarResponse.json();
                calendarColor = calendar.color || calendarColor;
              }
            } catch (calendarError) {
              console.warn(`Could not fetch calendar for group ${group.id}:`, calendarError);
            }

            return {
              ...group,
              membersCount,
              calendarColor,
            };
          } catch (error) {
            console.error(`Error fetching data for group ${group.id}:`, error);
            return { ...group, membersCount: 0, calendarColor: "#4f46e5" };
          }
        })
      );

      setGroups(groupsWithCounts);
    } catch (error) {
      toast({
        title: "Erreur",
        description: error instanceof Error ? error.message : "Une erreur est survenue",
        variant: "destructive",
      });
    } finally {
      setLoading(false);
    }
  };

  const handleCreateGroup = async () => {
    try {
      if (!newGroupName.trim()) {
        throw new Error("Le nom du groupe est requis");
      }

      const response = await fetch("/api/groups", {
        method: "POST",
        headers: {
          "Content-Type": "application/json",
        },
        body: JSON.stringify({ name: newGroupName }),
      });

      const data = await response.json();

      if (!response.ok) {
        throw new Error(data.message || "Erreur lors de la création du groupe");
      }

      setGroups(prev => [...prev, data]);
      setNewGroupDialog(false);
      setNewGroupName("");
      toast({
        title: "Succès",
        description: "Le groupe a été créé avec succès",
      });
    } catch (error) {
      toast({
        title: "Erreur",
        description: error instanceof Error ? error.message : "Une erreur est survenue",
        variant: "destructive",
      });
    }
  };

  const handleDeleteGroup = async (groupId: string) => {
    try {
      const response = await fetch(`/api/groups/${groupId}`, {
        method: "DELETE",
      });

      if (!response.ok) {
        throw new Error("Erreur lors de la suppression du groupe");
      }

      setGroups(prev => prev.filter(group => group.id !== groupId));
      toast({
        title: "Succès",
        description: "Le groupe a été supprimé avec succès",
      });
    } catch (error) {
      toast({
        title: "Erreur",
        description: error instanceof Error ? error.message : "Une erreur est survenue",
        variant: "destructive",
      });
    }
  };

  const handleModifyGroup = async (groupId: string) => {
    try {
      const group = groups.find(g => g.id === groupId);
      if (!group) return;

      setSelectedGroup(group);
      setModifiedGroupName(group.name);
      setModifyGroupDialog(true);
    } catch (error) {
      toast({
        title: "Erreur",
        description: error instanceof Error ? error.message : "Une erreur est survenue",
        variant: "destructive",
      });
    }
  };

  const handleUpdateGroup = async () => {
    try {
      if (!selectedGroup || !modifiedGroupName.trim()) {
        throw new Error("Le nom du groupe est requis");
      }

      const response = await fetch(`/api/groups/${selectedGroup.id}`, {
        method: "PUT",
        headers: {
          "Content-Type": "application/json",
        },
        body: JSON.stringify({ name: modifiedGroupName }),
      });

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

      setGroups(prev => prev.map(group => 
        group.id === selectedGroup.id 
          ? { ...group, name: modifiedGroupName }
          : group
      ));
      
      setModifyGroupDialog(false);
      setSelectedGroup(null);
      setModifiedGroupName("");
      
      toast({
        title: "Succès",
        description: "Le groupe a été modifié avec succès",
      });
    } catch (error) {
      toast({
        title: "Erreur",
        description: error instanceof Error ? error.message : "Une erreur est survenue",
        variant: "destructive",
      });
    }
  };

  const handleManageMembers = async (groupId: string) => {
    const group = groups.find(g => g.id === groupId);
    if (!group) return;

    setSelectedGroup(group);
    
    try {
      const membersResponse = await fetch(`/api/groups/${groupId}/members`);
      if (!membersResponse.ok) throw new Error("Failed to fetch group members");
      const members = await membersResponse.json();
      setGroupMembers(members);

      setGroups(prev => prev.map(g => 
        g.id === groupId 
          ? { ...g, membersCount: members.length }
          : g
      ));

      const usersResponse = await fetch("/api/users");
      if (!usersResponse.ok) throw new Error("Failed to fetch users");
      const users = await usersResponse.json();
      setAvailableUsers(users.filter((user: User) => !members.some((m: User) => m.id === user.id)));

      setManageMembersDialog(true);
    } catch (error) {
      toast({
        title: "Erreur",
        description: "Erreur lors de la récupération des membres",
        variant: "destructive",
      });
    }
  };

  const handleAddMember = async (userId: string) => {
    if (!selectedGroup) return;

    try {
      const response = await fetch(`/api/groups/${selectedGroup.id}/members`, {
        method: "POST",
        headers: {
          "Content-Type": "application/json",
        },
        body: JSON.stringify({ userId }),
      });

      if (!response.ok) {
        throw new Error("Failed to add member");
      }

      const updatedMember = availableUsers.find(u => u.id === userId);
      if (updatedMember) {
        setGroupMembers(prev => [...prev, updatedMember]);
        setAvailableUsers(prev => prev.filter(u => u.id !== userId));
      }

      setGroups(prev => prev.map(group => 
        group.id === selectedGroup.id 
          ? { ...group, membersCount: group.membersCount + 1 }
          : group
      ));

      toast({
        title: "Success",
        description: "Member added successfully",
      });
    } catch (error) {
      toast({
        title: "Error",
        description: error instanceof Error ? error.message : "An error occurred",
        variant: "destructive",
      });
    }
  };

  const handleRemoveMember = async (userId: string) => {
    if (!selectedGroup) return;

    try {
      const response = await fetch(`/api/groups/${selectedGroup.id}/members/${userId}`, {
        method: "DELETE",
      });

      if (!response.ok) {
        throw new Error("Failed to remove member");
      }

      const removedMember = groupMembers.find(u => u.id === userId);
      if (removedMember) {
        setGroupMembers(prev => prev.filter(u => u.id !== userId));
        setAvailableUsers(prev => [...prev, removedMember]);
      }

      setGroups(prev => prev.map(group => 
        group.id === selectedGroup.id 
          ? { ...group, membersCount: Math.max(0, group.membersCount - 1) }
          : group
      ));

      toast({
        title: "Success",
        description: "Member removed successfully",
      });
    } catch (error) {
      toast({
        title: "Error",
        description: error instanceof Error ? error.message : "An error occurred",
        variant: "destructive",
      });
    }
  };

  // Reset callbacks
  const resetNewGroupForm = useCallback(() => {
    setNewGroupName("");
  }, []);

  const resetModifyGroupForm = useCallback(() => {
    setSelectedGroup(null);
    setModifiedGroupName("");
  }, []);

  const resetMembersForm = useCallback(() => {
    setSelectedGroup(null);
    setGroupMembers([]);
    setAvailableUsers([]);
  }, []);

  const resetColorPickerForm = useCallback(() => {
    setSelectedGroupForColor(null);
    setSelectedColor("#4f46e5");
  }, []);

  const handleOpenColorPicker = (group: Group) => {
    setSelectedGroupForColor(group);
    setSelectedColor(group.calendarColor || "#4f46e5");
    setColorPickerDialog(true);
  };

  const handleSaveColor = async () => {
    if (!selectedGroupForColor) return;

    try {
      const response = await fetch(`/api/groups/${selectedGroupForColor.id}/calendar`, {
        method: "PATCH",
        headers: {
          "Content-Type": "application/json",
        },
        body: JSON.stringify({ color: selectedColor }),
      });

      if (!response.ok) {
        const errorData = await response.json();
        throw new Error(errorData.error || "Erreur lors de la mise à jour de la couleur");
      }

      // Update local state
      setGroups(prev => prev.map(g => 
        g.id === selectedGroupForColor.id 
          ? { ...g, calendarColor: selectedColor }
          : g
      ));

      setColorPickerDialog(false);
      toast({
        title: "Succès",
        description: "La couleur du calendrier a été mise à jour",
      });
    } catch (error) {
      toast({
        title: "Erreur",
        description: error instanceof Error ? error.message : "Une erreur est survenue",
        variant: "destructive",
      });
    }
  };

  // Predefined color palette
  const colorPalette = [
    "#4f46e5", // Indigo
    "#0891b2", // Cyan
    "#0e7490", // Teal
    "#16a34a", // Green
    "#65a30d", // Lime
    "#ca8a04", // Amber
    "#d97706", // Orange
    "#dc2626", // Red
    "#e11d48", // Rose
    "#9333ea", // Purple
    "#7c3aed", // Violet
    "#2563eb", // Blue
    "#0284c7", // Sky
    "#059669", // Emerald
    "#84cc16", // Lime
    "#eab308", // Yellow
  ];

  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 groupe..."
          value={searchTerm}
          onChange={(e) => setSearchTerm(e.target.value)}
          className="max-w-xs bg-white text-gray-900 border-gray-300"
        />
        <DialogWrapper
          open={newGroupDialog}
          onOpenChange={setNewGroupDialog}
          onAfterClose={resetNewGroupForm}
          triggerComponent={
            <Button className="bg-blue-600 hover:bg-blue-700 text-white">
              <Plus className="mr-2 h-4 w-4" /> Ajouter un groupe
            </Button>
          }
          className="bg-white text-black border border-gray-300"
        >
          <DialogHeader>
            <DialogTitle className="text-gray-900">Nouveau Groupe</DialogTitle>
          </DialogHeader>
          <div className="space-y-4">
            <div className="space-y-2">
              <Label htmlFor="groupName" className="text-gray-900">Nom du groupe</Label>
              <Input
                id="groupName"
                value={newGroupName}
                onChange={(e) => setNewGroupName(e.target.value)}
                placeholder="Entrez le nom du groupe"
                className="bg-white text-gray-900 border-gray-300"
              />
            </div>
            <Button 
              onClick={handleCreateGroup}
              className="w-full bg-blue-600 hover:bg-blue-700 text-white"
            >
              Créer le groupe
            </Button>
          </div>
        </DialogWrapper>
      </div>

      <Table className="bg-white border border-gray-300 rounded-md">
        <TableHeader className="bg-gray-50">
          <TableRow>
            <TableHead className="text-gray-900">Nom</TableHead>
            <TableHead className="text-gray-900">Chemin</TableHead>
            <TableHead className="text-gray-900">Membres</TableHead>
            <TableHead className="text-right text-gray-900">Actions</TableHead>
          </TableRow>
        </TableHeader>
        <TableBody>
          {groups
            .filter(group => 
              group.name.toLowerCase().includes(searchTerm.toLowerCase()) ||
              group.path.toLowerCase().includes(searchTerm.toLowerCase())
            )
            .map((group) => (
              <TableRow key={group.id} className="hover:bg-gray-50 border-t border-gray-200">
                <TableCell className="text-gray-900 font-medium">
                  <div className="flex items-center gap-2">
                    <div 
                      className="w-3 h-3 rounded-full flex-shrink-0" 
                      style={{ backgroundColor: group.calendarColor || "#4f46e5" }}
                    />
                    {group.name}
                  </div>
                </TableCell>
                <TableCell className="text-gray-900">{group.path}</TableCell>
                <TableCell className="text-gray-900">{group.membersCount}</TableCell>
                <TableCell className="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={() => handleModifyGroup(group.id)}
                        className="text-gray-900 hover:bg-gray-100"
                      >
                        <Edit className="mr-2 h-4 w-4" />
                        Modifier
                      </DropdownMenuItem>
                      <DropdownMenuItem
                        onClick={() => handleOpenColorPicker(group)}
                        className="text-gray-900 hover:bg-gray-100"
                      >
                        <Palette className="mr-2 h-4 w-4" />
                        Couleur du calendrier
                      </DropdownMenuItem>
                      <DropdownMenuItem
                        onClick={() => handleManageMembers(group.id)}
                        className="text-gray-900 hover:bg-gray-100"
                      >
                        <Users className="mr-2 h-4 w-4" />
                        Gérer les membres
                      </DropdownMenuItem>
                      <DropdownMenuSeparator />
                      <DropdownMenuItem
                        onClick={() => handleDeleteGroup(group.id)}
                        className="text-red-600 hover:bg-red-50 hover:text-red-700"
                      >
                        <Trash className="mr-2 h-4 w-4" />
                        Supprimer
                      </DropdownMenuItem>
                    </DropdownMenuContent>
                  </DropdownMenu>
                </TableCell>
              </TableRow>
            ))}
        </TableBody>
      </Table>

      <DialogWrapper
        open={modifyGroupDialog}
        onOpenChange={setModifyGroupDialog}
        onAfterClose={resetModifyGroupForm}
        className="bg-white text-black border border-gray-300"
      >
        <DialogHeader>
          <DialogTitle className="text-gray-900">Modifier le groupe</DialogTitle>
        </DialogHeader>
        <div className="space-y-4">
          <div className="space-y-2">
            <Label htmlFor="modifiedGroupName" className="text-gray-900">Nom du groupe</Label>
            <Input
              id="modifiedGroupName"
              value={modifiedGroupName}
              onChange={(e) => setModifiedGroupName(e.target.value)}
              className="bg-white text-gray-900 border-gray-300"
              autoFocus
            />
          </div>
          <Button 
            onClick={handleUpdateGroup}
            className="w-full bg-blue-600 hover:bg-blue-700 text-white"
          >
            Mettre à jour
          </Button>
        </div>
      </DialogWrapper>

      <DialogWrapper
        open={colorPickerDialog}
        onOpenChange={setColorPickerDialog}
        onAfterClose={resetColorPickerForm}
        className="sm:max-w-[400px] bg-white text-black border border-gray-300"
      >
        <DialogHeader>
          <DialogTitle className="text-gray-900">
            Changer la couleur du calendrier - {selectedGroupForColor?.name}
          </DialogTitle>
        </DialogHeader>
        <div className="space-y-4 py-4">
          <div>
            <Label className="text-gray-900 mb-3 block">Couleur sélectionnée</Label>
            <div className="flex items-center gap-3 mb-4">
              <div 
                className="w-16 h-16 rounded-lg border-2 border-gray-300 shadow-sm" 
                style={{ backgroundColor: selectedColor }}
              />
              <div className="flex-1">
                <Input
                  type="text"
                  value={selectedColor}
                  onChange={(e) => setSelectedColor(e.target.value)}
                  className="bg-white text-gray-900 border-gray-300 font-mono"
                  placeholder="#4f46e5"
                />
              </div>
            </div>
          </div>

          <div>
            <Label className="text-gray-900 mb-3 block">Palette de couleurs</Label>
            <div className="grid grid-cols-8 gap-2">
              {colorPalette.map((color) => (
                <button
                  key={color}
                  type="button"
                  onClick={() => setSelectedColor(color)}
                  className={`w-8 h-8 rounded-md border-2 transition-all hover:scale-110 ${
                    selectedColor === color ? 'border-gray-900 shadow-md' : 'border-gray-300'
                  }`}
                  style={{ backgroundColor: color }}
                  title={color}
                />
              ))}
            </div>
          </div>

          <div className="flex justify-end gap-2 pt-4">
            <Button
              variant="outline"
              onClick={() => {
                setColorPickerDialog(false);
                resetColorPickerForm();
              }}
              className="border-gray-300 text-gray-700 hover:bg-gray-50 bg-white"
            >
              Annuler
            </Button>
            <Button
              onClick={handleSaveColor}
              className="bg-blue-600 hover:bg-blue-700 text-white"
            >
              Enregistrer
            </Button>
          </div>
        </div>
      </DialogWrapper>

      <DialogWrapper
        open={manageMembersDialog}
        onOpenChange={setManageMembersDialog}
        onAfterClose={resetMembersForm}
        className="sm:max-w-[600px] max-h-[90vh] overflow-y-auto bg-white text-black border border-gray-300"
      >
        <DialogHeader>
          <DialogTitle className="text-gray-900">
            Gérer les membres - {selectedGroup?.name}
          </DialogTitle>
        </DialogHeader>
        <div className="space-y-4">
          <div>
            <h3 className="text-lg font-medium mb-2 text-gray-900">Membres actuels</h3>
            {groupMembers.length === 0 ? (
              <p className="text-gray-600">Ce groupe n'a pas de membres.</p>
            ) : (
              <div className="space-y-2">
                {groupMembers.map((member) => (
                  <div key={member.id} className="flex items-center justify-between p-2 bg-gray-50 rounded-md border border-gray-200">
                    <div className="text-gray-900">
                      <div className="font-medium">{member.username}</div>
                      <div className="text-sm text-gray-600">{member.firstName} {member.lastName} ({member.email})</div>
                    </div>
                    <Button 
                      variant="outline" 
                      size="sm" 
                      onClick={() => handleRemoveMember(member.id)}
                      className="text-red-600 hover:bg-red-50 hover:text-red-700 border-red-200"
                    >
                      <Trash className="h-4 w-4" />
                    </Button>
                  </div>
                ))}
              </div>
            )}
          </div>
          
          <div>
            <h3 className="text-lg font-medium mb-2 text-gray-900">Ajouter des membres</h3>
            <Input
              type="text"
              placeholder="Rechercher un utilisateur..."
              value={searchTerm}
              onChange={(e) => setSearchTerm(e.target.value)}
              className="mb-2 bg-white text-gray-900 border-gray-300"
            />
            <div className="space-y-2 max-h-[250px] overflow-y-auto">
              {availableUsers
                .filter(user => 
                  !groupMembers.some(member => member.id === user.id) &&
                  (user.username.toLowerCase().includes(searchTerm.toLowerCase()) ||
                  user.email.toLowerCase().includes(searchTerm.toLowerCase()) ||
                  user.firstName.toLowerCase().includes(searchTerm.toLowerCase()) ||
                  user.lastName.toLowerCase().includes(searchTerm.toLowerCase()))
                )
                .map((user) => (
                  <div key={user.id} className="flex items-center justify-between p-2 bg-gray-50 rounded-md border border-gray-200">
                    <div className="text-gray-900">
                      <div className="font-medium">{user.username}</div>
                      <div className="text-sm text-gray-600">{user.firstName} {user.lastName} ({user.email})</div>
                    </div>
                    <Button 
                      variant="outline" 
                      size="sm" 
                      onClick={() => handleAddMember(user.id)}
                      className="text-green-600 hover:bg-green-50 hover:text-green-700 border-green-200"
                    >
                      <Plus className="h-4 w-4" />
                    </Button>
                  </div>
                ))}
            </div>
          </div>
        </div>
      </DialogWrapper>
    </div>
  );
} 