import { useState, useEffect, useCallback } from 'react';
import PartySocket from 'partysocket';
import { GameState } from '../types';
import { useAuth, useUser } from '@clerk/clerk-react';

const PARTY_HOST = import.meta.env.DEV ? 'https://solid-rotary-phone-pg69xw5vj7rc7r55-1999.app.github.dev' : 'bozo-clicker.arjunindia.partykit.dev';

export function usePartyKit() {
  const { getToken, isLoaded, isSignedIn } = useAuth();
  const { user } = useUser();
  const [gameState, setGameState] = useState<GameState | null>(null);
  const [socket, setSocket] = useState<PartySocket | null>(null);
  const [lastMessage, setLastMessage] = useState<string | null>(null);
  // ratPoisonChallengeData will now be derived from gameState
  const [ratPoisonResultData, setRatPoisonResultData] = useState<{ success: boolean; message: string } | null>(null);
  const [ratPoisonFeedbackData, setRatPoisonFeedbackData] = useState<string | null>(null);
  // Generate a persistent guest ID if the user is not signed in
  const [guestId] = useState(() => {
    let storedGuestId = localStorage.getItem('bozo_guest_id');
    if (!storedGuestId) {
      storedGuestId = `guest_${Math.random().toString(36).substring(2, 15)}`;
      localStorage.setItem('bozo_guest_id', storedGuestId);
    }
    return storedGuestId;
  });
  const [guestName] = useState(() => {
    let storedGuestName = localStorage.getItem('bozo_guest_name');
    if (!storedGuestName) {
      storedGuestName = `Guest${Math.floor(Math.random() * 10000)}`;
      localStorage.setItem('bozo_guest_name', storedGuestName);
    }
    return storedGuestName;
  });

  useEffect(() => {
    // Always attempt to connect the socket
    const ws = new PartySocket({
      host: PARTY_HOST,
      room: 'bozo-clicker'
    });

    ws.onopen = async () => {
      if (isLoaded && isSignedIn && user) {
        const token = await getToken();
        ws.send(JSON.stringify({
          type: 'user-join',
          userId: user.id,
          userName: user.username || user.fullName || user.emailAddresses[0].emailAddress,
          token
        }));
      } else {
        // If not signed in, send a generic user-join message for guest
        ws.send(JSON.stringify({
          type: 'user-join',
          userId: guestId,
          userName: guestName
        }));
      }
    };

    ws.onmessage = (event) => {
      const data = JSON.parse(event.data);
      if (data.type === 'game-state') {
        setGameState(data.state);
      } else if (data.type === 'rat-poison-result') {
        console.log('usePartyKit: Setting ratPoisonResultData:', { success: data.success, message: data.message });
        setRatPoisonResultData({ success: data.success, message: data.message });
      } else if (data.type === 'rat-poison-feedback') {
        console.log('usePartyKit: Setting ratPoisonFeedbackData:', data.message);
        setRatPoisonFeedbackData(data.message);
      }
      // No longer setting ratPoisonChallengeData directly here, it will be derived from gameState
      setLastMessage(event.data); // Still store the raw last message for other general purposes if needed
    };

    setSocket(ws);

    return () => {
      ws.close();
    };
  }, [isLoaded, isSignedIn, user, getToken, guestId, guestName]);

  const sendClick = useCallback(async () => {
    if (socket && isSignedIn && user) {
      const token = await getToken();
      socket.send(JSON.stringify({
        type: 'click',
        userId: user.id,
        userName: user.username || user.fullName || user.emailAddresses[0].emailAddress,
        token
      }));
    }
  }, [socket, isSignedIn, user, getToken]);

  const purchaseUpgrade = useCallback(async (upgradeId: string) => {
    if (socket && isSignedIn && user) {
      const token = await getToken();
      socket.send(JSON.stringify({
        type: 'purchase-upgrade',
        userId: user.id,
        upgradeId,
        token
      }));
    }
  }, [socket, isSignedIn, user, getToken]);

  const sendMascotClickBonus = useCallback(async (multiplierBonus: number) => {
    if (socket && isSignedIn && user) {
      const token = await getToken();
      socket.send(JSON.stringify({
        type: 'apply-multiplier-bonus',
        userId: user.id,
        userName: user.username || user.fullName || user.emailAddresses[0].emailAddress,
        token,
        multiplierBonus
      }));
    }
  }, [socket, isSignedIn, user, getToken]);

  // Determine the userId and userName to expose based on sign-in status
  // Only expose Clerk user ID/name if signed in, otherwise undefined
  const sendMessage = useCallback((message: string) => {
    if (socket) {
      socket.send(message);
    }
  }, [socket]);

  // Determine the userId and userName to expose based on sign-in status
  // Only expose Clerk user ID/name if signed in, otherwise undefined
  const currentUserId = isSignedIn && user ? user.id : undefined;
  const currentUserName = isSignedIn && user ? (user.username || user.fullName || user.emailAddresses[0].emailAddress) : undefined;

  const editUser = useCallback(async (targetUserId: string, clicks: number, upgrades: Record<string, { owned: number; cost: number }>) => {
    if (socket && isSignedIn && user) {
      const token = await getToken();
      socket.send(JSON.stringify({
        type: 'edit-user',
        token,
        userId: user.id,
        userName: user.username || user.fullName || user.emailAddresses[0].emailAddress,
        targetUserId,
        clicks,
        upgrades
      }));
    }
  }, [socket, isSignedIn, user, getToken]);

  const throwRatPoison = useCallback(async (targetUserId: string) => {
    if (socket && isSignedIn && user) {
      const token = await getToken();
      socket.send(JSON.stringify({
        type: 'throw-rat-poison',
        userId: user.id,
        userName: user.username || user.fullName || user.emailAddresses[0].emailAddress,
        token,
        targetUserId,
      }));
    }
  }, [socket, isSignedIn, user, getToken]);

  const sendSolveRatPoison = useCallback(async (challengeString: string) => {
    if (socket && isSignedIn && user) {
      const token = await getToken();
      socket.send(JSON.stringify({
        type: 'solve-rat-poison',
        userId: user.id,
        userName: user.username || user.fullName || user.emailAddresses[0].emailAddress,
        token,
        challengeString,
      }));
    }
  }, [socket, isSignedIn, user, getToken]);

  const clearRatPoisonChallenge = useCallback(() => {
    setRatPoisonResultData(null);
    setRatPoisonFeedbackData(null);
  }, []);

  return {
    gameState,
    sendClick,
    purchaseUpgrade,
    sendMascotClickBonus,
    sendMessage, // Expose sendMessage
    lastMessage, // Expose lastMessage
    userId: currentUserId,
    userName: currentUserName,
    getToken, // Expose getToken
    editUser,
    throwRatPoison,
    sendSolveRatPoison,
    ratPoisonResultData,
    ratPoisonFeedbackData,
    ratPoisonChallengeData: gameState?.users[currentUserId || '']?.ratPoisonChallenge || null,
    clearRatPoisonChallenge,
  };
}
