import { useState, useEffect, useRef, useCallback } from 'react';
import { useLocation } from 'react-router-dom';
import { useAuth } from '../context/AuthContext';

const WS_RECONNECT_DELAY = 3000;
const PING_INTERVAL = 30000;

export function usePresence() {
  const { token, adminName, isAuthenticated } = useAuth();
  const location = useLocation();
  const [viewers, setViewers] = useState([]);
  const [services, setServices] = useState([]);
  const wsRef = useRef(null);
  const pingRef = useRef(null);
  const reconnectRef = useRef(null);
  const locationRef = useRef(location.pathname);
  const adminNameRef = useRef(adminName);

  locationRef.current = location.pathname;
  adminNameRef.current = adminName;

  const getWsUrl = useCallback(() => {
    const protocol = window.location.protocol === 'https:' ? 'wss:' : 'ws:';
    return `${protocol}//${window.location.host}/api/sessions/live`;
  }, []);

  const connect = useCallback(() => {
    if (!isAuthenticated || !token) return;

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

    ws.onopen = () => {
      ws.send(JSON.stringify({ type: 'auth', token }));
    };

    ws.onmessage = (event) => {
      const msg = JSON.parse(event.data);

      if (msg.type === 'auth_success') {
        ws.send(JSON.stringify({ type: 'page_focus', page: locationRef.current }));

        pingRef.current = setInterval(() => {
          if (ws.readyState === WebSocket.OPEN) {
            ws.send(JSON.stringify({ type: 'ping' }));
          }
        }, PING_INTERVAL);
      }

      if (msg.type === 'presence_update') {
        const currentPage = locationRef.current;
        const currentName = adminNameRef.current;
        const pageViewers = msg.admins
          .filter(a => a.role !== 'bot' && a.role !== 'utility' && a.page === currentPage)
          .map(a => ({ name: a.name === currentName ? 'me' : a.name, role: a.role || 'admin' }));
        const connectedServices = msg.admins
          .filter(a => a.role === 'bot' || a.role === 'utility')
          .map(a => ({ name: a.name, role: a.role }));
        setViewers(pageViewers);
        setServices(connectedServices);
      }
    };

    ws.onclose = () => {
      clearInterval(pingRef.current);
      reconnectRef.current = setTimeout(connect, WS_RECONNECT_DELAY);
    };

    ws.onerror = () => {
      ws.close();
    };
  }, [isAuthenticated, token, getWsUrl]);

  useEffect(() => {
    connect();

    return () => {
      clearTimeout(reconnectRef.current);
      clearInterval(pingRef.current);
      if (wsRef.current) {
        wsRef.current.onclose = null;
        wsRef.current.close();
      }
    };
  }, [connect]);

  useEffect(() => {
    if (wsRef.current?.readyState === WebSocket.OPEN) {
      wsRef.current.send(JSON.stringify({ type: 'page_focus', page: location.pathname }));
    }
  }, [location.pathname]);

  return { viewers, services };
}
