// Socket.io event type definitions for type-safe client-server communication

// ============================================================================
// Vote Types
// ============================================================================

export interface VoteSubmitPayload {
  candidateId: string;
  category: VoteCategory;
  clientTimestamp: number;
  localId: string; // For optimistic UI reconciliation
}

export interface VoteBatchPayload {
  votes: VoteSubmitPayload[];
}

export interface VoteUpdatePayload {
  candidateId: string;
  category: VoteCategory;
  totalVotes: number;
  delta: number;
}

export interface VoteResultPayload {
  category: VoteCategory;
  results: Array<{
    candidateId: string;
    candidateName: string;
    votes: number;
    rank: number;
  }>;
}

// ============================================================================
// Draw Types
// ============================================================================

export interface DrawStartPayload {
  drawId: string;
  prizeLevel: PrizeLevel;
  prizeName: string;
  participantCount: number;
}

export interface DrawSpinPayload {
  drawId: string;
  currentNames: string[]; // Names being shuffled on screen
  phase: 'accelerating' | 'spinning' | 'decelerating';
}

export interface DrawWinnerPayload {
  drawId: string;
  winner: {
    odrawId: string;
    visitorId: string;
    userId: string;
    userName: string;
    department: string;
    avatar?: string;
  };
  prizeLevel: PrizeLevel;
  prizeName: string;
}

export interface DrawStartRequest {
  prizeLevel: PrizeLevel;
  filters?: DrawFilters;
}

export interface DrawFilters {
  excludeWinners?: boolean; // Exclude previous winners
  zodiacFilter?: string; // e.g., 'horse' for Year of the Horse
  ageRange?: { min?: number; max?: number };
  departments?: string[];
}

// ============================================================================
// Connection Types
// ============================================================================

export interface JoinPayload {
  userId: string;
  userName: string;
  department?: string;
  role: UserRole;
  sessionToken?: string;
}

export interface ConnectionAckPayload {
  sessionId: string;
  serverTime: number;
  reconnected: boolean;
  missedEvents?: unknown[];
}

export interface SyncStatePayload {
  votes: Record<VoteCategory, Record<string, number>>; // category -> candidateId -> count
  userVotedCategories: VoteCategory[];
  currentDraw?: {
    isActive: boolean;
    prizeLevel: PrizeLevel;
    drawId: string;
  };
}

export interface SyncRequestPayload {
  lastEventId?: string;
  lastTimestamp?: number;
}

// ============================================================================
// Error Types
// ============================================================================

export interface ErrorPayload {
  code: SocketErrorCode;
  message: string;
  details?: Record<string, unknown>;
}

export type SocketErrorCode =
  | 'ALREADY_VOTED'
  | 'MAX_VOTES_REACHED'
  | 'INVALID_CANDIDATE'
  | 'VOTING_CLOSED'
  | 'UNAUTHORIZED'
  | 'RATE_LIMITED'
  | 'INTERNAL_ERROR';

// ============================================================================
// Callback Types
// ============================================================================

export type AckCallback<T = unknown> = (response: AckResponse<T>) => void;

export interface AckResponse<T = unknown> {
  success: boolean;
  error?: SocketErrorCode;
  message?: string;
  data?: T;
}

// ============================================================================
// Socket.io Event Maps
// ============================================================================

export interface ServerToClientEvents {
  // Vote events
  'vote:updated': (data: VoteUpdatePayload) => void;
  'vote:result': (data: VoteResultPayload) => void;
  'vote:error': (data: ErrorPayload) => void;

  // Draw events
  'draw:started': (data: DrawStartPayload) => void;
  'draw:spinning': (data: DrawSpinPayload) => void;
  'draw:winner': (data: DrawWinnerPayload) => void;
  'draw:ended': () => void;

  // Connection events
  'connection:ack': (data: ConnectionAckPayload) => void;
  'connection:users_count': (count: number) => void;
  'connection:pong': () => void;

  // Sync events
  'sync:state': (data: SyncStatePayload) => void;
}

export interface ClientToServerEvents {
  // Vote events
  'vote:submit': (data: VoteSubmitPayload, callback: AckCallback<{ newCount: number }>) => void;
  'vote:batch': (data: VoteBatchPayload, callback: AckCallback<{ processed: number }>) => void;

  // Draw events (admin only)
  'draw:start': (data: DrawStartRequest, callback: AckCallback<{ drawId: string }>) => void;
  'draw:stop': (callback: AckCallback) => void;

  // Connection events
  'connection:ping': () => void;
  'connection:join': (data: JoinPayload, callback: AckCallback<ConnectionAckPayload>) => void;

  // Sync events
  'sync:request': (data: SyncRequestPayload) => void;
}

export interface InterServerEvents {
  ping: () => void;
}

export interface SocketData {
  userId: string;
  userName: string;
  department: string;
  role: UserRole;
  connectedAt: Date;
  sessionId: string;
}

// ============================================================================
// Enums & Constants
// ============================================================================

export type UserRole = 'user' | 'admin' | 'screen';

export type VoteCategory =
  | 'best_employee'
  | 'best_team'
  | 'best_newcomer'
  | 'best_innovation'
  | 'best_service'
  | 'best_collaboration'
  | 'best_leadership';

export type PrizeLevel = 'special' | 'first' | 'second' | 'third' | 'participation';

export const VOTE_CATEGORIES: VoteCategory[] = [
  'best_employee',
  'best_team',
  'best_newcomer',
  'best_innovation',
  'best_service',
  'best_collaboration',
  'best_leadership',
];

export const PRIZE_LEVELS: PrizeLevel[] = ['special', 'first', 'second', 'third', 'participation'];
