import React, { useEffect, useRef, useState } from 'react'
import { useStudioSession } from '../hooks/useStudioSession'
import { connect, createLocalTracks, Room, LocalTrack } from 'livekit-client'

export const StudioConnector: React.FC = () => {
  const { state, session, error, connect, disconnect } = useStudioSession()

  const [room, setRoom] = useState<Room | null>(null)
  const [localTracks, setLocalTracks] = useState<LocalTrack[] | null>(null)
  const videoRef = useRef<HTMLVideoElement | null>(null)
  const [connectingError, setConnectingError] = useState<string | null>(null)

  // Determine LiveKit server URL (from Vite env or fallback)
  const LIVEKIT_URL = (import.meta.env.VITE_LIVEKIT_URL as string) || (window as any).VITE_LIVEKIT_URL || 'wss://livekit-server.bfzqqk.easypanel.host'

  useEffect(() => {
    // When the hook reports connected state and we have a token, establish the livekit Room
    const doConnect = async () => {
      setConnectingError(null)
      if (!session?.token) return
      // If we already have a room, skip
      if (room) return

      try {
        // Request local media permissions and create tracks
        const tracks = await createLocalTracks({ audio: true, video: true })
        setLocalTracks(tracks)

        // Connect to LiveKit room using token (session.token) and LIVEKIT_URL
        const r = await connect(LIVEKIT_URL, session.token, { reconnect: true })

        // Publish local tracks
        for (const t of tracks) {
          try {
            await r.localParticipant.publishTrack(t)
          } catch (err) {
            console.warn('publishTrack failed', err)
          }
        }

        // Attach the first video track to our preview element
        const videoTrack = tracks.find((t) => t.kind === 'video') as LocalTrack | undefined
        if (videoTrack && videoRef.current) {
          try {
            const el = videoTrack.attach()
            // attach returns HTMLMediaElement, ensure it's a video element
            // Replace container's children with this element
            if (videoRef.current.parentElement) {
              const parent = videoRef.current.parentElement
              parent.replaceChild(el, videoRef.current)
              videoRef.current = el as HTMLVideoElement
            }
          } catch (err) {
            console.warn('attach track failed', err)
          }
        }

        // Listen for room events (optional)
        r.on('disconnected', () => {
          setRoom(null)
        })
        r.on('reconnecting', () => {
          // Could set state to reconnecting
        })

        setRoom(r)
      } catch (e: any) {
        console.error('LiveKit connect error', e)
        setConnectingError(String(e?.message ?? e))
      }
    }

    if (state === 'connected' && session?.token) {
      void doConnect()
    }

    return () => {
      // nothing here: cleanup handled separately
    }
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [state, session?.token])

  // Cleanup on unmount or disconnect
  useEffect(() => {
    return () => {
      // Stop local tracks and disconnect room
      try {
        if (localTracks) {
          for (const t of localTracks) {
            try { t.stop(); t.detach(); } catch (e) { }
          }
        }
        if (room) {
          try { room.disconnect(); } catch (e) { }
        }
      } catch (e) {}
    }
  }, [localTracks, room])

  const onCreateAndEnter = async () => {
    try {
      await connect({ createIfMissing: true, createPayload: { title: 'E2E Transmisión' } })
    } catch (e) {
      console.error('connect failed', e)
    }
  }

  const onEnterExisting = async () => {
    if (!session?.id) {
      await onCreateAndEnter()
      return
    }
    try {
      await connect({ sessionId: session.id })
    } catch (e) {
      console.error('connect failed', e)
    }
  }

  const onDisconnect = async () => {
    try {
      if (room) {
        try { room.disconnect() } catch (e) { }
        setRoom(null)
      }
      if (localTracks) {
        for (const t of localTracks) {
          try { t.stop(); t.detach(); } catch (e) { }
        }
        setLocalTracks(null)
      }
      await disconnect()
    } catch (e) {
      console.warn('disconnect error', e)
    }
  }

  return (
    <div className="studio-connector">
      <div className="status" data-testid="studio-status">Estado: {state}</div>
      {error && <div className="error" data-testid="studio-error">Error: {error}</div>}
      {connectingError && <div className="error" data-testid="studio-connecting-error">Conexión LiveKit: {connectingError}</div>}

      <div className="controls">
        <button data-testid="btn-create-enter" onClick={onCreateAndEnter}>Crear transmisión y Entrar al Estudio</button>
        <button data-testid="btn-enter" onClick={onEnterExisting}>Entrar al Estudio</button>
        <button data-testid="btn-disconnect" onClick={onDisconnect}>Salir</button>
      </div>

      <div className="preview">
        <p>Session: {session?.id ?? 'n/a'}</p>
        <p>Token: {session?.token ? `${session.token.substring(0,20)}...` : 'n/a'}</p>
        <div style={{ width: 320, height: 240, background: '#111' }}>
          {/* placeholder video element - will be replaced by attach() result when track attaches */}
          <video ref={videoRef} autoPlay muted playsInline style={{ width: '100%', height: '100%', objectFit: 'cover' }} />
        </div>
      </div>
    </div>
  )
}

export default StudioConnector
