import { useCallback, useState, ReactNode, useMemo } from 'react';
import { createContext, useContextSelector } from 'use-context-selector';

export interface ProposeChangesDecision {
    approved: boolean;
    user_reason?: string;
}

interface UIContextProps {
    isMobileSidebarOpen: boolean;
    setIsMobileSidebarOpen: React.Dispatch<React.SetStateAction<boolean>>;
    isLoginModalOpen: boolean;
    setIsLoginModalOpen: React.Dispatch<React.SetStateAction<boolean>>;
    isRateLimitModalOpen: boolean;
    setIsRateLimitModalOpen: React.Dispatch<React.SetStateAction<boolean>>;
    isUpgradeModalOpen: boolean;
    setIsUpgradeModalOpen: React.Dispatch<React.SetStateAction<boolean>>;
    isWorkflowsModalOpen: boolean;
    setIsWorkflowsModalOpen: React.Dispatch<React.SetStateAction<boolean>>;
    isSettingsModalOpen: boolean;
    setIsSettingsModalOpen: React.Dispatch<React.SetStateAction<boolean>>;
    isConfirmDeleteModalOpen: boolean;
    setIsConfirmDeleteModalOpen: React.Dispatch<React.SetStateAction<boolean>>;
    confirmDeleteConversationName: string | null;
    setConfirmDeleteConversationName: React.Dispatch<React.SetStateAction<string | null>>;
    confirmDeleteConversationId: string | null;
    setConfirmDeleteConversationId: React.Dispatch<React.SetStateAction<string | null>>;
    // Propose Changes modal
    isProposeChangesModalOpen: boolean;
    setIsProposeChangesModalOpen: React.Dispatch<React.SetStateAction<boolean>>;
    proposeChangesRequest: any | null;
    setProposeChangesRequest: React.Dispatch<React.SetStateAction<any | null>>;
    openProposeChanges: (request: any) => Promise<ProposeChangesDecision>;
    resolveProposeChanges: (decision: ProposeChangesDecision) => void;
}

const defaultContextValue: UIContextProps = {
    isMobileSidebarOpen: false,
    setIsMobileSidebarOpen: () => {},
    isLoginModalOpen: false,
    setIsLoginModalOpen: () => {},
    isRateLimitModalOpen: false,
    setIsRateLimitModalOpen: () => {},
    isUpgradeModalOpen: false,
    setIsUpgradeModalOpen: () => {},
    isWorkflowsModalOpen: false,
    setIsWorkflowsModalOpen: () => {},
    isSettingsModalOpen: false,
    setIsSettingsModalOpen: () => {},
    isConfirmDeleteModalOpen: false,
    setIsConfirmDeleteModalOpen: () => {},
    confirmDeleteConversationName: null,
    setConfirmDeleteConversationName: () => {},
    confirmDeleteConversationId: null,
    setConfirmDeleteConversationId: () => {},
    isProposeChangesModalOpen: false,
    setIsProposeChangesModalOpen: () => {},
    proposeChangesRequest: null,
    setProposeChangesRequest: () => {},
    openProposeChanges: async () => ({ approved: false }),
    resolveProposeChanges: () => {},
};

const UIContext = createContext<UIContextProps>(defaultContextValue);

interface UIProviderProps {
  children: ReactNode;
}

export const UIProvider = ({ children }: UIProviderProps): JSX.Element => {
    const [isMobileSidebarOpen, setIsMobileSidebarOpen] = useState(false);
    const [isLoginModalOpen, setIsLoginModalOpen] = useState(false);
    const [isRateLimitModalOpen, setIsRateLimitModalOpen] = useState(false);
    const [isUpgradeModalOpen, setIsUpgradeModalOpen] = useState(false);
    const [isWorkflowsModalOpen, setIsWorkflowsModalOpen] = useState(false);
    const [isSettingsModalOpen, setIsSettingsModalOpen] = useState(false);
    const [isConfirmDeleteModalOpen, setIsConfirmDeleteModalOpen] = useState(false);
    const [confirmDeleteConversationName, setConfirmDeleteConversationName] = useState<string | null>(null);
    const [confirmDeleteConversationId, setConfirmDeleteConversationId] = useState<string | null>(null);
    const [isProposeChangesModalOpen, setIsProposeChangesModalOpen] = useState(false);
    const [proposeChangesRequest, setProposeChangesRequest] = useState<any | null>(null);
    const [resolver, setResolver] = useState<((value: ProposeChangesDecision) => void) | null>(null);

    const openProposeChanges = useCallback((request: any) => {
        setProposeChangesRequest(request);
        setIsProposeChangesModalOpen(true);
        return new Promise<ProposeChangesDecision>((resolve) => {
            setResolver(() => resolve);
        });
    }, []);

    const resolveProposeChanges = useCallback((decision: ProposeChangesDecision) => {
        if (resolver) {
            resolver(decision);
            setResolver(null);
        }
        setIsProposeChangesModalOpen(false);
        setProposeChangesRequest(null);
    }, [resolver]);

    const contextValue = useMemo(() => ({
        isMobileSidebarOpen,
        setIsMobileSidebarOpen,
        isLoginModalOpen,
        setIsLoginModalOpen,
        isRateLimitModalOpen,
        setIsRateLimitModalOpen,
        isUpgradeModalOpen,
        setIsUpgradeModalOpen,
        isWorkflowsModalOpen,
        setIsWorkflowsModalOpen,
        isSettingsModalOpen,
        setIsSettingsModalOpen,
        isConfirmDeleteModalOpen,
        setIsConfirmDeleteModalOpen,
        confirmDeleteConversationName,
        setConfirmDeleteConversationName,
        confirmDeleteConversationId,
        setConfirmDeleteConversationId,
        isProposeChangesModalOpen,
        setIsProposeChangesModalOpen,
        proposeChangesRequest,
        setProposeChangesRequest,
        openProposeChanges,
        resolveProposeChanges,
    }), [
        isMobileSidebarOpen,
        isLoginModalOpen,
        isRateLimitModalOpen,
        isUpgradeModalOpen,
        isWorkflowsModalOpen,
        isSettingsModalOpen,
        isConfirmDeleteModalOpen,
        confirmDeleteConversationName,
        confirmDeleteConversationId,
        isProposeChangesModalOpen,
        proposeChangesRequest,
        openProposeChanges,
        resolveProposeChanges,
    ]);

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

// Selector Hook
export const useUISelector = <T,>(selector: (state: UIContextProps) => T): T => {
  return useContextSelector(UIContext, selector);
};

export const useIsMobileSidebarOpen = () => {
  return useUISelector(state => state.isMobileSidebarOpen);
};

export const useIsLoginModalOpen = () => {
  return useUISelector(state => state.isLoginModalOpen);
};

export const useIsRateLimitModalOpen = () => {
  return useUISelector(state => state.isRateLimitModalOpen);
};

export const useIsUpgradeModalOpen = () => {
  return useUISelector(state => state.isUpgradeModalOpen);
};

export const useIsWorkflowsModalOpen = () => {
  return useUISelector(state => state.isWorkflowsModalOpen);
};

export const useIsSettingsModalOpen = () => {
  return useUISelector(state => state.isSettingsModalOpen);
};

export const useIsConfirmDeleteModalOpen = () => {
  return useUISelector(state => state.isConfirmDeleteModalOpen);
};

export const useConfirmDeleteConversationName = () => {
  return useUISelector(state => state.confirmDeleteConversationName);
};

export const useConfirmDeleteConversationId = () => {
  return useUISelector(state => state.confirmDeleteConversationId);
};

// Individual Selector Hooks for Setter Functions
export const useSetIsMobileSidebarOpen = () => {
  return useUISelector(state => state.setIsMobileSidebarOpen);
};

export const useSetIsLoginModalOpen = () => {
  return useUISelector(state => state.setIsLoginModalOpen);
};

export const useSetIsRateLimitModalOpen = () => {
  return useUISelector(state => state.setIsRateLimitModalOpen);
};

export const useSetIsUpgradeModalOpen = () => {
  return useUISelector(state => state.setIsUpgradeModalOpen);
};

export const useSetIsWorkflowsModalOpen = () => {
  return useUISelector(state => state.setIsWorkflowsModalOpen);
};

export const useSetIsSettingsModalOpen = () => {
  return useUISelector(state => state.setIsSettingsModalOpen);
};

export const useSetIsConfirmDeleteModalOpen = () => {
  return useUISelector(state => state.setIsConfirmDeleteModalOpen);
};

export const useSetConfirmDeleteConversationName = () => {
  return useUISelector(state => state.setConfirmDeleteConversationName);
};

export const useSetConfirmDeleteConversationId = () => {
  return useUISelector(state => state.setConfirmDeleteConversationId);
};

export const useIsProposeChangesModalOpen = () => {
  return useUISelector(state => state.isProposeChangesModalOpen);
};

export const useSetIsProposeChangesModalOpen = () => {
  return useUISelector(state => state.setIsProposeChangesModalOpen);
};

export const useProposeChangesRequest = () => {
  return useUISelector(state => state.proposeChangesRequest);
};

export const useSetProposeChangesRequest = () => {
  return useUISelector(state => state.setProposeChangesRequest);
};

export const useOpenProposeChanges = () => {
  return useUISelector(state => state.openProposeChanges);
};
