'use client';

import { useCallback, useEffect, useRef, useState } from 'react';

export interface UserStatus {
  user_id: number;
  is_online: boolean;
  last_activity: string | null;
}

// Глобальное хранилище статусов
const userStatuses = new Map<number, UserStatus>();
const listeners = new Set<(s: UserStatus) => void>();

export const subscribeToUserStatus = (cb: (s: UserStatus) => void) => {
  listeners.add(cb);
  return () => listeners.delete(cb);
};

export const getUserStatus = (userId: number): UserStatus | null => userStatuses.get(userId) || null;

const updateUserStatus = (s: UserStatus) => {
  userStatuses.set(s.user_id, s);
  listeners.forEach((cb) => {
    try {
      cb(s);
    } catch {
      // ignore
    }
  });
};

export const usePresenceWebSocket = (options?: { enabled?: boolean }) => {
  const enabled = options?.enabled ?? true;
  const [isConnected, setIsConnected] = useState(false);
  const wsRef = useRef<WebSocket | null>(null);
  const pingRef = useRef<number | null>(null);

  const connect = useCallback(() => {
    if (!enabled) return;
    const token = typeof window !== 'undefined' ? localStorage.getItem('access_token') : null;
    if (!token) return;

    let apiUrl = process.env.NEXT_PUBLIC_API_URL || window.location.origin;
    apiUrl = apiUrl.replace(/\/api\/?$/, '').replace(/\/api\//, '/');
    apiUrl = apiUrl.replace(/\/$/, '');

    const wsProtocol = apiUrl.startsWith('https') ? 'wss:' : 'ws:';
    const wsHost = apiUrl.replace(/^https?:\/\//, '');
    const wsUrl = `${wsProtocol}//${wsHost}/ws/presence/?token=${token}`;

    const ws = new WebSocket(wsUrl);
    wsRef.current = ws;

    ws.onopen = () => {
      setIsConnected(true);
      // ping каждые 30 секунд
      pingRef.current = window.setInterval(() => {
        try {
          if (ws.readyState === WebSocket.OPEN) ws.send(JSON.stringify({ type: 'ping' }));
        } catch {
          // ignore
        }
      }, 30000);
    };

    ws.onclose = () => {
      setIsConnected(false);
      if (pingRef.current) window.clearInterval(pingRef.current);
      pingRef.current = null;
    };

    ws.onerror = () => {
      setIsConnected(false);
    };

    ws.onmessage = (ev) => {
      try {
        const data = JSON.parse(ev.data);
        if (data?.type === 'user_status_update' && typeof data.user_id === 'number') {
          updateUserStatus({
            user_id: data.user_id,
            is_online: !!data.is_online,
            last_activity: data.last_activity ?? null,
          });
        }
      } catch {
        // ignore
      }
    };
  }, [enabled]);

  const disconnect = useCallback(() => {
    if (pingRef.current) window.clearInterval(pingRef.current);
    pingRef.current = null;
    if (wsRef.current) {
      wsRef.current.close();
      wsRef.current = null;
    }
    setIsConnected(false);
  }, []);

  useEffect(() => {
    disconnect();
    connect();
    return () => disconnect();
  }, [connect, disconnect]);

  return { isConnected };
};

