'use client';

import { useEffect, useRef, useCallback } from 'react';
import { useQueryClient } from '@tanstack/react-query';
import { queryKeys } from './use-api';

// socket.io-client dinamik import (SSR güvenli)
let io: typeof import('socket.io-client').io | null = null;
if (typeof window !== 'undefined') {
  import('socket.io-client').then((mod) => {
    io = mod.io;
  });
}

const WS_URL =
  process.env.NEXT_PUBLIC_WS_URL ||
  (process.env.NEXT_PUBLIC_API_URL || 'http://localhost:3000/api').replace('/api', '');

type RenderProgressPayload = {
  projectId: string;
  progress: number;
  stage: string;
  stageLabel: string;
  currentScene?: number;
  totalScenes?: number;
  eta?: number;
  timestamp: string;
};

type RenderCompletedPayload = {
  projectId: string;
  finalVideoUrl: string;
  thumbnailUrl?: string;
  processingTimeMs: number;
  fileSize: number;
  timestamp: string;
};

type RenderFailedPayload = {
  projectId: string;
  error: string;
  stage: string;
  attemptNumber: number;
  canRetry: boolean;
  timestamp: string;
};

type NotificationPayload = {
  id: string;
  type: string;
  title: string;
  message?: string | null;
  isRead: boolean;
  createdAt: string;
  timestamp: string;
};

interface UseWebSocketOptions {
  userId?: string;
  projectId?: string;
  onRenderProgress?: (payload: RenderProgressPayload) => void;
  onRenderCompleted?: (payload: RenderCompletedPayload) => void;
  onRenderFailed?: (payload: RenderFailedPayload) => void;
  onNotification?: (payload: NotificationPayload) => void;
}

/**
 * ContentGen WebSocket Hook
 *
 * Backend EventsGateway (/ws namespace) ile bağlantı kurar.
 * Render ilerleme bildirimleri ve anlık notification push için kullanılır.
 *
 * Kullanım:
 * - userId → join:user (bildirim room'u)
 * - projectId → join:project (render progress room'u)
 */
export function useWebSocket(options: UseWebSocketOptions = {}) {
  const { userId, projectId, onRenderProgress, onRenderCompleted, onRenderFailed, onNotification } =
    options;
  const socketRef = useRef<ReturnType<typeof import('socket.io-client').io> | null>(null);
  const qc = useQueryClient();

  const connect = useCallback(async () => {
    if (typeof window === 'undefined') return;
    if (socketRef.current?.connected) return;

    // io yüklenmemişse bekle
    if (!io) {
      const mod = await import('socket.io-client');
      io = mod.io;
    }

    const socket = io(`${WS_URL}/ws`, {
      path: '/socket.io',
      transports: ['websocket', 'polling'],
      reconnectionAttempts: 5,
      reconnectionDelay: 2000,
    });

    socketRef.current = socket;

    socket.on('connect', () => {
      // Kullanıcı bildirim room'una katıl
      if (userId) {
        socket.emit('join:user', { userId });
      }
      // Proje render progress room'una katıl
      if (projectId) {
        socket.emit('join:project', { projectId });
      }
    });

    // ── Render Progress ──────────────────────────────────────────────
    socket.on('render:progress', (payload: RenderProgressPayload) => {
      onRenderProgress?.(payload);
      // Proje cache'ini invalide et (progress güncellemesi için)
      if (payload.projectId) {
        qc.invalidateQueries({ queryKey: queryKeys.projects.detail(payload.projectId) });
      }
    });

    socket.on('render:completed', (payload: RenderCompletedPayload) => {
      onRenderCompleted?.(payload);
      if (payload.projectId) {
        qc.invalidateQueries({ queryKey: queryKeys.projects.detail(payload.projectId) });
        qc.invalidateQueries({ queryKey: queryKeys.projects.all });
        qc.invalidateQueries({ queryKey: queryKeys.dashboard.stats });
      }
    });

    socket.on('render:failed', (payload: RenderFailedPayload) => {
      onRenderFailed?.(payload);
      if (payload.projectId) {
        qc.invalidateQueries({ queryKey: queryKeys.projects.detail(payload.projectId) });
      }
    });

    // ── Notifications ────────────────────────────────────────────────
    socket.on('notification:new', (payload: NotificationPayload) => {
      onNotification?.(payload);
      // Bildirim cache'lerini güncelle
      qc.invalidateQueries({ queryKey: queryKeys.notifications.all });
      qc.invalidateQueries({ queryKey: queryKeys.notifications.unreadCount });
    });

    socket.on('disconnect', () => {
      // disconnect — reconnect otomatik yapılır
    });

    socket.on('connect_error', () => {
      // Sessiz bağlantı hatası — reconnect retry yapılır
    });
  }, [userId, projectId, onRenderProgress, onRenderCompleted, onRenderFailed, onNotification, qc]);

  useEffect(() => {
    connect();

    return () => {
      const socket = socketRef.current;
      if (socket) {
        if (projectId) socket.emit('leave:project', { projectId });
        if (userId) socket.emit('leave:user', { userId });
        socket.disconnect();
        socketRef.current = null;
      }
    };
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [userId, projectId]);

  // Proje değişince odayı güncelle
  useEffect(() => {
    const socket = socketRef.current;
    if (socket?.connected && projectId) {
      socket.emit('join:project', { projectId });
    }
  }, [projectId]);

  return {
    socket: socketRef.current,
    isConnected: socketRef.current?.connected ?? false,
  };
}

/**
 * Sadece kullanıcı bildirimleri için basit hook.
 * Layout/Provider seviyesinde kullanılır.
 */
export function useNotificationSocket(userId?: string, onNotification?: (payload: NotificationPayload) => void) {
  return useWebSocket({ userId, onNotification });
}
