import { useEffect, useRef } from 'react';
import type { MapPoint } from '../components/map/types';

export interface DeviceStreamEvent {
  deviceId: string;
  lastSeenAt?: string;
  isActive?: boolean;
  disabledReason?: string | null;
  position?: MapPoint;
  job?: { id: string; ticketNumber: string; title: string };
}

// Subscribes to live device updates (position pings, log points, and
// admin enable/disable) for an org over the backend WebSocket, so the
// devices page reflects device activity without a manual refresh.
export function useDevicesStream(orgId: string | null, onEvent: (event: DeviceStreamEvent) => void) {
  const eventRef = useRef(onEvent);
  eventRef.current = onEvent;

  useEffect(() => {
    if (!orgId) {
      return;
    }

    let socket: WebSocket | null = null;
    let closed = false;
    let attempt = 0;
    let timer: ReturnType<typeof setTimeout> | null = null;
    const channel = `org:${orgId}:devices`;

    const connect = () => {
      const proto = window.location.protocol === 'https:' ? 'wss' : 'ws';
      socket = new WebSocket(`${proto}://${window.location.host}/api/ws`);

      socket.onopen = () => {
        attempt = 0;
        socket?.send(JSON.stringify({ type: 'subscribe', channel }));
      };

      socket.onmessage = (event) => {
        try {
          const msg = JSON.parse(event.data);
          if (msg.type === 'device') {
            eventRef.current(msg as DeviceStreamEvent);
          }
        } catch {
          // ignore malformed frames
        }
      };

      socket.onclose = () => {
        if (closed) {
          return;
        }
        attempt += 1;
        const delay = Math.min(1000 * 2 ** attempt, 15000);
        timer = setTimeout(connect, delay);
      };
    };

    connect();

    return () => {
      closed = true;
      if (timer) {
        clearTimeout(timer);
      }
      socket?.close();
    };
  }, [orgId]);
}
