import { useState, useEffect, useCallback, useMemo } from 'react';
import * as Y from 'yjs';
import { HocuspocusProvider } from '@hocuspocus/provider';
import type { Collaborator, UseDocsCollaborationReturn } from '@/hooks/useDocsCollaboration';

/**
 * A variant of useDocsCollaboration for share-link guests.
 * Uses a collabToken (short-lived JWT) instead of the auth store token,
 * and sets awareness with the provided guestIdentity.
 */
export function useDocShareCollaboration(
  filePath: string | null,
  enabled: boolean,
  collabToken: string | null,
  guestIdentity: { id: string; name: string; color: string } | null,
): UseDocsCollaborationReturn {
  const [connected, setConnected] = useState(false);
  const [synced, setSynced] = useState(false);
  const [collaborators, setCollaborators] = useState<Collaborator[]>([]);

  const [collabState, setCollabState] = useState<{
    yDoc: Y.Doc;
    yText: Y.Text;
    provider: HocuspocusProvider;
  } | null>(null);

  // Build WebSocket URL
  const wsUrl = useMemo(() => {
    if (!filePath || !enabled || !collabToken) return null;
    const protocol = window.location.protocol === 'https:' ? 'wss:' : 'ws:';
    return `${protocol}//${window.location.host}/api/docs/collaborate`;
  }, [filePath, enabled, collabToken]);

  // Cleanup function
  const cleanup = useCallback(() => {
    setCollabState((prev) => {
      if (prev) {
        prev.provider.disconnect();
        prev.provider.destroy();
        prev.yDoc.destroy();
      }
      return null;
    });
    setConnected(false);
    setSynced(false);
    setCollaborators([]);
  }, []);

  useEffect(() => {
    if (!wsUrl || !filePath || !enabled || !collabToken || !guestIdentity) {
      cleanup();
      return;
    }

    // Create new Y.Doc and provider
    const doc = new Y.Doc();
    const yText = doc.getText('content');

    const provider = new HocuspocusProvider({
      url: wsUrl,
      name: filePath,
      document: doc,
      token: collabToken,
      onConnect: () => setConnected(true),
      onDisconnect: () => {
        setConnected(false);
        setSynced(false);
      },
      onSynced: () => setSynced(true),
    });

    // Set local awareness state with guest identity
    provider.setAwarenessField('user', {
      id: guestIdentity.id,
      name: guestIdentity.name,
      color: guestIdentity.color,
    });

    // Track collaborators via awareness changes
    const handleAwarenessChange = () => {
      const states = provider.awareness?.getStates();
      if (!states) return;
      const collab: Collaborator[] = [];
      states.forEach((state, clientId) => {
        const u = state.user as { id: string; name: string; color: string } | undefined;
        if (u && u.id !== guestIdentity.id) {
          collab.push({ id: u.id, name: u.name, color: u.color, clientId });
        }
      });
      setCollaborators(collab);
    };
    provider.awareness?.on('change', handleAwarenessChange);

    // Set state LAST so the component re-renders with everything ready
    setCollabState({ yDoc: doc, yText, provider });

    return () => {
      provider.awareness?.off('change', handleAwarenessChange);
      provider.disconnect();
      provider.destroy();
      doc.destroy();
      setCollabState(null);
      setConnected(false);
      setSynced(false);
      setCollaborators([]);
    };
    // We intentionally only recreate when these core values change
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [wsUrl, filePath, enabled, collabToken, guestIdentity?.id]);

  return {
    yDoc: collabState?.yDoc ?? null,
    yText: collabState?.yText ?? null,
    provider: collabState?.provider ?? null,
    connected,
    synced,
    collaborators,
    active: enabled && !!collabState && synced && !!filePath,
  };
}
