import { defineStore } from 'pinia';
import { ref, computed, shallowRef, watch } from 'vue';
import { io, Socket } from 'socket.io-client';
import type {
  ServerToClientEvents,
  ClientToServerEvents,
  DrawStartPayload,
  DrawWinnerPayload,
  VoteUpdatePayload,
  AdminState,
  SystemPhase,
} from '@gala/shared/types';
import { SOCKET_EVENTS } from '@gala/shared/constants';

type GalaSocket = Socket<ServerToClientEvents, ClientToServerEvents>;

export const useDisplayStore = defineStore('display', () => {
  // State - use shallowRef for socket to avoid deep reactivity issues
  const socket = shallowRef<GalaSocket | null>(null);
  const isConnected = ref(false);
  const isConnecting = ref(false);
  const onlineUsers = ref(0);
  const currentMode = ref<'idle' | 'voting' | 'draw' | 'results'>('idle');

  // Draw state
  const isDrawing = ref(false);
  const currentPrize = ref<string | null>(null);
  const currentWinner = ref<{
    userId: string;
    userName: string;
    department: string;
    avatar?: string;
  } | null>(null);

  // Computed
  const connectionStatus = computed(() => {
    if (isConnected.value) return 'connected';
    if (isConnecting.value) return 'connecting';
    return 'disconnected';
  });

  /**
   * Connect to WebSocket server
   */
  function connect() {
    if (socket.value?.connected || isConnecting.value) {
      return;
    }

    isConnecting.value = true;

    const socketInstance = io(import.meta.env.VITE_SOCKET_URL || '', {
      reconnection: true,
      reconnectionAttempts: Infinity,
      reconnectionDelay: 1000,
      reconnectionDelayMax: 5000,
      timeout: 10000,
      transports: ['websocket', 'polling'],
    });

    // Connection events
    socketInstance.on('connect', () => {
      console.log('[Screen] Connected');
      isConnected.value = true;
      isConnecting.value = false;

      // Join as screen
      socketInstance.emit(SOCKET_EVENTS.CONNECTION_JOIN as any, {
        userId: 'screen_main',
        userName: 'Main Display',
        role: 'screen',
      }, () => { });
    });

    socketInstance.on('disconnect', (reason) => {
      console.log('[Screen] Disconnected:', reason);
      isConnected.value = false;
    });

    socketInstance.on('connect_error', (error) => {
      console.error('[Screen] Connection error:', error);
      isConnecting.value = false;
    });

    // User count updates
    socketInstance.on('connection:users_count' as any, (count: number) => {
      onlineUsers.value = count;
    });

    // Draw events
    socketInstance.on('draw:started' as any, (data: DrawStartPayload) => {
      isDrawing.value = true;
      currentPrize.value = data.prizeName;
      currentWinner.value = null;
      currentMode.value = 'draw';
    });

    socketInstance.on('draw:winner' as any, (data: DrawWinnerPayload) => {
      currentWinner.value = data.winner;
    });

    socketInstance.on('draw:ended' as any, () => {
      isDrawing.value = false;
    });

    // Vote updates
    socketInstance.on('vote:updated' as any, (data: VoteUpdatePayload) => {
      // Emit custom event for components to handle
      window.dispatchEvent(new CustomEvent('vote:updated', { detail: data }));
    });

    // Admin state sync - listen for phase changes from director console
    socketInstance.on(SOCKET_EVENTS.ADMIN_STATE_SYNC as any, (state: AdminState) => {
      console.log('[Screen] Admin state sync received:', state.systemPhase);

      // Map SystemPhase to display mode
      const phaseToMode: Record<SystemPhase, 'idle' | 'voting' | 'draw' | 'results'> = {
        'IDLE': 'idle',
        'VOTING': 'voting',
        'LOTTERY': 'draw',
        'RESULTS': 'results',
      };

      const newMode = phaseToMode[state.systemPhase] || 'idle';
      if (currentMode.value !== newMode) {
        currentMode.value = newMode;
        // Emit custom event for App.vue to handle route navigation
        window.dispatchEvent(new CustomEvent('screen:mode_change', {
          detail: { mode: newMode, phase: state.systemPhase }
        }));
      }
    });

    socket.value = socketInstance as GalaSocket;
  }

  /**
   * Disconnect from server
   */
  function disconnect() {
    if (socket.value) {
      socket.value.disconnect();
      socket.value = null;
    }
    isConnected.value = false;
    isConnecting.value = false;
  }

  /**
   * Set display mode
   */
  function setMode(mode: 'idle' | 'voting' | 'draw' | 'results') {
    currentMode.value = mode;
  }

  /**
   * Get socket instance (for advanced usage)
   */
  function getSocket(): GalaSocket | null {
    return socket.value;
  }

  return {
    // State (excluding socket to avoid type inference issues)
    isConnected,
    isConnecting,
    onlineUsers,
    currentMode,
    isDrawing,
    currentPrize,
    currentWinner,

    // Computed
    connectionStatus,

    // Actions
    connect,
    disconnect,
    setMode,
    getSocket,
  };
});
