"use client"

import { useState, useRef, useCallback, useEffect } from "react"

interface WebRTCState {
  isConnected: boolean
  isConnecting: boolean
  localStream: MediaStream | null
  remoteStream: MediaStream | null
  error: string | null
}

interface WebRTCConfig {
  video: boolean
  audio: boolean
}

export function useWebRTC(config: WebRTCConfig = { video: true, audio: true }) {
  const [state, setState] = useState<WebRTCState>({
    isConnected: false,
    isConnecting: false,
    localStream: null,
    remoteStream: null,
    error: null,
  })

  const peerConnectionRef = useRef<RTCPeerConnection | null>(null)
  const localStreamRef = useRef<MediaStream | null>(null)

  const initializePeerConnection = useCallback(() => {
    console.log("[v0] Initializing peer connection")

    const configuration = {
      iceServers: [{ urls: "stun:stun.l.google.com:19302" }, { urls: "stun:stun1.l.google.com:19302" }],
    }

    peerConnectionRef.current = new RTCPeerConnection(configuration)

    // Handle remote stream
    peerConnectionRef.current.ontrack = (event) => {
      console.log("[v0] Received remote stream")
      setState((prev) => ({ ...prev, remoteStream: event.streams[0] }))
    }

    // Handle ICE candidates
    peerConnectionRef.current.onicecandidate = (event) => {
      if (event.candidate) {
        console.log("[v0] ICE candidate generated:", event.candidate)
        // In a real app, send this to the remote peer via signaling server
      }
    }

    // Handle connection state changes
    peerConnectionRef.current.onconnectionstatechange = () => {
      const connectionState = peerConnectionRef.current?.connectionState
      console.log("[v0] Connection state changed:", connectionState)

      setState((prev) => ({
        ...prev,
        isConnected: connectionState === "connected",
        isConnecting: connectionState === "connecting",
      }))
    }

    return peerConnectionRef.current
  }, [])

  const getUserMedia = useCallback(async () => {
    try {
      console.log("[v0] Requesting user media")
      setState((prev) => ({ ...prev, isConnecting: true, error: null }))

      const stream = await navigator.mediaDevices.getUserMedia(config)
      localStreamRef.current = stream

      setState((prev) => ({ ...prev, localStream: stream }))

      // Add tracks to peer connection
      if (peerConnectionRef.current) {
        stream.getTracks().forEach((track) => {
          peerConnectionRef.current?.addTrack(track, stream)
        })
      }

      console.log("[v0] User media obtained successfully")
      return stream
    } catch (error) {
      console.error("[v0] Error getting user media:", error)
      setState((prev) => ({
        ...prev,
        error: error instanceof Error ? error.message : "Failed to access camera/microphone",
        isConnecting: false,
      }))
      throw error
    }
  }, [config])

  const createOffer = useCallback(async () => {
    if (!peerConnectionRef.current) {
      throw new Error("Peer connection not initialized")
    }

    try {
      console.log("[v0] Creating offer")
      const offer = await peerConnectionRef.current.createOffer()
      await peerConnectionRef.current.setLocalDescription(offer)
      console.log("[v0] Offer created and set as local description")
      return offer
    } catch (error) {
      console.error("[v0] Error creating offer:", error)
      throw error
    }
  }, [])

  const createAnswer = useCallback(async (offer: RTCSessionDescriptionInit) => {
    if (!peerConnectionRef.current) {
      throw new Error("Peer connection not initialized")
    }

    try {
      console.log("[v0] Creating answer")
      await peerConnectionRef.current.setRemoteDescription(offer)
      const answer = await peerConnectionRef.current.createAnswer()
      await peerConnectionRef.current.setLocalDescription(answer)
      console.log("[v0] Answer created and set as local description")
      return answer
    } catch (error) {
      console.error("[v0] Error creating answer:", error)
      throw error
    }
  }, [])

  const addIceCandidate = useCallback(async (candidate: RTCIceCandidateInit) => {
    if (!peerConnectionRef.current) {
      throw new Error("Peer connection not initialized")
    }

    try {
      await peerConnectionRef.current.addIceCandidate(candidate)
      console.log("[v0] ICE candidate added")
    } catch (error) {
      console.error("[v0] Error adding ICE candidate:", error)
      throw error
    }
  }, [])

  const toggleAudio = useCallback(() => {
    if (localStreamRef.current) {
      const audioTrack = localStreamRef.current.getAudioTracks()[0]
      if (audioTrack) {
        audioTrack.enabled = !audioTrack.enabled
        console.log("[v0] Audio toggled:", audioTrack.enabled)
        return audioTrack.enabled
      }
    }
    return false
  }, [])

  const toggleVideo = useCallback(() => {
    if (localStreamRef.current) {
      const videoTrack = localStreamRef.current.getVideoTracks()[0]
      if (videoTrack) {
        videoTrack.enabled = !videoTrack.enabled
        console.log("[v0] Video toggled:", videoTrack.enabled)
        return videoTrack.enabled
      }
    }
    return false
  }, [])

  const switchCamera = useCallback(async () => {
    if (!localStreamRef.current) return

    try {
      const videoTrack = localStreamRef.current.getVideoTracks()[0]
      if (!videoTrack) return

      // Get current constraints
      const constraints = videoTrack.getConstraints()
      const currentFacingMode = constraints.facingMode

      // Switch between front and back camera
      const newFacingMode = currentFacingMode === "user" ? "environment" : "user"

      const newStream = await navigator.mediaDevices.getUserMedia({
        video: { facingMode: newFacingMode },
        audio: true,
      })

      // Replace video track in peer connection
      const newVideoTrack = newStream.getVideoTracks()[0]
      const sender = peerConnectionRef.current?.getSenders().find((s) => s.track && s.track.kind === "video")

      if (sender) {
        await sender.replaceTrack(newVideoTrack)
      }

      // Stop old track and update stream
      videoTrack.stop()
      localStreamRef.current = newStream

      setState((prev) => ({ ...prev, localStream: newStream }))

      console.log("[v0] Camera switched to:", newFacingMode)
    } catch (error) {
      console.error("[v0] Error switching camera:", error)
    }
  }, [])

  const endCall = useCallback(() => {
    console.log("[v0] Ending call")

    // Stop all tracks
    if (localStreamRef.current) {
      localStreamRef.current.getTracks().forEach((track) => {
        track.stop()
      })
    }

    // Close peer connection
    if (peerConnectionRef.current) {
      peerConnectionRef.current.close()
    }

    // Reset state
    setState({
      isConnected: false,
      isConnecting: false,
      localStream: null,
      remoteStream: null,
      error: null,
    })

    localStreamRef.current = null
    peerConnectionRef.current = null
  }, [])

  const startCall = useCallback(async () => {
    try {
      initializePeerConnection()
      await getUserMedia()
      const offer = await createOffer()
      // In a real app, send offer to remote peer via signaling server
      console.log("[v0] Call started with offer:", offer)
    } catch (error) {
      console.error("[v0] Error starting call:", error)
    }
  }, [initializePeerConnection, getUserMedia, createOffer])

  // Cleanup on unmount
  useEffect(() => {
    return () => {
      endCall()
    }
  }, [endCall])

  return {
    ...state,
    startCall,
    endCall,
    createOffer,
    createAnswer,
    addIceCandidate,
    toggleAudio,
    toggleVideo,
    switchCamera,
  }
}
