import {
  createContext,
  type ReactNode,
  useCallback,
  useContext,
  useEffect,
  useMemo,
  useState,
  useTransition,
} from 'react';
import {projectInfo, type ProjectInfoRelational,} from '@/client';

interface ProjectContextValue {
    project: ProjectInfoRelational | null;
    projectName: string | null;
    isLoading: boolean;
    error: Error | null;
    refetch: () => Promise<void>;
}

const ProjectContext = createContext<ProjectContextValue | null>(null);

interface ProjectProviderProps {
    projectName: string | null;
    children: ReactNode;
}

export function ProjectProvider({projectName, children}: ProjectProviderProps) {
    const [project, setProject] = useState<ProjectInfoRelational | null>(null);
    const [error, setError] = useState<Error | null>(null);
    const [isLoading, setIsLoading] = useState(false);
    const [isPending, startTransition] = useTransition();

    const fetchProject = useCallback(async () => {
        if (!projectName) {
            setProject(null);
            setError(null);
            return;
        }
        setIsLoading(true);
        setError(null);
        try {
            const resp = await projectInfo({ path: { project_name: projectName } });
            setProject(resp.data?.data ?? null);
        } catch (err) {
            setProject(null);
            setError(err instanceof Error ? err : new Error('Failed to load project'));
        } finally {
            setIsLoading(false);
        }
    }, [projectName]);

    useEffect(() => {
        fetchProject();
        // eslint-disable-next-line react-hooks/exhaustive-deps
    }, [fetchProject]);

    const refetch = useCallback(async () => {
        startTransition(async () => {
            await fetchProject();
        });
    }, [fetchProject]);

    const value = useMemo<ProjectContextValue>(() => ({
        project,
        projectName,
        isLoading: isLoading || isPending,
        error,
        refetch,
    }), [project, projectName, isLoading, isPending, error, refetch]);

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

export function useProject() {
    const ctx = useContext(ProjectContext);
    if (!ctx) throw new Error('useProject must be used within ProjectProvider');
    return ctx;
}
