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 ? 'localhost:1999' : 'bozo-clicker.your-username.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); // New state for last message
  // 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);
      }
      setLastMessage(event.data); // Store the raw last message
    };

    setSocket(ws);

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

  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;

  return {
    gameState,
    sendClick,
    purchaseUpgrade,
    sendMascotClickBonus,
    sendMessage, // Expose sendMessage
    lastMessage, // Expose lastMessage
    userId: currentUserId,
    userName: currentUserName,
    getToken // Expose getToken
  };
}
