import React, { createContext, useContext, ReactNode, useEffect, useState } from 'react';
import { useCollaboration, CollaborationOptions, CollaborationState, CollaborationUser } from '../client/useCollaboration';

interface CollaborationContextValue {
  state: CollaborationState;
  connect: () => void;
  disconnect: () => void;
  updateField: (field: string, value: any) => void;
  updateCursor: (field: string, position: number, selection?: { start: number; end: number }) => void;
  updateAwareness: (awareness: any) => void;
  getValue: (field: string) => any;
  activeUsers: CollaborationUser[];
  isConnected: boolean;
  hasUnsavedChanges: boolean;
  documentId: string;
  documentType: 'task' | 'project';
}

const CollaborationContext = createContext<CollaborationContextValue | null>(null);

interface CollaborationProviderProps {
  children: ReactNode;
  options: CollaborationOptions;
}

/**
 * Collaboration Provider Component
 * Provides collaboration context to child components
 */
export const CollaborationProvider: React.FC<CollaborationProviderProps> = ({
  children,
  options
}) => {
  const collaboration = useCollaboration(options);
  const [awareness, setAwareness] = useState<Map<string, any>>(new Map());

  // Track user awareness updates
  useEffect(() => {
    if (options.onAwarenessUpdate) {
      const originalHandler = options.onAwarenessUpdate;
      options.onAwarenessUpdate = (userId: string, awarenessData: any) => {
        setAwareness(prev => {
          const updated = new Map(prev);
          updated.set(userId, awarenessData);
          return updated;
        });
        originalHandler(userId, awarenessData);
      };
    }
  }, []);

  // Broadcast section awareness when user navigates
  const updateSectionAwareness = (section: string, activity: 'viewing' | 'editing' | 'commenting') => {
    collaboration.updateAwareness({
      section,
      activity,
      timestamp: new Date().toISOString()
    });
  };

  // Enhanced context value with awareness helpers
  const contextValue: CollaborationContextValue = {
    ...collaboration,
    documentId: options.documentId,
    documentType: options.documentType
  };

  return (
    <CollaborationContext.Provider value={contextValue}>
      {children}
    </CollaborationContext.Provider>
  );
};

/**
 * Hook to use collaboration context
 */
export const useCollaborationContext = () => {
  const context = useContext(CollaborationContext);
  if (!context) {
    throw new Error('useCollaborationContext must be used within CollaborationProvider');
  }
  return context;
};

/**
 * HOC to inject collaboration props
 */
export function withCollaboration<P extends object>(
  Component: React.ComponentType<P & CollaborationContextValue>
): React.FC<P> {
  return (props: P) => {
    const collaboration = useCollaborationContext();
    return <Component {...props} {...collaboration} />;
  };
}

/**
 * Collaboration-aware section component
 */
interface CollaborativeSectionProps {
  sectionId: string;
  children: ReactNode;
  trackActivity?: boolean;
  className?: string;
}

export const CollaborativeSection: React.FC<CollaborativeSectionProps> = ({
  sectionId,
  children,
  trackActivity = true,
  className = ''
}) => {
  const { updateAwareness } = useCollaborationContext();
  const [isInView, setIsInView] = useState(false);

  useEffect(() => {
    if (!trackActivity) return;

    const observer = new IntersectionObserver(
      ([entry]) => {
        setIsInView(entry.isIntersecting);
        if (entry.isIntersecting) {
          updateAwareness({
            section: sectionId,
            activity: 'viewing',
            timestamp: new Date().toISOString()
          });
        }
      },
      { threshold: 0.5 }
    );

    const element = document.getElementById(sectionId);
    if (element) {
      observer.observe(element);
    }

    return () => {
      if (element) {
        observer.unobserve(element);
      }
    };
  }, [sectionId, trackActivity, updateAwareness]);

  return (
    <div 
      id={sectionId}
      className={`collaborative-section ${className} ${isInView ? 'in-view' : ''}`}
      data-section={sectionId}
    >
      {children}
    </div>
  );
};