"use client";

import React, {
  createContext,
  useContext,
  useReducer,
  useEffect,
  useRef,
  ReactNode,
  useCallback,
} from "react";

// Enums for better type safety
export enum ChatbotStatus {
  IDLE = "idle",
  LOADING = "loading",
  READY = "ready",
  ERROR = "error",
  DISCONNECTED = "disconnected",
}

export enum VectorStoreType {
  QDRANT = "qdrant",
  PINECONE = "pinecone",
  SUPABASE = "supabase",
}

export enum LLMProvider {
  OPENAI = "openai",
  ANTHROPIC = "anthropic",
  GOOGLE = "google",
  MISTRAL = "mistral",
}

// Core interfaces
export interface ChatbotError {
  code: string;
  message: string;
  details?: any;
  timestamp: Date;
}

export interface VectorStoreConfig {
  type: VectorStoreType;
  url?: string;
  apiKey?: string;
  collection?: string;
  dimensions?: number;
  similarity?: "cosine" | "euclidean" | "dot";
  namespace?: string;
}

export interface LLMConfig {
  provider: LLMProvider;
  model: string;
  apiKey?: string;
  temperature?: number;
  maxTokens?: number;
  topP?: number;
  frequencyPenalty?: number;
  presencePenalty?: number;
  systemPrompt?: string;
}

export interface StorageConfig {
  bucket: string;
  url?: string;
  apiKey?: string;
  maxFileSize?: number;
  allowedTypes?: string[];
}

export interface ChatbotConfig {
  systemPrompt: string;
  welcomeMessage: string;
  suggestedQuestions: string[];
  maxConversationHistory: number;
  enableRAG: boolean;
  ragSettings: {
    similarityThreshold: number;
    maxRetrievedDocs: number;
    chunkSize: number;
    chunkOverlap: number;
  };
  uiSettings: {
    theme: string;
    language: string;
    showTimestamps: boolean;
    enableTypingIndicator: boolean;
  };
}

export interface Document {
  id: string;
  title: string;
  content: string;
  metadata: {
    source?: string;
    uploadedAt: Date;
    size: number;
    type: string;
    description?: string;
    tags?: string[];
  };
  embedding?: number[];
  status: "processing" | "ready" | "error";
}

export interface ConversationMessage {
  id: string;
  content: string;
  role: "user" | "assistant" | "system";
  timestamp: Date;
  metadata?: {
    retrievedDocs?: Document[];
    confidence?: number;
    tokens?: number;
  };
}

export interface Conversation {
  id: string;
  title?: string;
  messages: ConversationMessage[];
  createdAt: Date;
  updatedAt: Date;
  metadata?: {
    userId?: string;
    sessionId?: string;
    tags?: string[];
  };
}

// State interfaces
export interface VectorStoreState {
  status: ChatbotStatus;
  isConnected: boolean;
  config: VectorStoreConfig | null;
  error: ChatbotError | null;
  collections: string[];
  documentCount: number;
}

export interface LLMState {
  status: ChatbotStatus;
  isConnected: boolean;
  config: LLMConfig | null;
  error: ChatbotError | null;
  availableModels: string[];
  currentModel: string | null;
}

export interface StorageState {
  status: ChatbotStatus;
  isConnected: boolean;
  config: StorageConfig | null;
  error: ChatbotError | null;
  uploadProgress: { [fileId: string]: number };
}

export interface ChatbotContextState {
  // Overall system state
  isInitialized: boolean;
  globalStatus: ChatbotStatus;
  initializationProgress: number;

  // Subsystem states
  vectorStore: VectorStoreState;
  llm: LLMState;
  storage: StorageState;

  // Configuration
  config: ChatbotConfig;

  // Data
  documents: Document[];
  conversations: Conversation[];
  currentConversation: Conversation | null;

  // UI state
  isProcessing: boolean;
  lastError: ChatbotError | null;
}

// Action types
export type ChatbotAction =
  | { type: "INITIALIZE_START" }
  | { type: "INITIALIZE_SUCCESS" }
  | { type: "INITIALIZE_ERROR"; payload: ChatbotError }
  | { type: "SET_INITIALIZATION_PROGRESS"; payload: number }

  // Vector store actions
  | { type: "VECTOR_STORE_CONNECTING" }
  | {
      type: "VECTOR_STORE_CONNECTED";
      payload: { collections: string[]; documentCount: number };
    }
  | { type: "VECTOR_STORE_ERROR"; payload: ChatbotError }
  | { type: "VECTOR_STORE_CONFIG_UPDATE"; payload: Partial<VectorStoreConfig> }

  // LLM actions
  | { type: "LLM_CONNECTING" }
  | {
      type: "LLM_CONNECTED";
      payload: { availableModels: string[]; currentModel: string };
    }
  | { type: "LLM_ERROR"; payload: ChatbotError }
  | { type: "LLM_CONFIG_UPDATE"; payload: Partial<LLMConfig> }

  // Storage actions
  | { type: "STORAGE_CONNECTING" }
  | { type: "STORAGE_CONNECTED" }
  | { type: "STORAGE_ERROR"; payload: ChatbotError }
  | {
      type: "STORAGE_UPLOAD_PROGRESS";
      payload: { fileId: string; progress: number };
    }
  | { type: "STORAGE_CONFIG_UPDATE"; payload: Partial<StorageConfig> }

  // Configuration actions
  | { type: "CONFIG_UPDATE"; payload: Partial<ChatbotConfig> }

  // Document actions
  | { type: "DOCUMENTS_SET"; payload: Document[] }
  | { type: "DOCUMENT_ADD"; payload: Document }
  | {
      type: "DOCUMENT_UPDATE";
      payload: { id: string; updates: Partial<Document> };
    }
  | { type: "DOCUMENT_REMOVE"; payload: string }

  // Conversation actions
  | { type: "CONVERSATIONS_SET"; payload: Conversation[] }
  | { type: "CONVERSATION_START"; payload: Conversation }
  | { type: "CONVERSATION_SELECT"; payload: string }
  | {
      type: "CONVERSATION_MESSAGE_ADD";
      payload: { conversationId: string; message: ConversationMessage };
    }

  // UI actions
  | { type: "SET_PROCESSING"; payload: boolean }
  | { type: "CLEAR_ERROR" }
  | { type: "SET_ERROR"; payload: ChatbotError };

// Context methods interface
export interface ChatbotContextMethods {
  // Initialization
  initialize: () => Promise<void>;
  reset: () => Promise<void>;

  // Vector store operations
  initializeVectorStore: (config: VectorStoreConfig) => Promise<void>;
  addDocuments: (documents: Document[]) => Promise<void>;
  removeDocuments: (documentIds: string[]) => Promise<void>;
  searchSimilarDocuments: (
    query: string,
    limit?: number
  ) => Promise<Document[]>;

  // LLM operations
  initializeLLM: (config: LLMConfig) => Promise<void>;
  generateResponse: (prompt: string, context?: Document[]) => Promise<string>;
  generateRAGResponse: (
    query: string
  ) => Promise<{ response: string; sources: Document[] }>;

  // Storage operations
  initializeStorage: (config: StorageConfig) => Promise<void>;
  uploadDocument: (
    file: File,
    metadata?: Partial<Document["metadata"]>
  ) => Promise<Document>;
  downloadDocument: (documentId: string) => Promise<Blob>;
  deleteDocument: (documentId: string) => Promise<void>;
  listDocuments: () => Promise<Document[]>;

  // Configuration management
  updateConfig: (updates: Partial<ChatbotConfig>) => Promise<void>;
  exportConfig: () => ChatbotConfig;
  importConfig: (config: ChatbotConfig) => Promise<void>;

  // Conversation management
  startConversation: (title?: string) => Promise<Conversation>;
  selectConversation: (conversationId: string) => Promise<void>;
  sendMessage: (content: string) => Promise<ConversationMessage>;
  getConversationHistory: (
    conversationId?: string
  ) => Promise<ConversationMessage[]>;
  deleteConversation: (conversationId: string) => Promise<void>;

  // Utility methods
  getStatus: () => {
    overall: ChatbotStatus;
    subsystems: {
      vectorStore: ChatbotStatus;
      llm: ChatbotStatus;
      storage: ChatbotStatus;
    };
  };
  clearError: () => void;
  healthCheck: () => Promise<{
    vectorStore: boolean;
    llm: boolean;
    storage: boolean;
  }>;
}

// Combined context type
export type ChatbotContextType = ChatbotContextState & ChatbotContextMethods;

// Default configuration
export const defaultChatbotConfig: ChatbotConfig = {
  systemPrompt:
    "You are a helpful AI assistant with access to a knowledge base. Use the provided context to answer questions accurately and helpfully.",
  welcomeMessage:
    "Hello! I'm here to help you find information. What would you like to know?",
  suggestedQuestions: [
    "What can you help me with?",
    "How does this system work?",
    "Tell me about your capabilities",
  ],
  maxConversationHistory: 10,
  enableRAG: true,
  ragSettings: {
    similarityThreshold: 0.7,
    maxRetrievedDocs: 5,
    chunkSize: 1000,
    chunkOverlap: 200,
  },
  uiSettings: {
    theme: "default",
    language: "en",
    showTimestamps: true,
    enableTypingIndicator: true,
  },
};

// Initial state
const initialState: ChatbotContextState = {
  isInitialized: false,
  globalStatus: ChatbotStatus.IDLE,
  initializationProgress: 0,

  vectorStore: {
    status: ChatbotStatus.IDLE,
    isConnected: false,
    config: null,
    error: null,
    collections: [],
    documentCount: 0,
  },

  llm: {
    status: ChatbotStatus.IDLE,
    isConnected: false,
    config: null,
    error: null,
    availableModels: [],
    currentModel: null,
  },

  storage: {
    status: ChatbotStatus.IDLE,
    isConnected: false,
    config: null,
    error: null,
    uploadProgress: {},
  },

  config: defaultChatbotConfig,
  documents: [],
  conversations: [],
  currentConversation: null,
  isProcessing: false,
  lastError: null,
};

// Reducer function
export function chatbotReducer(
  state: ChatbotContextState,
  action: ChatbotAction
): ChatbotContextState {
  switch (action.type) {
    case "INITIALIZE_START":
      return {
        ...state,
        globalStatus: ChatbotStatus.LOADING,
        initializationProgress: 0,
        lastError: null,
      };

    case "INITIALIZE_SUCCESS":
      return {
        ...state,
        isInitialized: true,
        globalStatus: ChatbotStatus.READY,
        initializationProgress: 100,
      };

    case "INITIALIZE_ERROR":
      return {
        ...state,
        globalStatus: ChatbotStatus.ERROR,
        lastError: action.payload,
      };

    case "SET_INITIALIZATION_PROGRESS":
      return {
        ...state,
        initializationProgress: action.payload,
      };

    // Vector store cases
    case "VECTOR_STORE_CONNECTING":
      return {
        ...state,
        vectorStore: {
          ...state.vectorStore,
          status: ChatbotStatus.LOADING,
          error: null,
        },
      };

    case "VECTOR_STORE_CONNECTED":
      return {
        ...state,
        vectorStore: {
          ...state.vectorStore,
          status: ChatbotStatus.READY,
          isConnected: true,
          collections: action.payload.collections,
          documentCount: action.payload.documentCount,
        },
      };

    case "VECTOR_STORE_ERROR":
      return {
        ...state,
        vectorStore: {
          ...state.vectorStore,
          status: ChatbotStatus.ERROR,
          isConnected: false,
          error: action.payload,
        },
      };

    case "VECTOR_STORE_CONFIG_UPDATE":
      return {
        ...state,
        vectorStore: {
          ...state.vectorStore,
          config: state.vectorStore.config
            ? { ...state.vectorStore.config, ...action.payload }
            : null,
        },
      };

    // LLM cases
    case "LLM_CONNECTING":
      return {
        ...state,
        llm: {
          ...state.llm,
          status: ChatbotStatus.LOADING,
          error: null,
        },
      };

    case "LLM_CONNECTED":
      return {
        ...state,
        llm: {
          ...state.llm,
          status: ChatbotStatus.READY,
          isConnected: true,
          availableModels: action.payload.availableModels,
          currentModel: action.payload.currentModel,
        },
      };

    case "LLM_ERROR":
      return {
        ...state,
        llm: {
          ...state.llm,
          status: ChatbotStatus.ERROR,
          isConnected: false,
          error: action.payload,
        },
      };

    case "LLM_CONFIG_UPDATE":
      return {
        ...state,
        llm: {
          ...state.llm,
          config: state.llm.config
            ? { ...state.llm.config, ...action.payload }
            : null,
        },
      };

    // Storage cases
    case "STORAGE_CONNECTING":
      return {
        ...state,
        storage: {
          ...state.storage,
          status: ChatbotStatus.LOADING,
          error: null,
        },
      };

    case "STORAGE_CONNECTED":
      return {
        ...state,
        storage: {
          ...state.storage,
          status: ChatbotStatus.READY,
          isConnected: true,
        },
      };

    case "STORAGE_ERROR":
      return {
        ...state,
        storage: {
          ...state.storage,
          status: ChatbotStatus.ERROR,
          isConnected: false,
          error: action.payload,
        },
      };

    case "STORAGE_UPLOAD_PROGRESS":
      return {
        ...state,
        storage: {
          ...state.storage,
          uploadProgress: {
            ...state.storage.uploadProgress,
            [action.payload.fileId]: action.payload.progress,
          },
        },
      };

    case "STORAGE_CONFIG_UPDATE":
      return {
        ...state,
        storage: {
          ...state.storage,
          config: state.storage.config
            ? { ...state.storage.config, ...action.payload }
            : null,
        },
      };

    // Configuration cases
    case "CONFIG_UPDATE":
      return {
        ...state,
        config: { ...state.config, ...action.payload },
      };

    // Document cases
    case "DOCUMENTS_SET":
      return {
        ...state,
        documents: action.payload,
      };

    case "DOCUMENT_ADD":
      return {
        ...state,
        documents: [...state.documents, action.payload],
      };

    case "DOCUMENT_UPDATE":
      return {
        ...state,
        documents: state.documents.map((doc) =>
          doc.id === action.payload.id
            ? { ...doc, ...action.payload.updates }
            : doc
        ),
      };

    case "DOCUMENT_REMOVE":
      return {
        ...state,
        documents: state.documents.filter((doc) => doc.id !== action.payload),
      };

    // Conversation cases
    case "CONVERSATIONS_SET":
      return {
        ...state,
        conversations: action.payload,
      };

    case "CONVERSATION_START":
      return {
        ...state,
        conversations: [action.payload, ...state.conversations],
        currentConversation: action.payload,
      };

    case "CONVERSATION_SELECT":
      return {
        ...state,
        currentConversation:
          state.conversations.find((c) => c.id === action.payload) || null,
      };

    case "CONVERSATION_MESSAGE_ADD":
      const updatedConversations = state.conversations.map((conv) =>
        conv.id === action.payload.conversationId
          ? {
              ...conv,
              messages: [...conv.messages, action.payload.message],
              updatedAt: new Date(),
            }
          : conv
      );

      return {
        ...state,
        conversations: updatedConversations,
        currentConversation:
          state.currentConversation?.id === action.payload.conversationId
            ? updatedConversations.find(
                (c) => c.id === action.payload.conversationId
              ) || null
            : state.currentConversation,
      };

    // UI cases
    case "SET_PROCESSING":
      return {
        ...state,
        isProcessing: action.payload,
      };

    case "CLEAR_ERROR":
      return {
        ...state,
        lastError: null,
      };

    case "SET_ERROR":
      return {
        ...state,
        lastError: action.payload,
      };

    default:
      return state;
  }
}

// Create context
export const ChatbotContext = createContext<ChatbotContextType | undefined>(
  undefined
);

// Provider props
export interface ChatbotProviderProps {
  children: ReactNode;
  initialConfig?: Partial<ChatbotConfig>;
  autoInitialize?: boolean;
}

// Custom hook for consuming context
export function useChatbot(): ChatbotContextType {
  const context = useContext(ChatbotContext);
  if (context === undefined) {
    throw new Error("useChatbot must be used within a ChatbotProvider");
  }
  return context;
}

// Provider component (basic structure - will be implemented in subsequent subtasks)
export function ChatbotProvider({
  children,
  initialConfig = {},
  autoInitialize = false,
}: ChatbotProviderProps) {
  const [state, dispatch] = useReducer(chatbotReducer, {
    ...initialState,
    config: { ...defaultChatbotConfig, ...initialConfig },
  });

  // Vector store instance reference
  const vectorStoreRef = useRef<any>(null);
  // LLM instance reference
  const llmRef = useRef<any>(null);
  // RAG chain instance reference
  const ragChainRef = useRef<any>(null);
  // Storage instance reference
  const storageRef = useRef<any>(null);

  // Initialization methods
  const initialize = useCallback(async () => {
    dispatch({ type: "INITIALIZE_START" });
    dispatch({ type: "SET_INITIALIZATION_PROGRESS", payload: 0 });

    try {
      // Clear any previous errors
      dispatch({ type: "CLEAR_ERROR" });

      // Initialize based on configuration
      const config = state.config;
      let initProgress = 10;

      // Step 1: Initialize Vector Store (if enabled)
      if (config.enableRAG) {
        try {
          // Check if we have vector store configuration
          const vectorStoreConfig = state.vectorStore.config;
          if (vectorStoreConfig) {
            await initializeVectorStore(vectorStoreConfig);
            initProgress = 40;
          } else {
            console.warn(
              "RAG is enabled but no vector store configuration found"
            );
          }
        } catch (error) {
          console.warn("Failed to initialize vector store:", error);
          // Continue with other initializations
        }
      }

      dispatch({ type: "SET_INITIALIZATION_PROGRESS", payload: initProgress });

      // Step 2: Initialize LLM (required for basic functionality)
      try {
        const llmConfig = state.llm.config;
        if (llmConfig) {
          await initializeLLM(llmConfig);
          initProgress = Math.max(initProgress, 80);
        } else {
          throw new Error("LLM configuration is required");
        }
      } catch (error) {
        console.error("Failed to initialize LLM:", error);
        throw error; // LLM is required, so fail initialization
      }

      dispatch({ type: "SET_INITIALIZATION_PROGRESS", payload: initProgress });

      // Step 3: Initialize Storage (optional)
      try {
        const storageConfig = state.storage.config;
        if (storageConfig) {
          await initializeStorage(storageConfig);
          initProgress = 100;
        } else {
          console.warn(
            "No storage configuration found, skipping storage initialization"
          );
          initProgress = 100;
        }
      } catch (error) {
        console.warn("Failed to initialize storage:", error);
        // Storage is optional, continue
        initProgress = 100;
      }

      dispatch({ type: "SET_INITIALIZATION_PROGRESS", payload: initProgress });
      dispatch({ type: "INITIALIZE_SUCCESS" });
    } catch (error) {
      const chatbotError: ChatbotError = {
        code: "INITIALIZATION_ERROR",
        message: `Failed to initialize chatbot: ${
          error instanceof Error ? error.message : "Unknown error"
        }`,
        details: error,
        timestamp: new Date(),
      };

      dispatch({ type: "INITIALIZE_ERROR", payload: chatbotError });
      dispatch({ type: "SET_ERROR", payload: chatbotError });
      throw error;
    }
  }, [
    state.config,
    state.vectorStore.config,
    state.llm.config,
    state.storage.config,
  ]);

  const reset = useCallback(async () => {
    try {
      dispatch({ type: "SET_PROCESSING", payload: true });

      // Disconnect and clear all subsystems
      if (vectorStoreRef.current) {
        try {
          await vectorStoreRef.current.disconnect();
        } catch (error) {
          console.warn("Failed to disconnect vector store:", error);
        }
        vectorStoreRef.current = null;
      }

      if (llmRef.current) {
        try {
          await llmRef.current.disconnect();
        } catch (error) {
          console.warn("Failed to disconnect LLM:", error);
        }
        llmRef.current = null;
      }

      if (ragChainRef.current) {
        ragChainRef.current = null;
      }

      if (storageRef.current) {
        try {
          await storageRef.current.disconnect();
        } catch (error) {
          console.warn("Failed to disconnect storage:", error);
        }
        storageRef.current = null;
      }

      // Reset state to initial values
      const resetState: ChatbotContextState = {
        ...initialState,
        config: state.config, // Keep the configuration
      };

      // Clear all state except config
      dispatch({ type: "INITIALIZE_START" }); // This will reset most of the state
      dispatch({ type: "CLEAR_ERROR" });
      dispatch({ type: "SET_PROCESSING", payload: false });
    } catch (error) {
      const chatbotError: ChatbotError = {
        code: "RESET_ERROR",
        message: `Failed to reset chatbot: ${
          error instanceof Error ? error.message : "Unknown error"
        }`,
        details: error,
        timestamp: new Date(),
      };

      dispatch({ type: "SET_ERROR", payload: chatbotError });
      throw error;
    }
  }, [state.config]);

  // Vector store methods
  const initializeVectorStore = useCallback(
    async (config: VectorStoreConfig) => {
      dispatch({ type: "VECTOR_STORE_CONNECTING" });
      dispatch({ type: "SET_INITIALIZATION_PROGRESS", payload: 20 });

      try {
        // Dynamic import to avoid bundling issues
        const { createVectorStore, VectorStoreUtils } = await import(
          "../services/vectorStore"
        );

        // Validate configuration
        if (!VectorStoreUtils.validateConfig(config)) {
          throw new Error("Invalid vector store configuration");
        }

        // Create vector store instance
        vectorStoreRef.current = createVectorStore(config);

        // Connect to vector store
        await vectorStoreRef.current.connect();

        // Get initial data
        const collections = await vectorStoreRef.current.getCollections();
        const documentCount = await vectorStoreRef.current.getDocumentCount();

        dispatch({
          type: "VECTOR_STORE_CONNECTED",
          payload: { collections, documentCount },
        });

        dispatch({ type: "VECTOR_STORE_CONFIG_UPDATE", payload: config });
        dispatch({ type: "SET_INITIALIZATION_PROGRESS", payload: 40 });
      } catch (error) {
        const chatbotError: ChatbotError = {
          code: "VECTOR_STORE_INIT_ERROR",
          message: `Failed to initialize vector store: ${
            error instanceof Error ? error.message : "Unknown error"
          }`,
          details: error,
          timestamp: new Date(),
        };

        dispatch({ type: "VECTOR_STORE_ERROR", payload: chatbotError });
        dispatch({ type: "SET_ERROR", payload: chatbotError });
        throw error;
      }
    },
    []
  );

  const addDocuments = useCallback(
    async (documents: Document[]) => {
      if (!vectorStoreRef.current) {
        throw new Error("Vector store is not initialized");
      }

      dispatch({ type: "SET_PROCESSING", payload: true });

      try {
        // Dynamic import for utilities
        const { VectorStoreUtils } = await import("../services/vectorStore");

        // Prepare documents with embeddings
        const preparedDocuments =
          await VectorStoreUtils.prepareDocumentsForStorage(documents);

        // Add to vector store
        await vectorStoreRef.current.addDocuments(preparedDocuments);

        // Update local state
        preparedDocuments.forEach((doc) => {
          dispatch({ type: "DOCUMENT_ADD", payload: doc });
        });

        // Update document count
        const documentCount = await vectorStoreRef.current.getDocumentCount();
        dispatch({
          type: "VECTOR_STORE_CONNECTED",
          payload: {
            collections: state.vectorStore.collections,
            documentCount,
          },
        });
      } catch (error) {
        const chatbotError: ChatbotError = {
          code: "ADD_DOCUMENTS_ERROR",
          message: `Failed to add documents: ${
            error instanceof Error ? error.message : "Unknown error"
          }`,
          details: error,
          timestamp: new Date(),
        };

        dispatch({ type: "SET_ERROR", payload: chatbotError });
        throw error;
      } finally {
        dispatch({ type: "SET_PROCESSING", payload: false });
      }
    },
    [state.vectorStore.collections]
  );

  const removeDocuments = useCallback(
    async (documentIds: string[]) => {
      if (!vectorStoreRef.current) {
        throw new Error("Vector store is not initialized");
      }

      dispatch({ type: "SET_PROCESSING", payload: true });

      try {
        // Remove from vector store
        await vectorStoreRef.current.removeDocuments(documentIds);

        // Update local state
        documentIds.forEach((id) => {
          dispatch({ type: "DOCUMENT_REMOVE", payload: id });
        });

        // Update document count
        const documentCount = await vectorStoreRef.current.getDocumentCount();
        dispatch({
          type: "VECTOR_STORE_CONNECTED",
          payload: {
            collections: state.vectorStore.collections,
            documentCount,
          },
        });
      } catch (error) {
        const chatbotError: ChatbotError = {
          code: "REMOVE_DOCUMENTS_ERROR",
          message: `Failed to remove documents: ${
            error instanceof Error ? error.message : "Unknown error"
          }`,
          details: error,
          timestamp: new Date(),
        };

        dispatch({ type: "SET_ERROR", payload: chatbotError });
        throw error;
      } finally {
        dispatch({ type: "SET_PROCESSING", payload: false });
      }
    },
    [state.vectorStore.collections]
  );

  const searchSimilarDocuments = useCallback(
    async (query: string, limit = 5): Promise<Document[]> => {
      if (!vectorStoreRef.current) {
        throw new Error("Vector store is not initialized");
      }

      try {
        const results = await vectorStoreRef.current.similaritySearch(
          query,
          limit
        );
        return results;
      } catch (error) {
        const chatbotError: ChatbotError = {
          code: "SIMILARITY_SEARCH_ERROR",
          message: `Failed to search documents: ${
            error instanceof Error ? error.message : "Unknown error"
          }`,
          details: error,
          timestamp: new Date(),
        };

        dispatch({ type: "SET_ERROR", payload: chatbotError });
        throw error;
      }
    },
    []
  );

  // LLM methods
  const initializeLLM = useCallback(async (config: LLMConfig) => {
    dispatch({ type: "LLM_CONNECTING" });
    dispatch({ type: "SET_INITIALIZATION_PROGRESS", payload: 60 });

    try {
      // Dynamic import to avoid bundling issues
      const { createLLM, LLMUtils, RAGChainService } = await import(
        "../services/llmService"
      );

      // Validate configuration
      if (!LLMUtils.validateConfig(config)) {
        throw new Error("Invalid LLM configuration");
      }

      // Create LLM instance
      llmRef.current = createLLM(config);

      // Connect to LLM
      await llmRef.current.connect();

      // Get available models and current model
      const availableModels = await llmRef.current.listModels();
      const currentModel = config.model;

      dispatch({
        type: "LLM_CONNECTED",
        payload: { availableModels, currentModel },
      });

      dispatch({ type: "LLM_CONFIG_UPDATE", payload: config });

      // Create RAG chain if vector store is available
      if (vectorStoreRef.current && llmRef.current) {
        ragChainRef.current = new RAGChainService(
          llmRef.current,
          vectorStoreRef.current
        );
      }

      dispatch({ type: "SET_INITIALIZATION_PROGRESS", payload: 80 });
    } catch (error) {
      const chatbotError: ChatbotError = {
        code: "LLM_INIT_ERROR",
        message: `Failed to initialize LLM: ${
          error instanceof Error ? error.message : "Unknown error"
        }`,
        details: error,
        timestamp: new Date(),
      };

      dispatch({ type: "LLM_ERROR", payload: chatbotError });
      dispatch({ type: "SET_ERROR", payload: chatbotError });
      throw error;
    }
  }, []);

  const generateResponse = useCallback(
    async (prompt: string, context?: Document[]): Promise<string> => {
      if (!llmRef.current) {
        throw new Error("LLM is not initialized");
      }

      dispatch({ type: "SET_PROCESSING", payload: true });

      try {
        const response = await llmRef.current.generateResponse(prompt, context);
        return response.content;
      } catch (error) {
        const chatbotError: ChatbotError = {
          code: "LLM_GENERATE_ERROR",
          message: `Failed to generate response: ${
            error instanceof Error ? error.message : "Unknown error"
          }`,
          details: error,
          timestamp: new Date(),
        };

        dispatch({ type: "SET_ERROR", payload: chatbotError });
        throw error;
      } finally {
        dispatch({ type: "SET_PROCESSING", payload: false });
      }
    },
    []
  );

  const generateRAGResponse = useCallback(
    async (
      query: string
    ): Promise<{ response: string; sources: Document[] }> => {
      if (!ragChainRef.current) {
        // Fallback to regular LLM if RAG chain is not available
        if (!llmRef.current) {
          throw new Error("Neither RAG chain nor LLM is initialized");
        }

        dispatch({ type: "SET_PROCESSING", payload: true });

        try {
          const response = await llmRef.current.generateResponse(query);
          return { response: response.content, sources: [] };
        } catch (error) {
          const chatbotError: ChatbotError = {
            code: "RAG_FALLBACK_ERROR",
            message: `Failed to generate response: ${
              error instanceof Error ? error.message : "Unknown error"
            }`,
            details: error,
            timestamp: new Date(),
          };

          dispatch({ type: "SET_ERROR", payload: chatbotError });
          throw error;
        } finally {
          dispatch({ type: "SET_PROCESSING", payload: false });
        }
      }

      dispatch({ type: "SET_PROCESSING", payload: true });

      try {
        const ragResponse = await ragChainRef.current.generateRAGResponse(
          query,
          {
            maxRetrievedDocs: state.config.ragSettings.maxRetrievedDocs,
            similarityThreshold: state.config.ragSettings.similarityThreshold,
          }
        );

        return {
          response: ragResponse.response,
          sources: ragResponse.sources,
        };
      } catch (error) {
        const chatbotError: ChatbotError = {
          code: "RAG_GENERATE_ERROR",
          message: `Failed to generate RAG response: ${
            error instanceof Error ? error.message : "Unknown error"
          }`,
          details: error,
          timestamp: new Date(),
        };

        dispatch({ type: "SET_ERROR", payload: chatbotError });
        throw error;
      } finally {
        dispatch({ type: "SET_PROCESSING", payload: false });
      }
    },
    [state.config.ragSettings]
  );

  // Storage methods
  const initializeStorage = useCallback(async (config: StorageConfig) => {
    dispatch({ type: "STORAGE_CONNECTING" });
    dispatch({ type: "SET_INITIALIZATION_PROGRESS", payload: 90 });

    try {
      // Dynamic import to avoid bundling issues
      const { createStorage, StorageUtils } = await import(
        "../services/storageService"
      );

      // Validate configuration
      if (!StorageUtils.validateConfig(config)) {
        throw new Error("Invalid storage configuration");
      }

      // Create storage instance
      storageRef.current = createStorage(config);

      // Connect to storage
      await storageRef.current.connect();

      dispatch({ type: "STORAGE_CONNECTED" });
      dispatch({ type: "STORAGE_CONFIG_UPDATE", payload: config });
      dispatch({ type: "SET_INITIALIZATION_PROGRESS", payload: 100 });
    } catch (error) {
      const chatbotError: ChatbotError = {
        code: "STORAGE_INIT_ERROR",
        message: `Failed to initialize storage: ${
          error instanceof Error ? error.message : "Unknown error"
        }`,
        details: error,
        timestamp: new Date(),
      };

      dispatch({ type: "STORAGE_ERROR", payload: chatbotError });
      dispatch({ type: "SET_ERROR", payload: chatbotError });
      throw error;
    }
  }, []);

  const uploadDocument = useCallback(
    async (
      file: File,
      metadata?: Partial<Document["metadata"]>
    ): Promise<Document> => {
      if (!storageRef.current) {
        throw new Error("Storage is not initialized");
      }

      dispatch({ type: "SET_PROCESSING", payload: true });

      try {
        // Setup progress tracking
        const fileId = `upload_${Date.now()}_${Math.random()
          .toString(36)
          .substr(2, 9)}`;

        if (storageRef.current.setProgressCallback) {
          storageRef.current.setProgressCallback(fileId, (progress: any) => {
            dispatch({
              type: "STORAGE_UPLOAD_PROGRESS",
              payload: { fileId: progress.fileId, progress: progress.progress },
            });
          });
        }

        // Upload file
        const document = await storageRef.current.uploadFile(file, {
          description: metadata?.description,
          tags: metadata?.tags,
          extractText: true,
        });

        // Add to local state
        dispatch({ type: "DOCUMENT_ADD", payload: document });

        // Add to vector store if available and document has content
        if (vectorStoreRef.current && document.content) {
          try {
            await vectorStoreRef.current.addDocuments([document]);
          } catch (error) {
            console.warn("Failed to add document to vector store:", error);
            // Continue without vector store indexing
          }
        }

        // Clean up progress tracking
        if (storageRef.current.removeProgressCallback) {
          storageRef.current.removeProgressCallback(fileId);
        }

        return document;
      } catch (error) {
        const chatbotError: ChatbotError = {
          code: "UPLOAD_DOCUMENT_ERROR",
          message: `Failed to upload document: ${
            error instanceof Error ? error.message : "Unknown error"
          }`,
          details: error,
          timestamp: new Date(),
        };

        dispatch({ type: "SET_ERROR", payload: chatbotError });
        throw error;
      } finally {
        dispatch({ type: "SET_PROCESSING", payload: false });
      }
    },
    []
  );

  const downloadDocument = useCallback(
    async (documentId: string): Promise<Blob> => {
      if (!storageRef.current) {
        throw new Error("Storage is not initialized");
      }

      try {
        const blob = await storageRef.current.downloadFile(documentId);
        return blob;
      } catch (error) {
        const chatbotError: ChatbotError = {
          code: "DOWNLOAD_DOCUMENT_ERROR",
          message: `Failed to download document: ${
            error instanceof Error ? error.message : "Unknown error"
          }`,
          details: error,
          timestamp: new Date(),
        };

        dispatch({ type: "SET_ERROR", payload: chatbotError });
        throw error;
      }
    },
    []
  );

  const deleteDocument = useCallback(
    async (documentId: string): Promise<void> => {
      if (!storageRef.current) {
        throw new Error("Storage is not initialized");
      }

      dispatch({ type: "SET_PROCESSING", payload: true });

      try {
        // Remove from storage
        await storageRef.current.deleteFile(documentId);

        // Remove from vector store if available
        if (vectorStoreRef.current) {
          try {
            await vectorStoreRef.current.removeDocuments([documentId]);
          } catch (error) {
            console.warn("Failed to remove document from vector store:", error);
            // Continue with local removal
          }
        }

        // Remove from local state
        dispatch({ type: "DOCUMENT_REMOVE", payload: documentId });
      } catch (error) {
        const chatbotError: ChatbotError = {
          code: "DELETE_DOCUMENT_ERROR",
          message: `Failed to delete document: ${
            error instanceof Error ? error.message : "Unknown error"
          }`,
          details: error,
          timestamp: new Date(),
        };

        dispatch({ type: "SET_ERROR", payload: chatbotError });
        throw error;
      } finally {
        dispatch({ type: "SET_PROCESSING", payload: false });
      }
    },
    []
  );

  const listDocuments = useCallback(async (): Promise<Document[]> => {
    if (!storageRef.current) {
      // Return local documents if storage is not initialized
      return state.documents;
    }

    try {
      const documents = await storageRef.current.listFiles();

      // Update local state
      dispatch({ type: "DOCUMENTS_SET", payload: documents });

      return documents;
    } catch (error) {
      const chatbotError: ChatbotError = {
        code: "LIST_DOCUMENTS_ERROR",
        message: `Failed to list documents: ${
          error instanceof Error ? error.message : "Unknown error"
        }`,
        details: error,
        timestamp: new Date(),
      };

      dispatch({ type: "SET_ERROR", payload: chatbotError });

      // Return local documents as fallback
      return state.documents;
    }
  }, [state.documents]);

  // Configuration methods (placeholders)
  const updateConfig = useCallback(async (updates: Partial<ChatbotConfig>) => {
    dispatch({ type: "CONFIG_UPDATE", payload: updates });
  }, []);

  const exportConfig = useCallback(() => {
    return state.config;
  }, [state.config]);

  const importConfig = useCallback(async (config: ChatbotConfig) => {
    dispatch({ type: "CONFIG_UPDATE", payload: config });
  }, []);

  // Conversation methods (placeholders)
  const startConversation = useCallback(
    async (title?: string): Promise<Conversation> => {
      // Implementation will be added in subtask 27.5
      const conversation: Conversation = {
        id: `conv_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`,
        title: title || `Conversation ${new Date().toLocaleDateString()}`,
        messages: [],
        createdAt: new Date(),
        updatedAt: new Date(),
      };
      dispatch({ type: "CONVERSATION_START", payload: conversation });
      return conversation;
    },
    []
  );

  const selectConversation = useCallback(async (conversationId: string) => {
    dispatch({ type: "CONVERSATION_SELECT", payload: conversationId });
  }, []);

  const sendMessage = useCallback(
    async (content: string): Promise<ConversationMessage> => {
      if (!state.currentConversation) {
        throw new Error(
          "No active conversation. Please start a conversation first."
        );
      }

      if (!llmRef.current) {
        throw new Error("LLM is not initialized");
      }

      dispatch({ type: "SET_PROCESSING", payload: true });

      try {
        // Create user message
        const userMessage: ConversationMessage = {
          id: `msg_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`,
          content,
          role: "user",
          timestamp: new Date(),
        };

        // Add user message to conversation
        dispatch({
          type: "CONVERSATION_MESSAGE_ADD",
          payload: {
            conversationId: state.currentConversation.id,
            message: userMessage,
          },
        });

        // Generate AI response
        let aiResponse: string;
        let retrievedDocs: Document[] = [];

        if (state.config.enableRAG && ragChainRef.current) {
          // Use RAG for response generation
          try {
            const ragResult = await generateRAGResponse(content);
            aiResponse = ragResult.response;
            retrievedDocs = ragResult.sources;
          } catch (error) {
            console.warn(
              "RAG generation failed, falling back to direct LLM:",
              error
            );
            aiResponse = await generateResponse(content);
          }
        } else {
          // Use direct LLM response
          aiResponse = await generateResponse(content);
        }

        // Create assistant message
        const assistantMessage: ConversationMessage = {
          id: `msg_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`,
          content: aiResponse,
          role: "assistant",
          timestamp: new Date(),
          metadata: {
            retrievedDocs: retrievedDocs.length > 0 ? retrievedDocs : undefined,
            confidence: retrievedDocs.length > 0 ? 0.8 : undefined, // Mock confidence
          },
        };

        // Add assistant message to conversation
        dispatch({
          type: "CONVERSATION_MESSAGE_ADD",
          payload: {
            conversationId: state.currentConversation.id,
            message: assistantMessage,
          },
        });

        return assistantMessage;
      } catch (error) {
        const chatbotError: ChatbotError = {
          code: "SEND_MESSAGE_ERROR",
          message: `Failed to send message: ${
            error instanceof Error ? error.message : "Unknown error"
          }`,
          details: error,
          timestamp: new Date(),
        };

        dispatch({ type: "SET_ERROR", payload: chatbotError });
        throw error;
      } finally {
        dispatch({ type: "SET_PROCESSING", payload: false });
      }
    },
    [
      state.currentConversation,
      state.config.enableRAG,
      llmRef.current,
      ragChainRef.current,
      generateRAGResponse,
      generateResponse,
    ]
  );

  const getConversationHistory = useCallback(
    async (conversationId?: string): Promise<ConversationMessage[]> => {
      const targetId = conversationId || state.currentConversation?.id;
      if (!targetId) return [];

      const conversation = state.conversations.find((c) => c.id === targetId);
      return conversation?.messages || [];
    },
    [state.conversations, state.currentConversation]
  );

  const deleteConversation = useCallback(
    async (conversationId: string) => {
      try {
        // Check if the conversation being deleted is the current one
        if (state.currentConversation?.id === conversationId) {
          // Clear current conversation
          dispatch({ type: "CONVERSATION_SELECT", payload: "" });
        }

        // Remove from conversations list
        const updatedConversations = state.conversations.filter(
          (c) => c.id !== conversationId
        );
        dispatch({ type: "CONVERSATIONS_SET", payload: updatedConversations });
      } catch (error) {
        const chatbotError: ChatbotError = {
          code: "DELETE_CONVERSATION_ERROR",
          message: `Failed to delete conversation: ${
            error instanceof Error ? error.message : "Unknown error"
          }`,
          details: error,
          timestamp: new Date(),
        };

        dispatch({ type: "SET_ERROR", payload: chatbotError });
        throw error;
      }
    },
    [state.conversations, state.currentConversation]
  );

  // Utility methods
  const getStatus = useCallback(() => {
    return {
      overall: state.globalStatus,
      subsystems: {
        vectorStore: state.vectorStore.status,
        llm: state.llm.status,
        storage: state.storage.status,
      },
    };
  }, [state]);

  const clearError = useCallback(() => {
    dispatch({ type: "CLEAR_ERROR" });
  }, []);

  const healthCheck = useCallback(async () => {
    const results = {
      vectorStore: false,
      llm: false,
      storage: false,
    };

    try {
      // Check vector store health
      if (vectorStoreRef.current) {
        try {
          await vectorStoreRef.current.healthCheck();
          results.vectorStore = true;
        } catch (error) {
          console.warn("Vector store health check failed:", error);
        }
      }

      // Check LLM health
      if (llmRef.current) {
        try {
          await llmRef.current.healthCheck();
          results.llm = true;
        } catch (error) {
          console.warn("LLM health check failed:", error);
        }
      }

      // Check storage health
      if (storageRef.current) {
        try {
          await storageRef.current.healthCheck();
          results.storage = true;
        } catch (error) {
          console.warn("Storage health check failed:", error);
        }
      }

      return results;
    } catch (error) {
      const chatbotError: ChatbotError = {
        code: "HEALTH_CHECK_ERROR",
        message: `Health check failed: ${
          error instanceof Error ? error.message : "Unknown error"
        }`,
        details: error,
        timestamp: new Date(),
      };

      dispatch({ type: "SET_ERROR", payload: chatbotError });
      return results; // Return partial results even on error
    }
  }, []);

  // Auto-initialize if enabled
  useEffect(() => {
    if (autoInitialize && !state.isInitialized) {
      initialize();
    }
  }, [autoInitialize, state.isInitialized, initialize]);

  // Context value
  const contextValue: ChatbotContextType = {
    ...state,
    initialize,
    reset,
    initializeVectorStore,
    addDocuments,
    removeDocuments,
    searchSimilarDocuments,
    initializeLLM,
    generateResponse,
    generateRAGResponse,
    initializeStorage,
    uploadDocument,
    downloadDocument,
    deleteDocument,
    listDocuments,
    updateConfig,
    exportConfig,
    importConfig,
    startConversation,
    selectConversation,
    sendMessage,
    getConversationHistory,
    deleteConversation,
    getStatus,
    clearError,
    healthCheck,
  };

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

// Re-export everything for convenience
export default ChatbotProvider;
