'use client';

import React from 'react';
import { usePathname } from 'next/navigation';

import { getStatus, listSessions, wsManager } from '@/lib/api';
import { runtimeBridgeEnabledForPath } from '@/lib/channel-connector-state';
import { useChatStore } from '@/lib/store';
import type { ProcessWsEvent, SessionUpdatedEvent, WsEvent } from '@/types';

function scheduleWhenIdle(task: () => void, timeout = 1200): () => void {
  if (typeof window === 'undefined') {
    task();
    return () => {};
  }

  const idleWindow = window as Window &
    typeof globalThis & {
      requestIdleCallback?: (callback: IdleRequestCallback, options?: IdleRequestOptions) => number;
      cancelIdleCallback?: (handle: number) => void;
    };

  if (typeof idleWindow.requestIdleCallback === 'function') {
    const id = idleWindow.requestIdleCallback(() => task(), { timeout });
    return () => idleWindow.cancelIdleCallback?.(id);
  }

  const id = globalThis.setTimeout(task, 250);
  return () => globalThis.clearTimeout(id);
}

function isProcessEvent(data: WsEvent | Record<string, unknown>): data is ProcessWsEvent {
  const type = typeof data.type === 'string' ? data.type : '';
  return type.startsWith('process_') || type === 'process_cancel_ack';
}

function isSessionUpdatedEvent(data: WsEvent | Record<string, unknown>): data is SessionUpdatedEvent {
  return data.type === 'session_updated' && typeof data.session_id === 'string';
}

export function AppRuntimeBridge() {
  const pathname = usePathname();
  const sessionId = useChatStore((state) => state.sessionId);
  const setSessions = useChatStore((state) => state.setSessions);
  const setWsStatus = useChatStore((state) => state.setWsStatus);
  const setBeaverReady = useChatStore((state) => state.setBeaverReady);
  const resetProcessState = useChatStore((state) => state.resetProcessState);
  const ingestProcessEvent = useChatStore((state) => state.ingestProcessEvent);
  const statusCheckCleanupRef = React.useRef<(() => void) | null>(null);
  const statusCheckInFlightRef = React.useRef(false);
  const chatRuntimeEnabled = runtimeBridgeEnabledForPath(pathname);

  const loadSessions = React.useCallback(async () => {
    try {
      const sessions = await listSessions();
      setSessions(sessions);
    } catch {
      // backend may still be offline during first render
    }
  }, [setSessions]);

  const scheduleStatusCheck = React.useCallback(() => {
    if (statusCheckInFlightRef.current) return;

    statusCheckCleanupRef.current?.();
    statusCheckCleanupRef.current = scheduleWhenIdle(async () => {
      statusCheckInFlightRef.current = true;
      try {
        await getStatus();
        setBeaverReady(true);
      } catch {
        setBeaverReady(false);
      } finally {
        statusCheckInFlightRef.current = false;
      }
    });
  }, [setBeaverReady]);

  React.useEffect(() => {
    if (!chatRuntimeEnabled) {
      return;
    }
    void loadSessions();
  }, [chatRuntimeEnabled, loadSessions]);

  React.useEffect(() => {
    if (!chatRuntimeEnabled) {
      wsManager.disconnect();
      setWsStatus('disconnected');
      setBeaverReady(null);
      return;
    }
    resetProcessState();
    wsManager.connect(sessionId);
  }, [chatRuntimeEnabled, resetProcessState, sessionId, setBeaverReady, setWsStatus]);

  React.useEffect(() => {
    if (!chatRuntimeEnabled) {
      return;
    }
    const unsubStatus = wsManager.onStatusChange((status) => {
      setWsStatus(status);
      if (status === 'connected') {
        scheduleStatusCheck();
      } else {
        statusCheckCleanupRef.current?.();
        statusCheckCleanupRef.current = null;
        setBeaverReady(null);
      }
    });

    return () => {
      statusCheckCleanupRef.current?.();
      statusCheckCleanupRef.current = null;
      unsubStatus();
    };
  }, [chatRuntimeEnabled, scheduleStatusCheck, setBeaverReady, setWsStatus]);

  React.useEffect(() => {
    if (!chatRuntimeEnabled) {
      return;
    }
    const unsubMessage = wsManager.onMessage((data) => {
      if (isSessionUpdatedEvent(data)) {
        void loadSessions();
        return;
      }

      if (isProcessEvent(data)) {
        ingestProcessEvent(data);
      }
    });

    return () => {
      unsubMessage();
    };
  }, [chatRuntimeEnabled, ingestProcessEvent, loadSessions]);

  return null;
}
