import { useConfig } from '@/api/useConfig'
import { useIsAnalyticsEnabled } from '@/features/analytics/hooks/useIsAnalyticsEnabled'
import {
  useRemoteParticipants,
  useRoomContext,
} from '@livekit/components-react'
import { useEffect, useRef } from 'react'
import { useSnapshot } from 'valtio'
import { DisconnectReason, RoomEvent } from 'livekit-client'

import { userPreferencesStore } from '@/stores/userPreferences'

import { captureEvent, captureMediaEvent } from '@/features/analytics/telemetry'
import { connectionObserverStore } from '@/stores/connectionObserver'

export const ConnectionObserver = () => {
  const room = useRoomContext()
  const connectionStartTimeRef = useRef<number | null>(null)

  const { data } = useConfig()
  const isAnalyticsEnabled = useIsAnalyticsEnabled()
  const userPreferencesSnap = useSnapshot(userPreferencesStore)

  const idleDisconnectModalTimeoutRef = useRef<ReturnType<
    typeof setTimeout
  > | null>(null)

  const remoteParticipants = useRemoteParticipants({
    updateOnlyOn: [
      RoomEvent.ParticipantConnected,
      RoomEvent.ParticipantDisconnected,
    ],
  })

  useEffect(() => {
    // Always clear existing timer on dependency change
    if (idleDisconnectModalTimeoutRef.current) {
      clearTimeout(idleDisconnectModalTimeoutRef.current)
      idleDisconnectModalTimeoutRef.current = null
    }

    const isEnabled = userPreferencesSnap.is_idle_disconnect_modal_enabled
    const delay = data?.idle_disconnect_warning_delay

    // Disabled or invalid delay: ensure modal is closed
    if (!isEnabled || !delay) {
      connectionObserverStore.isIdleDisconnectModalOpen = false
      return
    }

    if (remoteParticipants.length === 0) {
      idleDisconnectModalTimeoutRef.current = setTimeout(() => {
        connectionObserverStore.isIdleDisconnectModalOpen = true
      }, delay)
    } else {
      connectionObserverStore.isIdleDisconnectModalOpen = false
    }

    return () => {
      if (idleDisconnectModalTimeoutRef.current) {
        clearTimeout(idleDisconnectModalTimeoutRef.current)
        idleDisconnectModalTimeoutRef.current = null
      }
    }
  }, [
    remoteParticipants.length,
    data?.idle_disconnect_warning_delay,
    userPreferencesSnap.is_idle_disconnect_modal_enabled,
  ])

  useEffect(() => {
    if (!isAnalyticsEnabled) return

    const handleConnection = () => {
      // Preserve original connection timestamp across reconnections to measure
      // total session duration from first connect to final disconnect.
      if (connectionStartTimeRef.current != null) return
      connectionStartTimeRef.current = Date.now()
      void captureMediaEvent('connection-event', {})
    }

    const handleReconnect = () => {
      captureEvent('reconnect-event')
    }

    const handleReconnected = () => {
      captureEvent('reconnected-event')
    }

    const handleSignalingConnect = () => {
      captureEvent('signaling-connect-event')
    }

    const handleSignalingReconnect = () => {
      captureEvent('signaling-reconnect-event')
    }

    const handleDisconnect = (
      disconnectReason: DisconnectReason | undefined
    ) => {
      const connectionEndTime = Date.now()

      captureEvent('disconnect-event', {
        // Calculate total session duration from first connection to final disconnect
        // This duration is sensitive to refreshing the page.
        sessionDuration: connectionStartTimeRef.current
          ? connectionEndTime - connectionStartTimeRef.current
          : -1,
        reason: disconnectReason
          ? DisconnectReason[disconnectReason]
          : 'UNKNOWN',
      })
    }

    room.on(RoomEvent.Connected, handleConnection)
    room.on(RoomEvent.SignalConnected, handleSignalingConnect)
    room.on(RoomEvent.Disconnected, handleDisconnect)
    room.on(RoomEvent.Reconnecting, handleReconnect)
    room.on(RoomEvent.Reconnected, handleReconnected)
    room.on(RoomEvent.SignalReconnecting, handleSignalingReconnect)

    return () => {
      room.off(RoomEvent.Connected, handleConnection)
      room.off(RoomEvent.SignalConnected, handleSignalingConnect)
      room.off(RoomEvent.Disconnected, handleDisconnect)
      room.off(RoomEvent.Reconnecting, handleReconnect)
      room.off(RoomEvent.Reconnected, handleReconnected)
      room.off(RoomEvent.SignalReconnecting, handleSignalingReconnect)
    }
  }, [room, isAnalyticsEnabled])

  useEffect(() => {
    return () => {
      connectionStartTimeRef.current = null
    }
  }, [])

  return null
}
