import { useCallback, useEffect, useRef, useState } from 'react';
import type { AccessLog } from '../types';

const WS_BASE = (import.meta.env.VITE_API_BASE ?? 'http://localhost:8000')
  .replace(/^http/, 'ws');

const MAX_LOGS = 200;
const MAX_BACKOFF = 30000;

export function useWebSocket() {
  const [logs, setLogs] = useState<AccessLog[]>([]);
  const [connected, setConnected] = useState(false);
  const wsRef = useRef<WebSocket | null>(null);
  const retryRef = useRef<ReturnType<typeof setTimeout> | null>(null);
  const backoffRef = useRef(1000);
  const unmountedRef = useRef(false);

  const connect = useCallback(() => {
    if (unmountedRef.current) return;

    const ws = new WebSocket(`${WS_BASE}/ws/logs`);
    wsRef.current = ws;

    ws.onopen = () => {
      if (unmountedRef.current) { ws.close(); return; }
      setConnected(true);
      backoffRef.current = 1000;
    };

    ws.onmessage = (evt) => {
      try {
        const log: AccessLog = JSON.parse(evt.data as string);
        setLogs((prev) => [log, ...prev].slice(0, MAX_LOGS));
      } catch {
        // ignore malformed messages
      }
    };

    ws.onclose = () => {
      setConnected(false);
      if (!unmountedRef.current) {
        retryRef.current = setTimeout(() => {
          backoffRef.current = Math.min(backoffRef.current * 2, MAX_BACKOFF);
          connect();
        }, backoffRef.current);
      }
    };

    ws.onerror = () => ws.close();
  }, []);

  useEffect(() => {
    unmountedRef.current = false;
    connect();
    return () => {
      unmountedRef.current = true;
      if (retryRef.current) clearTimeout(retryRef.current);
      wsRef.current?.close();
    };
  }, [connect]);

  return { logs, connected, setLogs };
}
