import { useState, useCallback } from "react";
import { useQuery, useMutation, useQueryClient } from "@tanstack/react-query";
import { DndContext, closestCenter, KeyboardSensor, PointerSensor, useSensor, useSensors, DragOverlay, DragStartEvent, DragEndEvent } from "@dnd-kit/core";
import { arrayMove, SortableContext, sortableKeyboardCoordinates, verticalListSortingStrategy, rectSortingStrategy } from "@dnd-kit/sortable";
import { useSortable } from "@dnd-kit/sortable";
import { CSS } from "@dnd-kit/utilities";
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card";
import { Button } from "@/components/ui/button";
import { Badge } from "@/components/ui/badge";
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select";
import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs";
import { Dialog, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogTitle, DialogTrigger } from "@/components/ui/dialog";
import { Input } from "@/components/ui/input";
import { Label } from "@/components/ui/label";
import { Textarea } from "@/components/ui/textarea";
import { useToast } from "@/hooks/use-toast";
import { apiRequest } from "@/lib/queryClient";
import { Users, Trophy, Save, RotateCcw, Copy, Settings, Plus, Minus, ArrowUpDown, Download, Camera } from "lucide-react";
import jsPDF from "jspdf";
import html2canvas from "html2canvas";
import { type Player, type Team, type Coach } from "@shared/schema";

interface Formation {
  id: string;
  name: string;
  positions: Array<{
    id: string;
    name: string;
    x: number;
    y: number;
    required: boolean;
  }>;
}

interface PlayerAssignment {
  playerId: number;
  positionId: string;
  isStarter: boolean;
  orderIndex: number;
}

interface RosterState {
  teamId: number;
  formation: Formation;
  assignments: PlayerAssignment[];
  substitutes: number[];
}

// Rugby formations
const RUGBY_FORMATIONS: Formation[] = [
  {
    id: "15s-standard",
    name: "15s Standard",
    positions: [
      { id: "1", name: "Loosehead Prop", x: 50, y: 85, required: true },
      { id: "2", name: "Hooker", x: 50, y: 75, required: true },
      { id: "3", name: "Tighthead Prop", x: 50, y: 85, required: true },
      { id: "4", name: "Lock", x: 40, y: 70, required: true },
      { id: "5", name: "Lock", x: 60, y: 70, required: true },
      { id: "6", name: "Blindside Flanker", x: 35, y: 65, required: true },
      { id: "7", name: "Openside Flanker", x: 65, y: 65, required: true },
      { id: "8", name: "Number 8", x: 50, y: 60, required: true },
      { id: "9", name: "Scrum-half", x: 50, y: 50, required: true },
      { id: "10", name: "Fly-half", x: 50, y: 40, required: true },
      { id: "11", name: "Left Wing", x: 20, y: 30, required: true },
      { id: "12", name: "Inside Centre", x: 40, y: 30, required: true },
      { id: "13", name: "Outside Centre", x: 60, y: 30, required: true },
      { id: "14", name: "Right Wing", x: 80, y: 30, required: true },
      { id: "15", name: "Fullback", x: 50, y: 15, required: true },
    ]
  },
  {
    id: "7s-standard",
    name: "7s Standard",
    positions: [
      { id: "1", name: "Prop", x: 40, y: 80, required: true },
      { id: "2", name: "Hooker", x: 50, y: 75, required: true },
      { id: "3", name: "Prop", x: 60, y: 80, required: true },
      { id: "4", name: "Scrum-half", x: 50, y: 60, required: true },
      { id: "5", name: "Fly-half", x: 50, y: 45, required: true },
      { id: "6", name: "Centre", x: 50, y: 30, required: true },
      { id: "7", name: "Fullback", x: 50, y: 15, required: true },
    ]
  }
];

// Draggable Player Card Component
interface DraggablePlayerProps {
  player: Player;
  isDragging?: boolean;
  isAssigned?: boolean;
  position?: string;
}

function DraggablePlayer({ player, isDragging, isAssigned, position }: DraggablePlayerProps) {
  const {
    attributes,
    listeners,
    setNodeRef,
    transform,
    transition,
  } = useSortable({ id: player.id });

  const style = {
    transform: CSS.Transform.toString(transform),
    transition,
    opacity: isDragging ? 0.5 : 1,
  };

  return (
    <div
      ref={setNodeRef}
      style={style}
      {...attributes}
      {...listeners}
      className={`p-3 bg-white border rounded-lg shadow-sm cursor-grab active:cursor-grabbing transition-all hover:shadow-md ${
        isAssigned ? 'border-blue-500 bg-blue-50' : 'border-gray-200'
      }`}
    >
      <div className="flex items-center justify-between">
        <div className="flex items-center space-x-2">
          <div className="w-8 h-8 bg-gray-200 rounded-full flex items-center justify-center">
            <span className="text-xs font-semibold">{player.jerseyNumber || '?'}</span>
          </div>
          <div>
            <p className="font-medium text-sm">{player.firstName} {player.lastName}</p>
            <p className="text-xs text-gray-600">{player.position}</p>
          </div>
        </div>
        {position && (
          <Badge variant="secondary" className="text-xs">
            {position}
          </Badge>
        )}
      </div>
    </div>
  );
}

// Field Position Component
interface FieldPositionProps {
  position: Formation['positions'][0];
  assignedPlayer?: Player;
  onDrop: (playerId: number, positionId: string) => void;
}

function FieldPosition({ position, assignedPlayer, onDrop }: FieldPositionProps) {
  const {
    setNodeRef,
    isOver,
  } = useSortable({ 
    id: `position-${position.id}`,
    data: {
      type: 'position',
      positionId: position.id,
    }
  });

  return (
    <div
      ref={setNodeRef}
      className={`absolute w-16 h-16 rounded-full border-2 border-dashed flex items-center justify-center text-xs font-medium transition-all ${
        isOver ? 'border-blue-500 bg-blue-100' : 'border-gray-400 bg-white'
      } ${assignedPlayer ? 'bg-green-100 border-green-500' : ''}`}
      style={{
        left: `${position.x}%`,
        top: `${position.y}%`,
        transform: 'translate(-50%, -50%)',
      }}
    >
      {assignedPlayer ? (
        <div className="text-center">
          <div className="text-xs font-bold">{assignedPlayer.jerseyNumber}</div>
          <div className="text-xs">{assignedPlayer.lastName}</div>
        </div>
      ) : (
        <div className="text-center">
          <div className="text-xs">{position.id}</div>
          <div className="text-xs opacity-60">{position.name.split(' ')[0]}</div>
        </div>
      )}
    </div>
  );
}



export default function RosterManagement() {
  const [selectedTeam, setSelectedTeam] = useState<number | null>(null);
  const [selectedFormation, setSelectedFormation] = useState<Formation>(RUGBY_FORMATIONS[0]);
  const [activeId, setActiveId] = useState<string | null>(null);
  const [rosterState, setRosterState] = useState<RosterState>({
    teamId: 0,
    formation: RUGBY_FORMATIONS[0],
    assignments: [],
    substitutes: [],
  });
  const [showSaveDialog, setShowSaveDialog] = useState(false);
  const [rosterName, setRosterName] = useState("");
  const [rosterNotes, setRosterNotes] = useState("");

  const { toast } = useToast();
  const queryClient = useQueryClient();

  const sensors = useSensors(
    useSensor(PointerSensor),
    useSensor(KeyboardSensor, {
      coordinateGetter: sortableKeyboardCoordinates,
    })
  );

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

  const { data: players = [] } = useQuery<Player[]>({
    queryKey: ["/api/players"],
  });

  const teamPlayers = players.filter(player => 
    selectedTeam ? player.teamId === selectedTeam : false
  );

  const availablePlayers = teamPlayers.filter(player => 
    !rosterState.assignments.some(assignment => assignment.playerId === player.id) &&
    !rosterState.substitutes.includes(player.id)
  );

  const assignedPlayers = rosterState.assignments.map(assignment => ({
    ...assignment,
    player: players.find(p => p.id === assignment.playerId),
  }));

  const substitutePlayers = rosterState.substitutes.map(playerId => 
    players.find(p => p.id === playerId)
  ).filter(Boolean) as Player[];

  // Export functions
  const exportToPDF = async () => {
    try {
      const element = document.getElementById('roster-export-content');
      if (!element) {
        toast({
          title: "Export Error",
          description: "Could not find roster content to export",
          variant: "destructive",
        });
        return;
      }

      const canvas = await html2canvas(element, {
        scale: 2,
        useCORS: true,
        allowTaint: true,
        backgroundColor: '#ffffff',
      });

      const imgData = canvas.toDataURL('image/png');
      const pdf = new jsPDF('l', 'mm', 'a4'); // landscape orientation
      
      const imgWidth = 297; // A4 landscape width
      const pageHeight = 210; // A4 landscape height
      const imgHeight = (canvas.height * imgWidth) / canvas.width;
      let heightLeft = imgHeight;
      let position = 0;

      pdf.addImage(imgData, 'PNG', 0, position, imgWidth, imgHeight);
      heightLeft -= pageHeight;

      while (heightLeft >= 0) {
        position = heightLeft - imgHeight;
        pdf.addPage();
        pdf.addImage(imgData, 'PNG', 0, position, imgWidth, imgHeight);
        heightLeft -= pageHeight;
      }

      const selectedTeamData = teams.find(t => t.id === selectedTeam);
      const teamName = selectedTeamData?.name || 'Team';
      const fileName = `${teamName}-roster-${new Date().toISOString().split('T')[0]}.pdf`;
      
      pdf.save(fileName);
      
      toast({
        title: "PDF Export Successful",
        description: `Roster exported as ${fileName}`,
      });
    } catch (error) {
      toast({
        title: "Export Failed",
        description: "Failed to generate PDF export",
        variant: "destructive",
      });
    }
  };

  const exportToJPG = async () => {
    try {
      const element = document.getElementById('roster-export-content');
      if (!element) {
        toast({
          title: "Export Error",
          description: "Could not find roster content to export",
          variant: "destructive",
        });
        return;
      }

      const canvas = await html2canvas(element, {
        scale: 2,
        useCORS: true,
        allowTaint: true,
        backgroundColor: '#ffffff',
      });

      const link = document.createElement('a');
      const selectedTeamData = teams.find(t => t.id === selectedTeam);
      const teamName = selectedTeamData?.name || 'Team';
      const fileName = `${teamName}-roster-${new Date().toISOString().split('T')[0]}.jpg`;
      
      link.download = fileName;
      link.href = canvas.toDataURL('image/jpeg', 0.9);
      link.click();
      
      toast({
        title: "JPG Export Successful",
        description: `Roster exported as ${fileName}`,
      });
    } catch (error) {
      toast({
        title: "Export Failed",
        description: "Failed to generate JPG export",
        variant: "destructive",
      });
    }
  };

  // Save roster mutation
  const saveRosterMutation = useMutation({
    mutationFn: async (rosterData: any) => {
      const res = await apiRequest("POST", "/api/rosters", rosterData);
      return res.json();
    },
    onSuccess: () => {
      toast({
        title: "Roster saved",
        description: "The team roster has been saved successfully.",
      });
      setShowSaveDialog(false);
      queryClient.invalidateQueries({ queryKey: ["/api/rosters"] });
    },
    onError: (error: Error) => {
      toast({
        title: "Failed to save roster",
        description: error.message,
        variant: "destructive",
      });
    },
  });

  const handleDragStart = useCallback((event: DragStartEvent) => {
    setActiveId(event.active.id as string);
  }, []);

  const handleDragEnd = useCallback((event: DragEndEvent) => {
    const { active, over } = event;
    setActiveId(null);

    if (!over) return;

    const activeType = active.data.current?.type;
    const overType = over.data.current?.type;
    const overPositionId = over.data.current?.positionId;

    // Player dropped on position
    if (activeType === 'player' && overType === 'position') {
      const playerId = parseInt(active.id as string);
      const positionId = overPositionId;

      // Remove player from current assignment if exists
      setRosterState(prev => ({
        ...prev,
        assignments: prev.assignments.filter(a => a.playerId !== playerId),
        substitutes: prev.substitutes.filter(id => id !== playerId),
      }));

      // Add new assignment
      setRosterState(prev => ({
        ...prev,
        assignments: [
          ...prev.assignments.filter(a => a.positionId !== positionId),
          {
            playerId,
            positionId,
            isStarter: true,
            orderIndex: 0,
          }
        ],
      }));
    }

    // Player dropped on substitutes
    if (activeType === 'player' && over.id === 'substitutes') {
      const playerId = parseInt(active.id as string);
      
      setRosterState(prev => ({
        ...prev,
        assignments: prev.assignments.filter(a => a.playerId !== playerId),
        substitutes: [...prev.substitutes.filter(id => id !== playerId), playerId],
      }));
    }

    // Player dropped on available players (remove from roster)
    if (activeType === 'player' && over.id === 'available') {
      const playerId = parseInt(active.id as string);
      
      setRosterState(prev => ({
        ...prev,
        assignments: prev.assignments.filter(a => a.playerId !== playerId),
        substitutes: prev.substitutes.filter(id => id !== playerId),
      }));
    }
  }, []);

  const handleFormationChange = (formationId: string) => {
    const formation = RUGBY_FORMATIONS.find(f => f.id === formationId);
    if (formation) {
      setSelectedFormation(formation);
      setRosterState(prev => ({
        ...prev,
        formation,
        assignments: [], // Clear assignments when changing formation
      }));
    }
  };

  const handleSaveRoster = () => {
    if (!selectedTeam || !rosterName.trim()) return;

    const rosterData = {
      name: rosterName,
      teamId: selectedTeam,
      formation: selectedFormation.id,
      assignments: rosterState.assignments,
      substitutes: rosterState.substitutes,
      notes: rosterNotes,
    };

    saveRosterMutation.mutate(rosterData);
  };

  const clearRoster = () => {
    setRosterState(prev => ({
      ...prev,
      assignments: [],
      substitutes: [],
    }));
  };

  const autoFillRoster = () => {
    if (!selectedFormation || availablePlayers.length === 0) return;

    const newAssignments: PlayerAssignment[] = [];
    const availablePlayersCopy = [...availablePlayers];

    selectedFormation.positions.forEach((position, index) => {
      if (availablePlayersCopy.length > 0) {
        // Try to match by preferred position first
        let playerIndex = availablePlayersCopy.findIndex(p => 
          p.position?.toLowerCase().includes(position.name.toLowerCase()) ||
          position.name.toLowerCase().includes(p.position?.toLowerCase() || '')
        );

        // If no match found, take the first available player
        if (playerIndex === -1) {
          playerIndex = 0;
        }

        const player = availablePlayersCopy[playerIndex];
        newAssignments.push({
          playerId: player.id,
          positionId: position.id,
          isStarter: true,
          orderIndex: index,
        });

        availablePlayersCopy.splice(playerIndex, 1);
      }
    });

    setRosterState(prev => ({
      ...prev,
      assignments: newAssignments,
      substitutes: availablePlayersCopy.map(p => p.id),
    }));
  };

  const draggedPlayer = activeId ? players.find(p => p.id === parseInt(activeId)) || availablePlayers.find(p => p.id === parseInt(activeId)) || substitutePlayers.find(p => p.id === parseInt(activeId)) : null;

  return (
    <div className="container mx-auto p-6 space-y-6" id="roster-export-content">
      <div className="flex justify-between items-center">
        <div>
          <h1 className="text-3xl font-bold">Team Roster Management</h1>
          <p className="text-gray-600">Drag and drop players to create your team lineup</p>
        </div>
        
        <div className="flex gap-2">
          <Button variant="outline" onClick={exportToJPG} disabled={!selectedTeam}>
            <Camera className="h-4 w-4 mr-2" />
            Export JPG
          </Button>
          <Button variant="outline" onClick={exportToPDF} disabled={!selectedTeam}>
            <Download className="h-4 w-4 mr-2" />
            Export PDF
          </Button>
          <Button variant="outline" onClick={clearRoster}>
            <RotateCcw className="h-4 w-4 mr-2" />
            Clear
          </Button>
          <Button variant="outline" onClick={autoFillRoster}>
            <Settings className="h-4 w-4 mr-2" />
            Auto Fill
          </Button>
          <Button onClick={() => setShowSaveDialog(true)} disabled={!selectedTeam}>
            <Save className="h-4 w-4 mr-2" />
            Save Roster
          </Button>
        </div>
      </div>

      {/* Team and Formation Selection */}
      <Card>
        <CardHeader>
          <CardTitle>Setup</CardTitle>
          <CardDescription>Select team and formation to begin roster management</CardDescription>
        </CardHeader>
        <CardContent>
          <div className="grid grid-cols-1 md:grid-cols-2 gap-4">
            <div>
              <Label htmlFor="team">Team</Label>
              <Select value={selectedTeam?.toString() || ""} onValueChange={(value) => setSelectedTeam(parseInt(value))}>
                <SelectTrigger>
                  <SelectValue placeholder="Select a team" />
                </SelectTrigger>
                <SelectContent>
                  {teams.map((team) => (
                    <SelectItem key={team.id} value={team.id.toString()}>
                      {team.name}
                    </SelectItem>
                  ))}
                </SelectContent>
              </Select>
            </div>

            <div>
              <Label htmlFor="formation">Formation</Label>
              <Select value={selectedFormation.id} onValueChange={handleFormationChange}>
                <SelectTrigger>
                  <SelectValue />
                </SelectTrigger>
                <SelectContent>
                  {RUGBY_FORMATIONS.map((formation) => (
                    <SelectItem key={formation.id} value={formation.id}>
                      {formation.name}
                    </SelectItem>
                  ))}
                </SelectContent>
              </Select>
            </div>
          </div>
        </CardContent>
      </Card>

      {selectedTeam && (
        <DndContext
          sensors={sensors}
          collisionDetection={closestCenter}
          onDragStart={handleDragStart}
          onDragEnd={handleDragEnd}
        >
          <div className="grid grid-cols-1 lg:grid-cols-3 gap-6">
            {/* Available Players */}
            <Card>
              <CardHeader>
                <CardTitle className="flex items-center gap-2">
                  <Users className="h-5 w-5" />
                  Available Players ({availablePlayers.length})
                </CardTitle>
              </CardHeader>
              <CardContent>
                <div 
                  className="space-y-2 max-h-96 overflow-y-auto min-h-[200px] p-2 border-2 border-dashed border-gray-200 rounded-lg"
                  id="available-players-zone"
                >
                  {availablePlayers.length > 0 ? (
                    availablePlayers.map((player) => (
                      <DraggablePlayer key={player.id} player={player} />
                    ))
                  ) : (
                    <div className="text-center text-gray-500 py-8">
                      All players have been assigned
                    </div>
                  )}
                </div>
              </CardContent>
            </Card>

            {/* Field Formation */}
            <Card className="lg:col-span-2">
              <CardHeader>
                <CardTitle className="flex items-center gap-2">
                  <Trophy className="h-5 w-5" />
                  {selectedFormation.name} Formation
                </CardTitle>
              </CardHeader>
              <CardContent>
                <div className="relative w-full h-96 bg-green-100 rounded-lg border-2 border-green-200">
                  {/* Field lines */}
                  <div className="absolute inset-0 opacity-30">
                    <div className="w-full h-px bg-white absolute top-1/4"></div>
                    <div className="w-full h-px bg-white absolute top-2/4"></div>
                    <div className="w-full h-px bg-white absolute top-3/4"></div>
                    <div className="w-px h-full bg-white absolute left-1/4"></div>
                    <div className="w-px h-full bg-white absolute left-2/4"></div>
                    <div className="w-px h-full bg-white absolute left-3/4"></div>
                  </div>

                  {/* Positions */}
                  <SortableContext 
                    items={selectedFormation.positions.map(p => `position-${p.id}`)}
                    strategy={rectSortingStrategy}
                  >
                    {selectedFormation.positions.map((position) => {
                      const assignment = rosterState.assignments.find(a => a.positionId === position.id);
                      const assignedPlayer = assignment ? players.find(p => p.id === assignment.playerId) : undefined;
                      
                      return (
                        <FieldPosition
                          key={position.id}
                          position={position}
                          assignedPlayer={assignedPlayer}
                          onDrop={(playerId, positionId) => {
                            // Handle drop logic here if needed
                          }}
                        />
                      );
                    })}
                  </SortableContext>
                </div>
              </CardContent>
            </Card>
          </div>

          {/* Substitutes */}
          <Card>
            <CardHeader>
              <CardTitle className="flex items-center gap-2">
                <ArrowUpDown className="h-5 w-5" />
                Substitutes ({substitutePlayers.length})
              </CardTitle>
            </CardHeader>
            <CardContent>
              <SortableContext 
                items={substitutePlayers.map(p => p.id)} 
                strategy={verticalListSortingStrategy}
                id="substitutes"
              >
                <div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-2">
                  {substitutePlayers.map((player) => (
                    <DraggablePlayer key={player.id} player={player} isAssigned={true} />
                  ))}
                  {substitutePlayers.length === 0 && (
                    <div className="col-span-full text-center text-gray-500 py-8">
                      Drag players here to add them as substitutes
                    </div>
                  )}
                </div>
              </SortableContext>
            </CardContent>
          </Card>

          <DragOverlay>
            {draggedPlayer ? (
              <DraggablePlayer player={draggedPlayer} isDragging />
            ) : null}
          </DragOverlay>
        </DndContext>
      )}

      {/* Save Roster Dialog */}
      <Dialog open={showSaveDialog} onOpenChange={setShowSaveDialog}>
        <DialogContent>
          <DialogHeader>
            <DialogTitle>Save Roster</DialogTitle>
            <DialogDescription>
              Save this roster configuration for future use.
            </DialogDescription>
          </DialogHeader>
          
          <div className="space-y-4">
            <div>
              <Label htmlFor="rosterName">Roster Name</Label>
              <Input
                id="rosterName"
                value={rosterName}
                onChange={(e) => setRosterName(e.target.value)}
                placeholder="e.g., Starting XV vs Eagles"
              />
            </div>
            
            <div>
              <Label htmlFor="rosterNotes">Notes (Optional)</Label>
              <Textarea
                id="rosterNotes"
                value={rosterNotes}
                onChange={(e) => setRosterNotes(e.target.value)}
                placeholder="Add any notes about this roster configuration..."
              />
            </div>
          </div>

          <DialogFooter>
            <Button variant="outline" onClick={() => setShowSaveDialog(false)}>
              Cancel
            </Button>
            <Button 
              onClick={handleSaveRoster} 
              disabled={!rosterName.trim() || saveRosterMutation.isPending}
            >
              {saveRosterMutation.isPending ? "Saving..." : "Save Roster"}
            </Button>
          </DialogFooter>
        </DialogContent>
      </Dialog>
    </div>
  );
}