import { useState, useEffect } from "react";
import { useQuery, useMutation } from "@tanstack/react-query";
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card";
import { Button } from "@/components/ui/button";
import { Badge } from "@/components/ui/badge";
import { Avatar, AvatarFallback, AvatarImage } from "@/components/ui/avatar";
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select";
import { useToast } from "@/hooks/use-toast";
import { queryClient, apiRequest } from "@/lib/queryClient";
import { Team, Player } from "@shared/schema";
import {
  Users,
  UserPlus,
  Trophy,
  Target,
  ArrowRight,
  Save,
  RefreshCw,
  Search,
  Filter
} from "lucide-react";

interface DragDropRosterProps {
  selectedTeamId?: number;
  onTeamSelect?: (teamId: number) => void;
}

interface PlayerWithTeam extends Player {
  teamName?: string;
}

interface PositionSlot {
  id: string;
  position: string;
  playerId?: number;
  player?: PlayerWithTeam;
  isRequired: boolean;
  maxPlayers: number;
}

const DEFAULT_POSITIONS: PositionSlot[] = [
  { id: "front-row", position: "Front Row", isRequired: true, maxPlayers: 3 },
  { id: "second-row", position: "Second Row", isRequired: true, maxPlayers: 2 },
  { id: "back-row", position: "Back Row", isRequired: true, maxPlayers: 3 },
  { id: "half-backs", position: "Half Back", isRequired: true, maxPlayers: 2 },
  { id: "centres", position: "Centre", isRequired: true, maxPlayers: 2 },
  { id: "back-three", position: "Back Three", isRequired: true, maxPlayers: 3 },
  { id: "reserves", position: "Reserve", isRequired: false, maxPlayers: 8 },
];

export default function DragDropRoster({ selectedTeamId, onTeamSelect }: DragDropRosterProps) {
  const { toast } = useToast();
  const [draggedPlayer, setDraggedPlayer] = useState<PlayerWithTeam | null>(null);
  const [roster, setRoster] = useState<Map<string, PlayerWithTeam[]>>(new Map());
  const [availablePlayers, setAvailablePlayers] = useState<PlayerWithTeam[]>([]);
  const [searchQuery, setSearchQuery] = useState("");
  const [positionFilter, setPositionFilter] = useState("all");

  // Fetch teams
  const { data: teams = [] } = useQuery<Team[]>({
    queryKey: ["/api/teams"],
  });

  // Fetch all players
  const { data: allPlayers = [], isLoading: playersLoading } = useQuery<PlayerWithTeam[]>({
    queryKey: ["/api/players"],
  });

  // Initialize roster when team is selected
  useEffect(() => {
    if (selectedTeamId && allPlayers.length > 0) {
      const teamPlayers = allPlayers.filter(p => p.teamId === selectedTeamId);
      const newRoster = new Map<string, PlayerWithTeam[]>();
      
      // Initialize positions
      DEFAULT_POSITIONS.forEach(pos => {
        const positionPlayers = teamPlayers.filter(p => p.position === pos.position);
        newRoster.set(pos.id, positionPlayers.slice(0, pos.maxPlayers));
      });

      setRoster(newRoster);
      
      // Set available players (unassigned or from other teams)
      const assignedPlayerIds = new Set();
      newRoster.forEach(players => {
        players.forEach(p => assignedPlayerIds.add(p.id));
      });
      
      const available = allPlayers.filter(p => 
        !assignedPlayerIds.has(p.id) && (p.teamId !== selectedTeamId || !p.teamId)
      );
      setAvailablePlayers(available);
    }
  }, [selectedTeamId, allPlayers]);

  // Update player mutation
  const updatePlayerMutation = useMutation({
    mutationFn: async ({ playerId, updates }: { playerId: number; updates: Partial<Player> }) => {
      return await apiRequest("PATCH", `/api/players/${playerId}`, updates);
    },
    onSuccess: () => {
      queryClient.invalidateQueries({ queryKey: ["/api/players"] });
    },
    onError: (error: any) => {
      toast({
        title: "Error",
        description: error.message || "Failed to update player",
        variant: "destructive",
      });
    },
  });

  const handleDragStart = (player: PlayerWithTeam) => {
    setDraggedPlayer(player);
  };

  const handleDragOver = (e: React.DragEvent) => {
    e.preventDefault();
  };

  const handleDrop = (e: React.DragEvent, positionId: string) => {
    e.preventDefault();
    
    if (!draggedPlayer || !selectedTeamId) return;

    const position = DEFAULT_POSITIONS.find(p => p.id === positionId);
    if (!position) return;

    const currentPositionPlayers = roster.get(positionId) || [];
    
    // Check if position is full
    if (currentPositionPlayers.length >= position.maxPlayers) {
      toast({
        title: "Position Full",
        description: `${position.position} position is already full`,
        variant: "destructive",
      });
      setDraggedPlayer(null);
      return;
    }

    // Remove player from current position if already in roster
    const newRoster = new Map(roster);
    newRoster.forEach((players, posId) => {
      const filtered = players.filter(p => p.id !== draggedPlayer.id);
      newRoster.set(posId, filtered);
    });

    // Add player to new position
    const updatedPositionPlayers = [...currentPositionPlayers, draggedPlayer];
    newRoster.set(positionId, updatedPositionPlayers);
    setRoster(newRoster);

    // Remove from available players if adding to roster
    setAvailablePlayers(prev => prev.filter(p => p.id !== draggedPlayer.id));

    // Update player in database
    updatePlayerMutation.mutate({
      playerId: draggedPlayer.id,
      updates: {
        teamId: selectedTeamId,
        position: position.position,
      },
    });

    setDraggedPlayer(null);
  };

  const handleRemoveFromRoster = (player: PlayerWithTeam, positionId: string) => {
    const newRoster = new Map(roster);
    const currentPlayers = newRoster.get(positionId) || [];
    const filtered = currentPlayers.filter(p => p.id !== player.id);
    newRoster.set(positionId, filtered);
    setRoster(newRoster);

    // Add back to available players
    setAvailablePlayers(prev => [...prev, player]);

    // Update player in database to remove team assignment
    updatePlayerMutation.mutate({
      playerId: player.id,
      updates: {
        teamId: null,
        position: null,
      },
    });
  };

  const handleSaveRoster = async () => {
    if (!selectedTeamId) return;

    try {
      const promises: Promise<any>[] = [];
      
      roster.forEach((players, positionId) => {
        const position = DEFAULT_POSITIONS.find(p => p.id === positionId);
        if (!position) return;

        players.forEach(player => {
          promises.push(
            updatePlayerMutation.mutateAsync({
              playerId: player.id,
              updates: {
                teamId: selectedTeamId,
                position: position.position,
              },
            })
          );
        });
      });

      await Promise.all(promises);
      
      toast({
        title: "Roster Saved",
        description: "Team roster has been saved successfully",
      });
    } catch (error) {
      toast({
        title: "Save Failed",
        description: "Failed to save roster changes",
        variant: "destructive",
      });
    }
  };

  const filteredAvailablePlayers = availablePlayers.filter(player => {
    const matchesSearch = `${player.firstName} ${player.lastName}`.toLowerCase().includes(searchQuery.toLowerCase());
    const matchesPosition = positionFilter === "all" || player.position === positionFilter;
    return matchesSearch && matchesPosition;
  });

  const getTotalPlayersInRoster = () => {
    let total = 0;
    roster.forEach(players => {
      total += players.length;
    });
    return total;
  };

  const getPositionColor = (positionId: string) => {
    switch (positionId) {
      case "front-row": return "bg-red-100 border-red-300";
      case "second-row": return "bg-blue-100 border-blue-300";
      case "back-row": return "bg-green-100 border-green-300";
      case "half-backs": return "bg-purple-100 border-purple-300";
      case "centres": return "bg-orange-100 border-orange-300";
      case "back-three": return "bg-cyan-100 border-cyan-300";
      case "reserves": return "bg-gray-100 border-gray-300";
      default: return "bg-gray-100 border-gray-300";
    }
  };

  if (!selectedTeamId) {
    return (
      <Card>
        <CardHeader>
          <CardTitle>Select a Team</CardTitle>
          <CardDescription>Choose a team to manage its roster</CardDescription>
        </CardHeader>
        <CardContent>
          <Select onValueChange={(value) => onTeamSelect?.(parseInt(value))}>
            <SelectTrigger className="w-full">
              <SelectValue placeholder="Select team..." />
            </SelectTrigger>
            <SelectContent>
              {teams.map(team => (
                <SelectItem key={team.id} value={team.id.toString()}>
                  {team.name}
                </SelectItem>
              ))}
            </SelectContent>
          </Select>
        </CardContent>
      </Card>
    );
  }

  const selectedTeam = teams.find(t => t.id === selectedTeamId);

  return (
    <div className="space-y-6">
      {/* Header */}
      <div className="flex items-center justify-between">
        <div>
          <h2 className="text-2xl font-bold">Team Roster Management</h2>
          <p className="text-gray-600">
            {selectedTeam?.name} • {getTotalPlayersInRoster()} players assigned
          </p>
        </div>
        <div className="flex items-center space-x-3">
          <Button onClick={handleSaveRoster} disabled={updatePlayerMutation.isPending}>
            <Save className="h-4 w-4 mr-2" />
            Save Roster
          </Button>
          <Select onValueChange={(value) => onTeamSelect?.(parseInt(value))}>
            <SelectTrigger className="w-48">
              <SelectValue placeholder={selectedTeam?.name || "Select team..."} />
            </SelectTrigger>
            <SelectContent>
              {teams.map(team => (
                <SelectItem key={team.id} value={team.id.toString()}>
                  {team.name}
                </SelectItem>
              ))}
            </SelectContent>
          </Select>
        </div>
      </div>

      <div className="grid grid-cols-1 lg:grid-cols-3 gap-6">
        {/* Available Players */}
        <Card className="lg:col-span-1">
          <CardHeader>
            <CardTitle className="flex items-center space-x-2">
              <Users className="h-5 w-5" />
              <span>Available Players</span>
              <Badge variant="secondary">{filteredAvailablePlayers.length}</Badge>
            </CardTitle>
            <CardDescription>Drag players to assign them to positions</CardDescription>
          </CardHeader>
          <CardContent className="space-y-4">
            {/* Search and Filter */}
            <div className="space-y-2">
              <div className="relative">
                <Search className="absolute left-3 top-1/2 transform -translate-y-1/2 h-4 w-4 text-gray-400" />
                <input
                  type="text"
                  placeholder="Search players..."
                  value={searchQuery}
                  onChange={(e) => setSearchQuery(e.target.value)}
                  className="w-full pl-10 pr-4 py-2 border rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"
                />
              </div>
              <Select value={positionFilter} onValueChange={setPositionFilter}>
                <SelectTrigger>
                  <Filter className="h-4 w-4 mr-2" />
                  <SelectValue />
                </SelectTrigger>
                <SelectContent>
                  <SelectItem value="all">All Positions</SelectItem>
                  <SelectItem value="Front Row">Front Row</SelectItem>
                  <SelectItem value="Second Row">Second Row</SelectItem>
                  <SelectItem value="Back Row">Back Row</SelectItem>
                  <SelectItem value="Half Back">Half Backs</SelectItem>
                  <SelectItem value="Centre">Centres</SelectItem>
                  <SelectItem value="Back Three">Back Three</SelectItem>
                  <SelectItem value="Reserve">Reserves</SelectItem>
                </SelectContent>
              </Select>
            </div>

            {/* Player List */}
            <div className="space-y-2 max-h-96 overflow-y-auto">
              {playersLoading ? (
                <div className="text-center py-4">
                  <RefreshCw className="h-6 w-6 animate-spin mx-auto mb-2" />
                  <p className="text-sm text-gray-500">Loading players...</p>
                </div>
              ) : filteredAvailablePlayers.length === 0 ? (
                <div className="text-center py-8 text-gray-500">
                  <UserPlus className="h-8 w-8 mx-auto mb-2" />
                  <p>No available players</p>
                </div>
              ) : (
                filteredAvailablePlayers.map(player => (
                  <div
                    key={player.id}
                    draggable
                    onDragStart={() => handleDragStart(player)}
                    className="flex items-center space-x-3 p-3 border rounded-lg cursor-grab hover:bg-gray-50 active:cursor-grabbing transition-colors"
                  >
                    <Avatar className="h-10 w-10">
                      <AvatarImage src={player.profileImageUrl || ""} />
                      <AvatarFallback>
                        {player.firstName[0]}{player.lastName[0]}
                      </AvatarFallback>
                    </Avatar>
                    <div className="flex-1 min-w-0">
                      <p className="font-medium truncate">
                        {player.firstName} {player.lastName}
                      </p>
                      <p className="text-sm text-gray-500">
                        {player.position || "No position"} • #{player.jerseyNumber || "N/A"}
                      </p>
                    </div>
                  </div>
                ))
              )}
            </div>
          </CardContent>
        </Card>

        {/* Formation */}
        <Card className="lg:col-span-2">
          <CardHeader>
            <CardTitle className="flex items-center space-x-2">
              <Trophy className="h-5 w-5" />
              <span>Team Formation</span>
            </CardTitle>
            <CardDescription>Drop players into their positions</CardDescription>
          </CardHeader>
          <CardContent>
            <div className="space-y-4">
              {DEFAULT_POSITIONS.map(position => {
                const positionPlayers = roster.get(position.id) || [];
                
                return (
                  <div
                    key={position.id}
                    className={`min-h-20 p-4 border-2 border-dashed rounded-lg transition-colors ${getPositionColor(position.id)} ${
                      draggedPlayer ? "border-blue-500 bg-blue-50" : ""
                    }`}
                    onDragOver={handleDragOver}
                    onDrop={(e) => handleDrop(e, position.id)}
                  >
                    <div className="flex items-center justify-between mb-3">
                      <div className="flex items-center space-x-2">
                        <h3 className="font-semibold">{position.position}</h3>
                        <Badge variant={position.isRequired ? "default" : "secondary"}>
                          {positionPlayers.length}/{position.maxPlayers}
                        </Badge>
                        {position.isRequired && (
                          <Badge variant="destructive" className="text-xs">Required</Badge>
                        )}
                      </div>
                    </div>
                    
                    <div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-2">
                      {positionPlayers.map(player => (
                        <div
                          key={player.id}
                          className="flex items-center space-x-2 p-2 bg-white rounded border group hover:shadow-sm transition-shadow"
                        >
                          <Avatar className="h-8 w-8">
                            <AvatarImage src={player.profileImageUrl || ""} />
                            <AvatarFallback className="text-xs">
                              {player.firstName[0]}{player.lastName[0]}
                            </AvatarFallback>
                          </Avatar>
                          <div className="flex-1 min-w-0">
                            <p className="text-sm font-medium truncate">
                              {player.firstName} {player.lastName}
                            </p>
                            <p className="text-xs text-gray-500">
                              #{player.jerseyNumber || "N/A"}
                            </p>
                          </div>
                          <Button
                            size="sm"
                            variant="ghost"
                            onClick={() => handleRemoveFromRoster(player, position.id)}
                            className="opacity-0 group-hover:opacity-100 transition-opacity h-6 w-6 p-0"
                          >
                            ×
                          </Button>
                        </div>
                      ))}
                      
                      {/* Empty slots */}
                      {Array.from({ length: position.maxPlayers - positionPlayers.length }, (_, i) => (
                        <div
                          key={i}
                          className="flex items-center justify-center p-2 border-2 border-dashed border-gray-300 rounded text-gray-400 text-sm min-h-12"
                        >
                          Drop player here
                        </div>
                      ))}
                    </div>
                  </div>
                );
              })}
            </div>
          </CardContent>
        </Card>
      </div>
    </div>
  );
}