import type { ReactNode } from "react";
import React, { createContext, useContext } from "react";
import { useWebSocket } from "../hooks/useWebSocket";
import type { Socket } from "socket.io-client";

interface Task {
  id: string;
  [key: string]: unknown;
}

interface Event {
  id: string;
  [key: string]: unknown;
}

interface Project {
  id: string;
  [key: string]: unknown;
}

interface DeletePayload {
  id: string;
}

interface ConnectionError {
  message: string;
  type: string;
  description?: string;
}

interface WebSocketContextValue {
  isConnected: boolean;
  socket: Socket | null;
  connectionError: ConnectionError | null;
}

interface WebSocketProviderProps {
  workspaceId: string;
  token: string;
  onTaskCreated?: (task: Task) => void;
  onTaskUpdated?: (task: Task) => void;
  onTaskDeleted?: (payload: DeletePayload) => void;
  onEventCreated?: (event: Event) => void;
  onEventUpdated?: (event: Event) => void;
  onEventDeleted?: (payload: DeletePayload) => void;
  onProjectUpdated?: (project: Project) => void;
  children: ReactNode;
}

const WebSocketContext = createContext<WebSocketContextValue | undefined>(undefined);

/**
 * WebSocket Provider component
 * Manages WebSocket connection and provides context to children
 */
export function WebSocketProvider({
  workspaceId,
  token,
  onTaskCreated,
  onTaskUpdated,
  onTaskDeleted,
  onEventCreated,
  onEventUpdated,
  onEventDeleted,
  onProjectUpdated,
  children,
}: WebSocketProviderProps): React.JSX.Element {
  const callbacks: {
    onTaskCreated?: (task: Task) => void;
    onTaskUpdated?: (task: Task) => void;
    onTaskDeleted?: (payload: DeletePayload) => void;
    onEventCreated?: (event: Event) => void;
    onEventUpdated?: (event: Event) => void;
    onEventDeleted?: (payload: DeletePayload) => void;
    onProjectUpdated?: (project: Project) => void;
  } = {};

  if (onTaskCreated) callbacks.onTaskCreated = onTaskCreated;
  if (onTaskUpdated) callbacks.onTaskUpdated = onTaskUpdated;
  if (onTaskDeleted) callbacks.onTaskDeleted = onTaskDeleted;
  if (onEventCreated) callbacks.onEventCreated = onEventCreated;
  if (onEventUpdated) callbacks.onEventUpdated = onEventUpdated;
  if (onEventDeleted) callbacks.onEventDeleted = onEventDeleted;
  if (onProjectUpdated) callbacks.onProjectUpdated = onProjectUpdated;

  const { isConnected, socket, connectionError } = useWebSocket(workspaceId, token, callbacks);

  const value: WebSocketContextValue = {
    isConnected,
    socket,
    connectionError,
  };

  return <WebSocketContext.Provider value={value}>{children}</WebSocketContext.Provider>;
}

/**
 * Hook to access WebSocket context
 * @throws Error if used outside WebSocketProvider
 */
export function useWebSocketContext(): WebSocketContextValue {
  const context = useContext(WebSocketContext);

  if (context === undefined) {
    throw new Error("useWebSocketContext must be used within WebSocketProvider");
  }

  return context;
}
