import { createContext, useContext, useMemo, type ReactNode } from 'react'
import type { Awareness } from 'y-protocols/awareness'
import type * as Y from 'yjs'
import { useAuth } from '../auth/AuthProvider.tsx'
import { useYDoc } from './useYDoc.ts'
import { useWebSocketProvider } from './useWebSocketProvider.ts'
import { getUserColor, getDisplayName } from './awareness.ts'

interface CollabContextValue {
  ydoc: Y.Doc | null
  ytext: Y.Text | null
  awareness: Awareness | null
  ready: boolean
  connected: boolean
  peerCount: number
  initContent: (content: string) => void
  getContent: () => string
}

const CollabContext = createContext<CollabContextValue | null>(null)

export function useCollab(): CollabContextValue {
  const ctx = useContext(CollabContext)
  if (!ctx) throw new Error('useCollab must be used within CollabProvider')
  return ctx
}

interface CollabProviderProps {
  documentId: string | null
  cloudDocId: string | null
  children: ReactNode
}

export function CollabProvider({ documentId, cloudDocId, children }: CollabProviderProps) {
  const auth = useAuth()
  const { ydoc, ytext, ready, getContent, initContent } = useYDoc(documentId)

  const userName = useMemo(
    () => getDisplayName(auth.user?.email),
    [auth.user?.email],
  )
  const userColor = useMemo(
    () => getUserColor(auth.user?.id ?? 'anon'),
    [auth.user?.id],
  )

  // Only connect WebSocket if authenticated and we have a cloud doc ID
  const roomName = cloudDocId ? `doc:${cloudDocId}` : null
  const token = auth.session?.access_token ?? null

  const { awareness, connected, peerCount } = useWebSocketProvider({
    ydoc,
    roomName,
    token,
    userName,
    userColor,
  })

  return (
    <CollabContext.Provider
      value={{
        ydoc,
        ytext,
        awareness,
        ready,
        connected,
        peerCount,
        initContent,
        getContent,
      }}
    >
      {children}
    </CollabContext.Provider>
  )
}
