import React, { createContext, useContext, useState, useEffect, ReactNode } from 'react';
import { useAuth } from './AuthContext';
import { useUser } from './UserContext';
import { SchoolNeoDBService } from '../services/graph/schoolNeoDBService';
import { CCSchoolNodeProps } from '../utils/tldraw/cc-base/cc-graph/cc-graph-types';
import { logger } from '../debugConfig';

const NEO_INSTITUTE_TIMEOUT_MS = 8000;

export interface NeoInstituteContextType {
    schoolNode: CCSchoolNodeProps | null;
    isLoading: boolean;
    isInitialized: boolean;
    error: string | null;
}

const NeoInstituteContext = createContext<NeoInstituteContextType>({
    schoolNode: null,
    isLoading: true,
    isInitialized: false,
    error: null
});

export const NeoInstituteProvider: React.FC<{ children: ReactNode }> = ({ children }) => {
    const { user } = useAuth();
    const { profile, isInitialized: isUserInitialized } = useUser();

    const [schoolNode, setSchoolNode] = useState<CCSchoolNodeProps | null>(null);
    const [isLoading, setIsLoading] = useState(true);
    const [isInitialized, setIsInitialized] = useState(false);
    const [error, setError] = useState<string | null>(null);

    useEffect(() => {
        logger.debug('neo-institute-context', '🔄 useEffect triggered', {
            isUserInitialized,
            hasProfile: !!profile,
            hasUser: !!user,
            isInitialized
        });

        // Wait for user profile to be ready
        if (!isUserInitialized) {
            logger.debug('neo-institute-context', '⏳ Waiting for user initialization...');
            return;
        }

        // If no profile or no worker database, mark as initialized with no data
        if (!profile || !profile.school_db_name) {
            setIsLoading(false);
            setIsInitialized(true);
            logger.debug('neo-institute-context', 'ℹ️ No school database; marking institute context ready');
            return;
        }

        const loadSchoolNode = async () => {
            try {
                setIsLoading(true);
                logger.debug('neo-institute-context', '🔄 Loading school node', {
                    schoolDbName: profile.school_db_name,
                    userEmail: user?.email
                });

                // Race the Neo4j call against a timeout so a slow/unavailable Neo4j
                // never blocks the workspace from loading for more than 8 seconds.
                const timeoutPromise = new Promise<null>((_, reject) =>
                    setTimeout(() => reject(new Error(`Neo4j timed out after ${NEO_INSTITUTE_TIMEOUT_MS}ms`)), NEO_INSTITUTE_TIMEOUT_MS)
                );

                const node = await Promise.race([
                    SchoolNeoDBService.getSchoolNode(profile.school_db_name),
                    timeoutPromise
                ]);

                if (node) {
                    setSchoolNode(node);
                    logger.debug('neo-institute-context', '✅ School node loaded', {
                        schoolId: node.uuid_string,
                        dbName: profile.school_db_name
                    });
                } else {
                    logger.warn('neo-institute-context', '⚠️ No school node found');
                }

            } catch (error) {
                const errorMessage = error instanceof Error ? error.message : 'Failed to load school node';
                logger.warn('neo-institute-context', '⚠️ School node unavailable — workspace will load without institute data', {
                    error: errorMessage,
                    schoolDbName: profile.school_db_name
                });
                setError(errorMessage);
           } finally {
               setIsLoading(false);
               setIsInitialized(true);
               logger.debug('neo-institute-context', '✅ Institute context initialization complete');
           }
       };

        loadSchoolNode();
    }, [user, profile, isUserInitialized, isInitialized]);

    return (
        <NeoInstituteContext.Provider value={{
            schoolNode,
            isLoading,
            isInitialized,
            error
        }}>
            {children}
        </NeoInstituteContext.Provider>
    );
};

export const useNeoInstitute = () => useContext(NeoInstituteContext);
