import { useState, useEffect, useCallback } from 'react';
import { useParams, useNavigate } from 'react-router-dom';
import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query';
import { ArrowLeft, Plus, Users, Swords, ChevronRight } from 'lucide-react';
import { api } from '@/shared/lib/api';
import { useAuthStore } from '@/features/auth';
import { BattleCanvas } from './battle-canvas';
import { BattleSessionList } from './battle-session-list';
import { useBattleSocket } from '../hooks/use-battle-socket';
import type { BattleSession, BattleToken, Character, Combatant } from '@/shared/types';
import { cn } from '@/shared/lib/utils';

export function BattlePage() {
  const { id: campaignId } = useParams<{ id: string }>();
  const navigate = useNavigate();
  const queryClient = useQueryClient();
  const { user } = useAuthStore();

  const [selectedSessionId, setSelectedSessionId] = useState<string | null>(null);
  const [selectedTokenId, setSelectedTokenId] = useState<string | null>(null);
  const [showAddPanel, setShowAddPanel] = useState(false);

  // Fetch campaign to check GM status
  const { data: campaign } = useQuery({
    queryKey: ['campaign', campaignId],
    queryFn: () => api.getCampaign(campaignId!),
    enabled: !!campaignId,
  });

  const isGM = campaign?.gmId === user?.id;

  // Fetch battle sessions
  const { data: sessions = [] } = useQuery({
    queryKey: ['battleSessions', campaignId],
    queryFn: () => api.getBattleSessions(campaignId!),
    enabled: !!campaignId,
  });

  // Fetch battle maps
  const { data: maps = [] } = useQuery({
    queryKey: ['battleMaps', campaignId],
    queryFn: () => api.getBattleMaps(campaignId!),
    enabled: !!campaignId,
  });

  // Fetch characters for adding PCs
  const { data: characters = [] } = useQuery({
    queryKey: ['characters', campaignId],
    queryFn: () => api.getCharacters(campaignId!),
    enabled: !!campaignId && isGM,
  });

  // Fetch combatants for adding NPCs
  const { data: combatants = [] } = useQuery({
    queryKey: ['combatants', campaignId],
    queryFn: () => api.getCombatants(campaignId!),
    enabled: !!campaignId && isGM,
  });

  // Get current session
  const currentSession = sessions.find((s: BattleSession) => s.id === selectedSessionId);

  // WebSocket connection
  const {
    isConnected,
    moveToken,
    updateTokenHp,
    setInitiative,
    advanceRound,
  } = useBattleSocket({
    sessionId: selectedSessionId || '',
    onTokenMoved: useCallback((data: { tokenId: string; positionX: number; positionY: number }) => {
      queryClient.setQueryData(['battleSessions', campaignId], (old: BattleSession[]) =>
        old?.map(session =>
          session.id === selectedSessionId
            ? {
                ...session,
                tokens: session.tokens.map(token =>
                  token.id === data.tokenId
                    ? { ...token, positionX: data.positionX, positionY: data.positionY }
                    : token
                ),
              }
            : session
        )
      );
    }, [queryClient, campaignId, selectedSessionId]),
    onTokenHpChanged: useCallback((data: { tokenId: string; hpCurrent: number; hpMax: number }) => {
      queryClient.setQueryData(['battleSessions', campaignId], (old: BattleSession[]) =>
        old?.map(session =>
          session.id === selectedSessionId
            ? {
                ...session,
                tokens: session.tokens.map(token =>
                  token.id === data.tokenId
                    ? { ...token, hpCurrent: data.hpCurrent, hpMax: data.hpMax }
                    : token
                ),
              }
            : session
        )
      );
    }, [queryClient, campaignId, selectedSessionId]),
    onInitiativeSet: useCallback((data: { tokenId: string; initiative: number }) => {
      queryClient.setQueryData(['battleSessions', campaignId], (old: BattleSession[]) =>
        old?.map(session =>
          session.id === selectedSessionId
            ? {
                ...session,
                tokens: session.tokens.map(token =>
                  token.id === data.tokenId
                    ? { ...token, initiative: data.initiative }
                    : token
                ),
              }
            : session
        )
      );
    }, [queryClient, campaignId, selectedSessionId]),
    onRoundAdvanced: useCallback((data: { roundNumber: number }) => {
      queryClient.setQueryData(['battleSessions', campaignId], (old: BattleSession[]) =>
        old?.map(session =>
          session.id === selectedSessionId
            ? { ...session, roundNumber: data.roundNumber }
            : session
        )
      );
    }, [queryClient, campaignId, selectedSessionId]),
    onTokenAdded: useCallback(() => {
      queryClient.invalidateQueries({ queryKey: ['battleSessions', campaignId] });
    }, [queryClient, campaignId]),
    onTokenRemoved: useCallback(() => {
      queryClient.invalidateQueries({ queryKey: ['battleSessions', campaignId] });
    }, [queryClient, campaignId]),
  });

  // Mutations
  const createSessionMutation = useMutation({
    mutationFn: (data: { name: string; mapId?: string }) =>
      api.createBattleSession(campaignId!, data),
    onSuccess: (newSession) => {
      queryClient.invalidateQueries({ queryKey: ['battleSessions', campaignId] });
      setSelectedSessionId(newSession.id);
    },
  });

  const updateSessionMutation = useMutation({
    mutationFn: ({ sessionId, data }: { sessionId: string; data: any }) =>
      api.updateBattleSession(campaignId!, sessionId, data),
    onSuccess: () => {
      queryClient.invalidateQueries({ queryKey: ['battleSessions', campaignId] });
    },
  });

  const deleteSessionMutation = useMutation({
    mutationFn: (sessionId: string) =>
      api.deleteBattleSession(campaignId!, sessionId),
    onSuccess: () => {
      queryClient.invalidateQueries({ queryKey: ['battleSessions', campaignId] });
      setSelectedSessionId(null);
    },
  });

  const addTokenMutation = useMutation({
    mutationFn: (data: any) =>
      api.addBattleToken(campaignId!, selectedSessionId!, data),
    onSuccess: () => {
      queryClient.invalidateQueries({ queryKey: ['battleSessions', campaignId] });
    },
  });

  const removeTokenMutation = useMutation({
    mutationFn: (tokenId: string) =>
      api.removeBattleToken(campaignId!, selectedSessionId!, tokenId),
    onSuccess: () => {
      queryClient.invalidateQueries({ queryKey: ['battleSessions', campaignId] });
      setSelectedTokenId(null);
    },
  });

  // Auto-select first active session or first session
  useEffect(() => {
    if (sessions.length > 0 && !selectedSessionId) {
      const activeSession = sessions.find((s: BattleSession) => s.isActive);
      setSelectedSessionId(activeSession?.id || sessions[0].id);
    }
  }, [sessions, selectedSessionId]);

  // Handle token move
  const handleMoveToken = useCallback(async (tokenId: string, positionX: number, positionY: number) => {
    try {
      await moveToken(tokenId, positionX, positionY);
    } catch (error) {
      console.error('Failed to move token:', error);
    }
  }, [moveToken]);

  // Add PC token
  const handleAddPC = useCallback((character: Character) => {
    addTokenMutation.mutate({
      characterId: character.id,
      name: character.name,
      positionX: 0,
      positionY: 0,
      hpCurrent: character.hpCurrent,
      hpMax: character.hpMax,
      size: 1,
    });
    setShowAddPanel(false);
  }, [addTokenMutation]);

  // Add NPC token
  const handleAddNPC = useCallback((combatant: Combatant) => {
    addTokenMutation.mutate({
      combatantId: combatant.id,
      name: combatant.name,
      positionX: 0,
      positionY: 0,
      hpCurrent: combatant.hpMax,
      hpMax: combatant.hpMax,
      size: 1,
    });
    setShowAddPanel(false);
  }, [addTokenMutation]);

  // Get selected token
  const selectedToken = currentSession?.tokens.find((t: BattleToken) => t.id === selectedTokenId);

  return (
    <div className="h-screen flex flex-col bg-gray-900">
      {/* Header */}
      <header className="flex items-center justify-between px-4 py-3 bg-black/50 border-b border-white/10">
        <div className="flex items-center gap-3">
          <button
            onClick={() => navigate(`/campaigns/${campaignId}`)}
            className="p-2 rounded-lg bg-white/5 hover:bg-white/10 text-white/70 transition-colors"
          >
            <ArrowLeft className="w-5 h-5" />
          </button>
          <div className="flex items-center gap-2">
            <Swords className="w-5 h-5 text-primary" />
            <h1 className="text-lg font-semibold text-white">Kampfbildschirm</h1>
          </div>
          {isConnected && (
            <span className="px-2 py-0.5 text-[10px] font-medium bg-green-500/20 text-green-400 rounded">
              Verbunden
            </span>
          )}
        </div>

        {currentSession && (
          <div className="flex items-center gap-4">
            <div className="text-sm text-white/70">
              Runde: <span className="font-bold text-white">{currentSession.roundNumber}</span>
            </div>
            {isGM && (
              <button
                onClick={() => advanceRound()}
                className="px-3 py-1.5 bg-primary text-white rounded-lg text-sm font-medium hover:bg-primary/80 transition-colors"
              >
                Nächste Runde
              </button>
            )}
          </div>
        )}
      </header>

      {/* Main content */}
      <div className="flex-1 flex overflow-hidden">
        {/* Session list sidebar */}
        <BattleSessionList
          sessions={sessions}
          maps={maps}
          selectedSessionId={selectedSessionId}
          isGM={isGM}
          onSelectSession={setSelectedSessionId}
          onCreateSession={(name, mapId) => createSessionMutation.mutate({ name, mapId })}
          onDeleteSession={(sessionId) => deleteSessionMutation.mutate(sessionId)}
          onToggleActive={(sessionId, isActive) =>
            updateSessionMutation.mutate({ sessionId, data: { isActive } })
          }
        />

        {/* Battle canvas */}
        {currentSession ? (
          <BattleCanvas
            session={currentSession}
            map={currentSession.map || null}
            isGM={isGM}
            selectedTokenId={selectedTokenId}
            onSelectToken={setSelectedTokenId}
            onMoveToken={handleMoveToken}
          />
        ) : (
          <div className="flex-1 flex items-center justify-center text-white/50">
            <p>Wähle einen Kampf aus oder erstelle einen neuen</p>
          </div>
        )}

        {/* Token detail panel / Add panel */}
        {currentSession && isGM && (
          <div className="w-72 bg-black/30 border-l border-white/10 flex flex-col">
            {/* Panel header */}
            <div className="p-3 border-b border-white/10 flex items-center justify-between">
              <h3 className="font-semibold text-white">
                {showAddPanel ? 'Teilnehmer hinzufügen' : 'Token-Details'}
              </h3>
              <button
                onClick={() => setShowAddPanel(!showAddPanel)}
                className={cn(
                  'p-1.5 rounded-lg transition-colors',
                  showAddPanel
                    ? 'bg-white/10 text-white/70'
                    : 'bg-primary/20 text-primary hover:bg-primary/30',
                )}
              >
                <Plus className="w-4 h-4" />
              </button>
            </div>

            {/* Panel content */}
            <div className="flex-1 overflow-y-auto p-3">
              {showAddPanel ? (
                <div className="space-y-4">
                  {/* PCs */}
                  <div>
                    <h4 className="text-sm font-medium text-white/70 mb-2">Spielercharaktere</h4>
                    <div className="space-y-1">
                      {characters.filter((c: Character) => c.type === 'PC').map((character: Character) => (
                        <button
                          key={character.id}
                          onClick={() => handleAddPC(character)}
                          className="w-full flex items-center gap-2 p-2 rounded-lg bg-blue-500/10 hover:bg-blue-500/20 text-blue-400 transition-colors"
                        >
                          <Users className="w-4 h-4" />
                          <span className="text-sm truncate">{character.name}</span>
                          <ChevronRight className="w-4 h-4 ml-auto opacity-50" />
                        </button>
                      ))}
                      {characters.filter((c: Character) => c.type === 'PC').length === 0 && (
                        <p className="text-xs text-white/40">Keine Charaktere verfügbar</p>
                      )}
                    </div>
                  </div>

                  {/* NPCs/Monsters */}
                  <div>
                    <h4 className="text-sm font-medium text-white/70 mb-2">NPCs & Monster</h4>
                    <div className="space-y-1">
                      {combatants.map((combatant: Combatant) => (
                        <button
                          key={combatant.id}
                          onClick={() => handleAddNPC(combatant)}
                          className="w-full flex items-center gap-2 p-2 rounded-lg bg-red-500/10 hover:bg-red-500/20 text-red-400 transition-colors"
                        >
                          <Swords className="w-4 h-4" />
                          <span className="text-sm truncate">{combatant.name}</span>
                          <span className="text-xs opacity-50">Lvl {combatant.level}</span>
                          <ChevronRight className="w-4 h-4 ml-auto opacity-50" />
                        </button>
                      ))}
                      {combatants.length === 0 && (
                        <p className="text-xs text-white/40">Keine NPCs verfügbar</p>
                      )}
                    </div>
                  </div>
                </div>
              ) : selectedToken ? (
                <div className="space-y-4">
                  {/* Token info */}
                  <div>
                    <h4 className="text-lg font-semibold text-white">{selectedToken.name}</h4>
                    <p className="text-sm text-white/50">
                      {selectedToken.characterId ? 'Spielercharakter' : 'NPC/Monster'}
                    </p>
                  </div>

                  {/* HP */}
                  <div>
                    <label className="text-sm text-white/70">HP</label>
                    <div className="flex items-center gap-2 mt-1">
                      <input
                        type="number"
                        value={selectedToken.hpCurrent}
                        onChange={(e) => updateTokenHp(selectedToken.id, parseInt(e.target.value) || 0)}
                        className="w-20 px-2 py-1 bg-white/5 border border-white/10 rounded text-white text-center"
                      />
                      <span className="text-white/50">/</span>
                      <span className="text-white">{selectedToken.hpMax}</span>
                    </div>
                  </div>

                  {/* Initiative */}
                  <div>
                    <label className="text-sm text-white/70">Initiative</label>
                    <input
                      type="number"
                      value={selectedToken.initiative ?? ''}
                      onChange={(e) => setInitiative(selectedToken.id, parseInt(e.target.value) || 0)}
                      className="w-full mt-1 px-2 py-1 bg-white/5 border border-white/10 rounded text-white"
                      placeholder="0"
                    />
                  </div>

                  {/* Position */}
                  <div>
                    <label className="text-sm text-white/70">Position</label>
                    <p className="text-white">
                      X: {selectedToken.positionX}, Y: {selectedToken.positionY}
                    </p>
                  </div>

                  {/* Conditions */}
                  {selectedToken.conditions.length > 0 && (
                    <div>
                      <label className="text-sm text-white/70">Zustände</label>
                      <div className="flex flex-wrap gap-1 mt-1">
                        {selectedToken.conditions.map((condition: string, i: number) => (
                          <span
                            key={i}
                            className="px-2 py-0.5 text-xs bg-yellow-500/20 text-yellow-400 rounded"
                          >
                            {condition}
                          </span>
                        ))}
                      </div>
                    </div>
                  )}

                  {/* Remove token */}
                  <button
                    onClick={() => removeTokenMutation.mutate(selectedToken.id)}
                    className="w-full px-3 py-2 bg-red-500/20 text-red-400 rounded-lg text-sm hover:bg-red-500/30 transition-colors"
                  >
                    Vom Kampf entfernen
                  </button>
                </div>
              ) : (
                <div className="text-center text-white/40 py-8">
                  <p>Kein Token ausgewählt</p>
                  <p className="text-xs mt-1">Klicke auf ein Token oder füge neue hinzu</p>
                </div>
              )}
            </div>
          </div>
        )}
      </div>
    </div>
  );
}
