//
// SPDX-FileCopyrightText: Copyright (c) 1993-2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
// SPDX-License-Identifier: Apache-2.0
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
"use client"

import { useState, useEffect } from "react"
import { useDocuments } from "@/contexts/document-context"
import { Button } from "@/components/ui/button"
import { Sparkles, Loader2, CheckCircle, AlertCircle, FileText, Zap, Cpu, X, ChevronUp, ChevronDown } from "lucide-react"
import { Switch } from "@/components/ui/switch"
import { Label } from "@/components/ui/label"
import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from "@/components/ui/tooltip"
import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs"
import React from "react"
import { AdvancedOptions } from "@/components/advanced-options";
import { PromptConfiguration, PromptConfigurations } from "@/components/prompt-configuration";
import { useShiftSelect } from "@/hooks/use-shift-select"

interface EmbeddingsGeneratorProps {
  showTripleExtraction?: boolean;
}

type Document = {
  id: string;
  name: string;
  status: string;
  uploadStatus: string;
  size: string;
  triples?: any[];
  embeddings?: {
    count: number;
    generated: Date;
    status: "New" | "Processing" | "Processed" | "Error";
    error?: string;
  };
};

interface ContentProps {
  documents: Document[];
  selectedDocs: string[];
  handleSelectAll: () => void;
  handleItemClick: (item: Document, event?: React.MouseEvent) => void;
  isSelected: (itemId: string) => boolean;
  error: string | null;
  status: string;
}

interface EmbeddingsContentProps extends ContentProps {
  generateEmbeddings: () => void;
  isGenerating: boolean;
  useLangChain: boolean;
  setUseLangChain: (value: boolean) => void;
  useSentenceChunking: boolean;
  setUseSentenceChunking: (value: boolean) => void;
  embeddingsProvider: string;
  handleStopEmbeddings: () => void;
}

interface TriplesContentProps extends ContentProps {
  extractTriples: (promptConfigs?: PromptConfigurations) => void;
  isProcessing: boolean;
  useLangChain: boolean;
  setUseLangChain: (value: boolean) => void;
  useSentenceChunking: boolean;
  setUseSentenceChunking: (value: boolean) => void;
  useEntityExtraction: boolean;
  setUseEntityExtraction: (value: boolean) => void;
  error: string | null;
  status: string;
  handleStopProcessing: () => void;
}

export function EmbeddingsGenerator({ showTripleExtraction = false }: EmbeddingsGeneratorProps) {
  const { documents, processDocuments, generateEmbeddings: contextGenerateEmbeddings } = useDocuments()
  const [isGenerating, setIsGenerating] = useState(false)
  const [isProcessing, setIsProcessing] = useState(false)
  const [useLangChain, setUseLangChain] = useState(false)
  const [useSentenceChunking, setUseSentenceChunking] = useState(true)
  const [useEntityExtraction, setUseEntityExtraction] = useState(true)
  const [error, setError] = useState<string | null>(null)
  const [status, setStatus] = useState("")
  const [langChainMethod, setLangChainMethod] = React.useState<'default' | 'graphtransformer'>(
    'default'
  );
  const [embeddingsProvider, setEmbeddingsProvider] = useState<string>(
    typeof window !== 'undefined' ? localStorage.getItem("embeddings_provider") || "local" : "local"
  );

  // Use shift-select hook for document selection
  const {
    selectedItems: selectedDocs,
    setSelectedItems: setSelectedDocs,
    handleItemClick,
    handleSelectAll,
    isSelected
  } = useShiftSelect({
    items: documents,
    getItemId: (doc) => doc.id,
    canSelect: (doc) => doc.status === "New" || doc.status === "Processed" || doc.status === "Error",
    onSelectionChange: (selectedIds) => {
      // Optional: handle selection change if needed
    }
  })

  // Listen for embeddings settings changes
  useEffect(() => {
    const handleEmbeddingsSettingsChanged = () => {
      const updatedProvider = localStorage.getItem("embeddings_provider") || "local";
      setEmbeddingsProvider(updatedProvider);
      console.log("Embeddings generator detected embeddings settings change:", updatedProvider);
    };
    
    window.addEventListener('embeddings-settings-changed', handleEmbeddingsSettingsChanged);
    
    return () => {
      window.removeEventListener('embeddings-settings-changed', handleEmbeddingsSettingsChanged);
    };
  }, []);



  // Handle tab navigation
  const handleTabChange = (tab: string) => {
    const tabElement = document.querySelector(`[data-value="${tab}"]`)
    if (tabElement && 'click' in tabElement) {
      (tabElement as HTMLElement).click()
    }
  }

  // When LangChain is toggled off, disable dependent options
  useEffect(() => {
    if (!useLangChain) {
      setUseSentenceChunking(false)
      setUseEntityExtraction(false)
    }
    
    // Dispatch custom event to update embedding model info in Processing Summary
    const event = new CustomEvent('langChainToggled', {
      detail: { useLangChain }
    });
    window.dispatchEvent(event);
  }, [useLangChain])

  // Simulate embedding generation
  const generateEmbeddings = async () => {
    if (selectedDocs.length === 0) {
      setError("Please select at least one document")
      return
    }

    setError(null)
    setIsGenerating(true)
    setStatus("Preparing documents for embedding generation...")

    try {
      // Process each selected document
      for (let i = 0; i < selectedDocs.length; i++) {
        const docId = selectedDocs[i];
        const doc = documents.find(d => d.id === docId);
        
        if (!doc) {
          console.error(`Document with ID ${docId} not found`);
          continue;
        }
        
        setStatus(`Generating embeddings for document ${i+1} of ${selectedDocs.length}: ${doc.name}`);
        await contextGenerateEmbeddings(docId);
      }
      
      setStatus("Embedding generation complete!");
      setTimeout(() => {
        setIsGenerating(false);
        setStatus("");
      }, 1500);
    } catch (error) {
      console.error("Error generating embeddings:", error);
      setError("Failed to generate embeddings. Please try again.");
      setIsGenerating(false);
    }
  }

  // Extract triples from documents
  const extractTriples = async (options?: PromptConfigurations & { chunkSize?: number; overlapSize?: number; chunkingMethod?: 'optimized' | 'pyg' }) => {
    if (selectedDocs.length === 0) {
      setError("Please select at least one document")
      return
    }

    setError(null)
    setIsProcessing(true)
    setStatus("Preparing documents for triple extraction...")
    
    // Set up a listener for the processing-complete event
    const handleProcessingComplete = () => {
      console.log("Processing complete event received in embeddings-generator");
      setIsProcessing(false);
      setStatus("");
    };
    
    window.addEventListener('processing-complete', handleProcessingComplete);

    try {
      // Update the processing status display
      const docNames = selectedDocs.map(id => 
        documents.find(d => d.id === id)?.name || 'Unknown'
      ).join(', ');
      
      // Determine the processing method based on selected model and options
      let processingMethod = 'default extractor';
      try {
        const selectedModel = localStorage.getItem("selectedModel");
        if (selectedModel) {
          const model = JSON.parse(selectedModel);
          if (model.provider === "ollama") {
            processingMethod = `Ollama ${model.model || 'qwen3:1.7b'}`;
          } else if (model.provider === "vllm") {
            processingMethod = `vLLM ${model.model || 'local model'}`;
          } else if (model.id?.startsWith("nvidia-")) {
            processingMethod = 'NVIDIA Nemotron';
          }
        }
      } catch (e) {
        // Fallback to default if parsing fails
      }
      
      if (useLangChain) {
        processingMethod += langChainMethod === 'graphtransformer' ? ' with LLMGraphTransformer' : ' with LangChain';
      }
      
      setStatus(`Processing ${selectedDocs.length} document(s): ${docNames} using ${processingMethod}`);
      
      // Call processDocuments with the selected document IDs and processing options
      const useGraphTransformer = useLangChain && langChainMethod === 'graphtransformer';
      const processingOptions: Parameters<typeof processDocuments>[1] = {
        useLangChain,
        useGraphTransformer,
        promptConfigs: options || undefined,
        chunkSize: options?.chunkSize,
        overlapSize: options?.overlapSize,
        chunkingMethod: options?.chunkingMethod
      };

      try {
        const selectedModel = localStorage.getItem("selectedModel");
        if (selectedModel) {
          const model = JSON.parse(selectedModel);
          if (model.provider === "ollama") {
            processingOptions.llmProvider = "ollama";
            processingOptions.ollamaModel = model.model || "qwen3:1.7b";
            processingOptions.ollamaBaseUrl = model.baseURL || "http://localhost:11434/v1";
          } else if (model.provider === "vllm") {
            processingOptions.llmProvider = "vllm";
            processingOptions.vllmModel = model.model;
            processingOptions.vllmBaseUrl = model.baseURL || "http://localhost:8001/v1";
          } else if (model.provider === "nvidia" || model.id?.startsWith("nvidia-")) {
            processingOptions.llmProvider = "nvidia";
          }
        }
      } catch (e) {
        console.log("Could not parse selected model, using default extraction provider");
      }

      await processDocuments(selectedDocs, processingOptions);
      
      // Navigate to the edit tab after processing is complete
      setTimeout(() => {
        // Clean up the event listener
        window.removeEventListener('processing-complete', handleProcessingComplete);
        
        // Navigate to the edit tab
        handleTabChange("edit");
      }, 500);
    } catch (error) {
      console.error("Error processing documents:", error)
      setError("Failed to process documents. Please try again.")
      setIsProcessing(false)
      setStatus("")
      
      // Clean up the event listener
      window.removeEventListener('processing-complete', handleProcessingComplete);
    }
  }

  // Stop processing function
  const handleStopProcessing = async () => {
    try {
      const response = await fetch('/api/stop-processing', {
        method: 'POST',
        headers: {
          'Content-Type': 'application/json',
        },
      });

      if (response.ok) {
        setStatus("Processing stopped by user");
        setError(null);
        setIsProcessing(false);
        setIsGenerating(false);
      } else {
        setError("Failed to stop processing. Please try again.");
      }
    } catch (error) {
      console.error("Error stopping processing:", error);
      setError("Failed to stop processing. Please try again.");
    }
  }

  // Stop embeddings generation function
  const handleStopEmbeddings = async () => {
    try {
      const response = await fetch('/api/stop-embeddings', {
        method: 'POST',
        headers: {
          'Content-Type': 'application/json',
        },
      });

      if (response.ok) {
        setStatus("Embeddings generation stopped by user");
        setError(null);
        setIsGenerating(false);
      } else {
        setError("Failed to stop embeddings generation. Please try again.");
      }
    } catch (error) {
      console.error("Error stopping embeddings generation:", error);
      setError("Failed to stop embeddings generation. Please try again.");
    }
  }

  return (
    <div className="space-y-4">
      {showTripleExtraction ? (
        <Tabs defaultValue="triples" className="w-full">
          <TabsList className="grid w-full grid-cols-2">
            <TabsTrigger value="triples">Triple Extraction</TabsTrigger>
            <TabsTrigger value="embeddings">Embeddings</TabsTrigger>
          </TabsList>
          
          <TabsContent value="embeddings" className="space-y-4 pt-4">
            <EmbeddingsContent
              documents={documents}
              selectedDocs={selectedDocs}
              handleSelectAll={handleSelectAll}
              handleItemClick={handleItemClick}
              isSelected={isSelected}
              generateEmbeddings={generateEmbeddings}
              isGenerating={isGenerating}
              useLangChain={useLangChain}
              setUseLangChain={setUseLangChain}
              useSentenceChunking={useSentenceChunking}
              setUseSentenceChunking={setUseSentenceChunking}
              error={error}
              status={status}
              embeddingsProvider={embeddingsProvider}
              handleStopEmbeddings={handleStopEmbeddings}
            />
          </TabsContent>
          
          <TabsContent value="triples" className="space-y-4 pt-4">
            <TriplesContent
              documents={documents}
              selectedDocs={selectedDocs}
              handleSelectAll={handleSelectAll}
              handleItemClick={handleItemClick}
              isSelected={isSelected}
              extractTriples={extractTriples}
              isProcessing={isProcessing}
              useLangChain={useLangChain}
              setUseLangChain={setUseLangChain}
              useSentenceChunking={useSentenceChunking}
              setUseSentenceChunking={setUseSentenceChunking}
              useEntityExtraction={useEntityExtraction}
              setUseEntityExtraction={setUseEntityExtraction}
              error={error}
              status={status}
              handleStopProcessing={handleStopProcessing}
            />
          </TabsContent>
        </Tabs>
      ) : (
        <EmbeddingsContent
          documents={documents}
          selectedDocs={selectedDocs}
          handleSelectAll={handleSelectAll}
          handleItemClick={handleItemClick}
          isSelected={isSelected}
          generateEmbeddings={generateEmbeddings}
          isGenerating={isGenerating}
          useLangChain={useLangChain}
          setUseLangChain={setUseLangChain}
          useSentenceChunking={useSentenceChunking}
          setUseSentenceChunking={setUseSentenceChunking}
          error={error}
          status={status}
          embeddingsProvider={embeddingsProvider}
          handleStopEmbeddings={handleStopEmbeddings}
        />
      )}
    </div>
  )
}

// Embeddings content component
function EmbeddingsContent({
  documents,
  selectedDocs,
  handleSelectAll,
  handleItemClick,
  isSelected,
  generateEmbeddings,
  isGenerating,
  useLangChain,
  setUseLangChain,
  useSentenceChunking,
  setUseSentenceChunking,
  error,
  status,
  embeddingsProvider,
  handleStopEmbeddings
}: EmbeddingsContentProps) {
  // Helper function to get embeddings status icon
  const getEmbeddingsStatusIcon = (doc: Document) => {
    // Use embeddings status if available, otherwise show 'New'
    const embeddingsStatus = doc.embeddings?.status || "New";
    
    switch (embeddingsStatus) {
      case "New":
        return <span className="h-2 w-2 rounded-full bg-cyan-400 mr-2"></span>;
      case "Processing":
        return <Loader2 className="h-3.5 w-3.5 text-yellow-500 mr-2 animate-spin" />;
      case "Processed":
        return <CheckCircle className="h-3.5 w-3.5 text-green-500 mr-2" />;
      case "Error":
        return <AlertCircle className="h-3.5 w-3.5 text-destructive mr-2" />;
      default:
        return <span className="h-2 w-2 rounded-full bg-gray-400 mr-2"></span>;
    }
  };
  
  // Helper function to get embeddings status text
  const getEmbeddingsStatusText = (doc: Document) => {
    if (doc.embeddings?.status === "Processed") {
      return `${doc.embeddings.count} vectors`;
    } else if (doc.embeddings?.status) {
      return doc.embeddings.status;
    } else {
      return "Ready";
    }
  };
  
  return (
    <>
      <div className="flex items-center justify-between mb-4">
        <div className="flex items-center gap-3">
          <div className="w-6 h-6 rounded-md bg-nvidia-green/15 flex items-center justify-center">
            <Sparkles className="h-3 w-3 text-nvidia-green" />
          </div>
          <h3 className="text-base font-semibold text-foreground">Generate Embeddings</h3>
        </div>
        <TooltipProvider>
          <Tooltip>
            <TooltipTrigger asChild>
              <div className="text-xs text-muted-foreground cursor-help flex items-center hover:text-foreground transition-colors">
                <InfoIcon className="h-4 w-4 mr-1" />
                What are embeddings?
              </div>
            </TooltipTrigger>
            <TooltipContent className="max-w-[280px]">
              <p className="text-xs">
                Embeddings are vector representations of your documents that enable semantic search and similarity matching between documents.
              </p>
            </TooltipContent>
          </Tooltip>
        </TooltipProvider>
      </div>
      
      <p className="text-sm text-muted-foreground">
        Generate vector embeddings for semantic search and document similarity
      </p>
      
      {/* Current embeddings provider indicator */}
      <div className="flex items-center text-xs text-muted-foreground mt-1 mb-3 bg-background/40 border border-border/40 rounded-md p-2">
        <Cpu className="h-3.5 w-3.5 mr-1.5" />
        <span>Using: <span className="font-medium text-primary">{embeddingsProvider === "nvidia" ? "NVIDIA API" : "Local Sentence Transformer"}</span></span>
      </div>

      <div className="space-y-3 pt-2">
        <h4 className="text-sm font-medium">Processing Options</h4>
        
        <div className="space-y-2">
          <div className="flex items-center space-x-2">
            <Switch 
              id="use-langchain-embeddings" 
              checked={useLangChain}
              onCheckedChange={setUseLangChain}
              disabled={isGenerating}
            />
            <Label htmlFor="use-langchain-embeddings" className="text-sm cursor-pointer">Use LangChain</Label>
          </div>
          
          {useLangChain && (
            <div className="mt-3">
              <AdvancedOptions title="LangChain Options" defaultOpen={false}>
                <div className="space-y-3">
                  <div className="flex items-center space-x-2">
                    <Switch 
                      id="use-sentence-chunking-embeddings" 
                      checked={useSentenceChunking}
                      onCheckedChange={setUseSentenceChunking}
                      disabled={isGenerating}
                    />
                    <Label 
                      htmlFor="use-sentence-chunking-embeddings" 
                      className="text-sm cursor-pointer"
                    >
                      Use Sentence Chunking
                    </Label>
                  </div>
                  <p className="text-xs text-muted-foreground pl-7">
                    Split documents into sentences for more accurate embeddings
                  </p>
                </div>
              </AdvancedOptions>
            </div>
          )}
        </div>
      </div>

      {error && (
        <div className="bg-destructive/10 border border-destructive rounded-md p-3 flex items-start gap-2">
          <AlertCircle className="h-4 w-4 text-destructive mt-0.5 flex-shrink-0" />
          <p className="text-sm text-destructive">{error}</p>
        </div>
      )}

      <div className="border rounded-md overflow-hidden mt-4">
        <div className="bg-muted/30 p-3 flex items-center justify-between">
          <div className="flex items-center">
            <input
              type="checkbox"
              className="rounded border-border text-primary focus:ring-primary mr-3 h-4 w-4"
              checked={selectedDocs.length === documents.filter(doc => doc.uploadStatus === "Uploaded").length && 
                      documents.filter(doc => doc.uploadStatus === "Uploaded").length > 0}
              onChange={handleSelectAll}
              disabled={documents.length === 0 || isGenerating}
            />
            <span className="text-sm font-medium">
              {selectedDocs.length > 0 ? (
            <span className="text-nvidia-green text-xs">{selectedDocs.length} selected</span>
              ) : (
                <span className="text-xs">Select all</span>
              )}
            </span>
          </div>

          <div className="flex gap-3 pt-4">
            <Button
              size="default"
              disabled={isGenerating || selectedDocs.length === 0}
              onClick={generateEmbeddings}
              className="bg-nvidia-green hover:bg-nvidia-green/90 text-white font-medium px-6 py-2 gap-2"
            >
              {isGenerating ? (
                <>
                  <Loader2 className="h-4 w-4 animate-spin" />
                  <span>Generating</span>
                </>
              ) : (
                <>
                  <Sparkles className="h-4 w-4" />
                  <span>Generate Embeddings</span>
                </>
              )}
            </Button>
            
            {isGenerating && (
              <Button
                size="default"
                variant="destructive"
                onClick={handleStopEmbeddings}
                className="px-4 py-2 gap-2"
              >
                <X className="h-4 w-4" />
                <span>Stop</span>
              </Button>
            )}
          </div>
        </div>

        <div className="max-h-[250px] overflow-y-auto">
          <table className="w-full text-sm">
            <thead className="bg-muted/50">
              <tr>
                <th className="w-12 py-2 px-3 text-left"></th>
                <th className="py-2 px-3 text-left">Document</th>
                <th className="py-2 px-3 text-left">Size</th>
                <th className="py-2 px-3 text-left">Triple Status</th>
                <th className="py-2 px-3 text-left">Embeddings Status</th>
              </tr>
            </thead>
            <tbody>
              {documents.length === 0 ? (
                <tr>
                  <td colSpan={5} className="py-6 text-center text-muted-foreground">
                    No documents available for embedding generation
                  </td>
                </tr>
              ) : (
                documents.map((doc) => (
                  <tr key={doc.id} className="border-t hover:bg-muted/20"
                      onClick={(e) => handleItemClick(doc, e)}>
                    <td className="py-2 px-3" onClick={(e) => e.stopPropagation()}>
                      <input
                        type="checkbox"
                        className="rounded border-border text-primary focus:ring-primary h-4 w-4"
                        checked={isSelected(doc.id)}
                        onChange={(e) => handleItemClick(doc, e)}
                        disabled={isGenerating}
                      />
                    </td>
                    <td className="py-2 px-3 font-medium">{doc.name}</td>
                    <td className="py-2 px-3">{doc.size}</td>
                    <td className="py-2 px-3">
                      <div className="flex items-center">
                        {doc.status === "New" && (
                          <span className="h-2 w-2 rounded-full bg-cyan-400 mr-2"></span>
                        )}
                        {doc.status === "Processing" && (
                          <Loader2 className="h-3.5 w-3.5 text-yellow-500 mr-2 animate-spin" />
                        )}
                        {doc.status === "Processed" && (
                          <CheckCircle className="h-3.5 w-3.5 text-green-500 mr-2" />
                        )}
                        {doc.status === "Error" && (
                          <AlertCircle className="h-3.5 w-3.5 text-destructive mr-2" />
                        )}
                        <span>{doc.status}</span>
                      </div>
                    </td>
                    <td className="py-2 px-3">
                      <div className="flex items-center">
                        {getEmbeddingsStatusIcon(doc)}
                        <span>
                          {getEmbeddingsStatusText(doc)}
                          {doc.embeddings?.error && (
                            <TooltipProvider>
                              <Tooltip>
                                <TooltipTrigger asChild>
                                  <span className="ml-1 cursor-help text-destructive">
                                    <AlertCircle className="h-3 w-3 inline" />
                                  </span>
                                </TooltipTrigger>
                                <TooltipContent>
                                  <p className="text-xs max-w-[200px]">{doc.embeddings.error}</p>
                                </TooltipContent>
                              </Tooltip>
                            </TooltipProvider>
                          )}
                        </span>
                      </div>
                    </td>
                  </tr>
                ))
              )}
            </tbody>
          </table>
        </div>
      </div>

      {isGenerating && (
        <div className="border rounded-md p-4 bg-primary/5 mt-4">
          <div className="flex items-center gap-2 text-sm">
            <Loader2 className="h-4 w-4 animate-spin text-primary" />
            <span>{status}</span>
          </div>
          <div className="mt-2 h-1 w-full bg-muted overflow-hidden rounded-full">
            <div className="h-full bg-primary rounded-full animate-progress"></div>
          </div>
        </div>
      )}
    </>
  )
}

// Add this function near the top of the file
function RadioButton({ id, name, value, checked, onChange, disabled = false, children }: {
  id: string;
  name: string;
  value: string;
  checked: boolean;
  onChange: (e: React.ChangeEvent<HTMLInputElement>) => void;
  disabled?: boolean;
  children: React.ReactNode;
}) {
  return (
    <div className="flex items-center space-x-2">
      <input
        type="radio"
        id={id}
        name={name}
        value={value}
        checked={checked}
        onChange={onChange}
        disabled={disabled}
        className="h-4 w-4 border-border text-primary focus:ring-primary"
      />
      <label htmlFor={id} className={`text-sm cursor-pointer ${disabled ? "opacity-50" : ""}`}>
        {children}
      </label>
    </div>
  );
}

// Triple extraction content component
function TriplesContent({
  documents,
  selectedDocs,
  handleSelectAll,
  handleItemClick,
  isSelected,
  extractTriples,
  isProcessing,
  useLangChain,
  setUseLangChain,
  useSentenceChunking,
  setUseSentenceChunking,
  useEntityExtraction,
  setUseEntityExtraction,
  error,
  status,
  handleStopProcessing
}: TriplesContentProps) {
  // Add sorting state
  const [sortField, setSortField] = useState<'name' | 'size' | 'status'>('name')
  const [sortDirection, setSortDirection] = useState<'asc' | 'desc'>('asc')

  // Sort documents based on current sort field and direction
  const sortedDocuments = React.useMemo(() => {
    return [...documents].sort((a, b) => {
      let aValue: string | number
      let bValue: string | number

      switch (sortField) {
        case 'name':
          aValue = a.name.toLowerCase()
          bValue = b.name.toLowerCase()
          break
        case 'size':
          aValue = parseFloat(a.size) || 0
          bValue = parseFloat(b.size) || 0
          break
        case 'status':
          aValue = a.status
          bValue = b.status
          break
        default:
          aValue = a.name.toLowerCase()
          bValue = b.name.toLowerCase()
      }

      if (sortDirection === 'asc') {
        return aValue < bValue ? -1 : aValue > bValue ? 1 : 0
      } else {
        return aValue > bValue ? -1 : aValue < bValue ? 1 : 0
      }
    })
  }, [documents, sortField, sortDirection])

  // Handle column header click for sorting
  const handleSort = (field: 'name' | 'size' | 'status') => {
    if (sortField === field) {
      setSortDirection(sortDirection === 'asc' ? 'desc' : 'asc')
    } else {
      setSortField(field)
      setSortDirection('asc')
    }
  }
  const [langChainMethod, setLangChainMethod] = React.useState<'default' | 'graphtransformer'>(
    'default'
  );
  const [promptConfigs, setPromptConfigs] = useState<PromptConfigurations | null>(null);
  
  // Chunk configuration state
  const [chunkSize, setChunkSize] = useState<number>(512);
  const [overlapSize, setOverlapSize] = useState<number>(0);
  const [chunkingMethod, setChunkingMethod] = useState<'optimized' | 'pyg'>('pyg');

  // Handle radio button changes for LangChain method
  const handleLangChainMethodChange = (e: React.ChangeEvent<HTMLInputElement>) => {
    setLangChainMethod(e.target.value as 'default' | 'graphtransformer');
  };

  // Load prompt configurations from localStorage on component mount
  useEffect(() => {
    try {
      const savedConfigs = localStorage.getItem("promptConfigurations");
      if (savedConfigs) {
        setPromptConfigs(JSON.parse(savedConfigs));
      }
    } catch (err) {
      console.error("Error loading prompt configurations:", err);
    }
  }, []);

  // Handle prompt configuration changes
  const handlePromptConfigsChange = (configs: PromptConfigurations) => {
    setPromptConfigs(configs);
  };

  // Update actual flag used by API based on both useLangChain and langChainMethod
  React.useEffect(() => {
    // This effect is used to monitor langChainMethod changes
    // The actual implementation of different methods is handled in the API
  }, [langChainMethod]);

  // Handle extract triples button click
  const handleExtractTriples = () => {
    const options = {
      ...(promptConfigs || {}),
      chunkSize,
      overlapSize,
      chunkingMethod
    };
    extractTriples(options);
  };

  return (
    <>
      <div className="flex items-center gap-3 mb-4">
        <div className="w-6 h-6 rounded-md bg-nvidia-green/15 flex items-center justify-center">
          <Zap className="h-3 w-3 text-nvidia-green" />
        </div>
        <h3 className="text-base font-semibold text-foreground">Knowledge Graph Triple Extraction</h3>
      </div>
      <p className="text-sm text-muted-foreground leading-relaxed mb-4">
        Extract structured knowledge triples from documents for knowledge graph construction
      </p>

      <div className="space-y-4">
        <h4 className="text-sm font-semibold text-foreground">Processing Options</h4>
        
        <div className="space-y-2">
          {/* Hidden: Use LangChain toggle - LangChain is always used for triple extraction */}
          {/* <div className="flex items-center space-x-2">
            <Switch
              id="use-langchain-triples"
              checked={useLangChain}
              onCheckedChange={setUseLangChain}
              disabled={isProcessing}
            />
            <Label htmlFor="use-langchain-triples" className="text-sm cursor-pointer">Use LangChain</Label>
          </div> */}
          {/* <p className="text-xs text-muted-foreground pl-7">
            Leverages LangChain for knowledge extraction from documents
          </p> */}

          {false && useLangChain && (
            <div className="mt-3">
              <AdvancedOptions title="LangChain Options" defaultOpen={false}>
                <div className="space-y-3">
                  <div>
                    <h5 className="text-sm font-medium mb-2">LangChain Method</h5>
                    
                    <RadioButton
                      id="default-extractor"
                      name="langchain-method"
                      value="default"
                      checked={langChainMethod === 'default'}
                      onChange={handleLangChainMethodChange}
                      disabled={isProcessing}
                    >
                      Default Extractor
                    </RadioButton>
                    <p className="text-xs text-muted-foreground ml-6 mb-2">
                      Uses the standard LangChain extraction pipeline
                    </p>
                    
                    <RadioButton
                      id="graph-transformer"
                      name="langchain-method"
                      value="graphtransformer"
                      checked={langChainMethod === 'graphtransformer'}
                      onChange={handleLangChainMethodChange}
                      disabled={isProcessing}
                    >
                      LLMGraphTransformer
                    </RadioButton>
                    <p className="text-xs text-muted-foreground ml-6 mb-3">
                      Uses LangChain's specialized graph structure transformer
                    </p>
                  </div>
                  
                  <div>
                    <div className="flex items-center space-x-2">
                      <Switch 
                        id="use-sentence-chunking-triples" 
                        checked={useSentenceChunking}
                        onCheckedChange={setUseSentenceChunking}
                        disabled={isProcessing}
                      />
                      <Label 
                        htmlFor="use-sentence-chunking-triples" 
                        className="text-sm cursor-pointer"
                      >
                        Use Sentence Chunking
                      </Label>
                    </div>
                    <p className="text-xs text-muted-foreground pl-7 mb-3">
                      Split documents into sentences for more accurate triple extraction
                    </p>
                  </div>
                  
                  <div>
                    <div className="flex items-center space-x-2">
                      <Switch 
                        id="use-entity-extraction-triples" 
                        checked={useEntityExtraction}
                        onCheckedChange={setUseEntityExtraction}
                        disabled={isProcessing}
                      />
                      <Label 
                        htmlFor="use-entity-extraction-triples" 
                        className="text-sm cursor-pointer"
                      >
                        Entity Extraction
                      </Label>
                    </div>
                    <p className="text-xs text-muted-foreground pl-7">
                      Automatically detect and extract entities from documents
                    </p>
                  </div>
                </div>
              </AdvancedOptions>
            </div>
          )}
        </div>
      </div>
      
      {/* Chunk Configuration */}
      <div className="mt-4">
        <AdvancedOptions title="Chunk Configuration" defaultOpen={false}>
          <div className="space-y-4">
            {/* Chunking Method Selection */}
            <div>
              <Label className="text-sm font-medium mb-3 block">Chunking Method</Label>
              <div className="space-y-2">
                <div className="flex items-center space-x-2">
                  <input
                    type="radio"
                    id="chunking-optimized"
                    name="chunking-method"
                    value="optimized"
                    checked={chunkingMethod === 'optimized'}
                    onChange={(e) => setChunkingMethod(e.target.value as 'optimized' | 'pyg')}
                    disabled={isProcessing}
                    className="w-4 h-4 text-primary border-border focus:ring-primary"
                  />
                  <Label htmlFor="chunking-optimized" className="text-sm cursor-pointer">
                    Large chunks
                  </Label>
                </div>
                <p className="text-xs text-muted-foreground ml-6 mb-2">
                  Large chunks with overlap for modern LLMs like Gemma3:27b. Best for efficiency.
                </p>
                
                <div className="flex items-center space-x-2">
                  <input
                    type="radio"
                    id="chunking-pyg"
                    name="chunking-method"
                    value="pyg"
                    checked={chunkingMethod === 'pyg'}
                    onChange={(e) => setChunkingMethod(e.target.value as 'optimized' | 'pyg')}
                    disabled={isProcessing}
                    className="w-4 h-4 text-primary border-border focus:ring-primary"
                  />
                  <Label htmlFor="chunking-pyg" className="text-sm cursor-pointer">
                    Default (configurable size and overlap)
                  </Label>
                </div>
                <p className="text-xs text-muted-foreground ml-6 mb-3">
                  PyG's txt2kg.py chunking algorithm with configurable chunk size and overlap.
                </p>
              </div>
            </div>
            
            <div>
              <Label htmlFor="chunk-size" className="text-sm font-medium">
                Chunk Size (characters)
              </Label>
              <div className="mt-1">
                <input
                  id="chunk-size"
                  type="number"
                  min="1000"
                  max="128000"
                  step="1000"
                  value={chunkSize}
                  onChange={(e) => setChunkSize(Number(e.target.value))}
                  disabled={isProcessing}
                  className="w-full px-3 py-2 border border-border rounded-md bg-background text-foreground focus:outline-none focus:ring-2 focus:ring-primary focus:border-transparent"
                />
              </div>
              <p className="text-xs text-muted-foreground mt-1">
                Larger chunks provide more context but use more GPU memory and may lose detailed information.
              </p>
            </div>
            
            <div>
              <Label htmlFor="overlap-size" className="text-sm font-medium">
                Overlap Size (characters)
              </Label>
              <div className="mt-1">
                <input
                  id="overlap-size"
                  type="number"
                  min="0"
                  max="8000"
                  step="100"
                  value={overlapSize}
                  onChange={(e) => setOverlapSize(Number(e.target.value))}
                  disabled={isProcessing}
                  className="w-full px-3 py-2 border border-border rounded-md bg-background text-foreground focus:outline-none focus:ring-2 focus:ring-primary focus:border-transparent"
                />
              </div>
              <p className="text-xs text-muted-foreground mt-1">
                Overlap between chunks to preserve context across boundaries. Set to 0 for original PyG behavior.
              </p>
            </div>
            
            <div className="bg-muted/30 rounded-md p-3">
              <div className="flex items-center gap-2 mb-2">
                <div className="w-4 h-4 rounded bg-primary/20 flex items-center justify-center">
                  <span className="text-xs text-primary">ℹ</span>
                </div>
                <span className="text-xs font-medium">Current Configuration</span>
              </div>
              <div className="text-xs text-muted-foreground space-y-1">
                {chunkingMethod === 'pyg' ? (
                  <>
                    <div>• Method: PyTorch Geometric (enhanced with overlap)</div>
                    <div>• Estimated chunks for 64KB document: ~{Math.ceil(64000 / Math.max(1, chunkSize - overlapSize))}</div>
                    <div>• Chunk size: {chunkSize.toLocaleString()} characters</div>
                    <div>• Overlap: {overlapSize} characters {overlapSize === 0 ? '(original PyG)' : '(enhanced)'}</div>
                    <div>• Best for: {overlapSize === 0 ? 'PyG compatibility' : 'Enhanced context preservation'}</div>
                  </>
                ) : (
                  <>
                    <div>• Method: Optimized for modern LLMs</div>
                    <div>• Estimated chunks for 64KB document: ~{Math.ceil(64000 / chunkSize)}</div>
                    <div>• GPU memory per chunk: ~{Math.round(chunkSize / 1000)}MB</div>
                    <div>• Overlap: {overlapSize} characters</div>
                    <div>• Processing efficiency: {chunkSize >= 32000 ? 'Optimal' : chunkSize >= 16000 ? 'Good' : 'Basic'}</div>
                  </>
                )}
              </div>
            </div>
          </div>
        </AdvancedOptions>
      </div>
      
      {/* Advanced Options with Prompt Configuration */}
      <div className="mt-4">
        <AdvancedOptions title="Prompt Configuration">
          <PromptConfiguration 
            onChange={handlePromptConfigsChange}
            initialConfigs={promptConfigs || undefined}
            langChainMethod={langChainMethod}
            useLangChain={useLangChain}
          />
        </AdvancedOptions>
      </div>
      
      {error && (
        <div className="bg-destructive/10 border border-destructive rounded-md p-3 flex items-start gap-2 mt-4">
          <AlertCircle className="h-4 w-4 text-destructive mt-0.5 flex-shrink-0" />
          <p className="text-sm text-destructive">{error}</p>
        </div>
      )}

      <div className="border rounded-md overflow-hidden mt-4">
        <div className="bg-muted/30 p-3 flex items-center justify-between">
          <div className="flex items-center">
            <input
              type="checkbox"
              className="rounded border-border text-primary focus:ring-primary mr-3 h-4 w-4"
              checked={selectedDocs.length === documents.filter(doc => (doc.status === "New" || doc.status === "Processed" || doc.status === "Error")).length && 
                      documents.filter(doc => (doc.status === "New" || doc.status === "Processed" || doc.status === "Error")).length > 0}
              onChange={handleSelectAll}
              disabled={documents.filter(doc => (doc.status === "New" || doc.status === "Processed" || doc.status === "Error")).length === 0 || isProcessing}
            />
            <span className="text-sm font-medium">
              {selectedDocs.length > 0 ? (
                <span className="text-primary">{selectedDocs.length} selected</span>
              ) : (
                "Select all"
              )}
            </span>
          </div>
          
          <div className="flex gap-3 pt-4">
            <Button
              size="default"
              onClick={handleExtractTriples}
              disabled={selectedDocs.length === 0 || isProcessing}
              className="bg-nvidia-green hover:bg-nvidia-green/90 text-white font-medium px-6 py-2 gap-2"
            >
              {isProcessing ? (
                <>
                  <Loader2 className="h-4 w-4 animate-spin" />
                  <span>Processing...</span>
                </>
              ) : (
                <>
                  <Zap className="h-4 w-4" />
                  <span>Extract Triples</span>
                </>
              )}
            </Button>
            
            {isProcessing && (
              <Button
                size="default"
                variant="destructive"
                onClick={handleStopProcessing}
                className="px-4 py-2 gap-2"
              >
                <X className="h-4 w-4" />
                <span>Stop</span>
              </Button>
            )}
          </div>
        </div>

        <div className="max-h-[200px] overflow-y-auto">
          {documents.length === 0 ? (
            <div className="p-6 text-center">
              <p className="text-muted-foreground">No documents available for processing</p>
            </div>
          ) : (
            <table className="w-full text-sm">
              <thead className="bg-muted/50">
                <tr>
                  <th className="w-12 py-2 px-3 text-left"></th>
                  <th 
                    className="py-2 px-3 text-left cursor-pointer hover:bg-muted/30 transition-colors"
                    onClick={() => handleSort('name')}
                  >
                    <div className="flex items-center gap-1">
                      <span>Document</span>
                      {sortField === 'name' && (
                        sortDirection === 'asc' ? 
                          <ChevronUp className="h-3 w-3" /> : 
                          <ChevronDown className="h-3 w-3" />
                      )}
                    </div>
                  </th>
                  <th 
                    className="py-2 px-3 text-left cursor-pointer hover:bg-muted/30 transition-colors"
                    onClick={() => handleSort('size')}
                  >
                    <div className="flex items-center gap-1">
                      <span>Size</span>
                      {sortField === 'size' && (
                        sortDirection === 'asc' ? 
                          <ChevronUp className="h-3 w-3" /> : 
                          <ChevronDown className="h-3 w-3" />
                      )}
                    </div>
                  </th>
                  <th 
                    className="py-2 px-3 text-left cursor-pointer hover:bg-muted/30 transition-colors"
                    onClick={() => handleSort('status')}
                  >
                    <div className="flex items-center gap-1">
                      <span>Status</span>
                      {sortField === 'status' && (
                        sortDirection === 'asc' ? 
                          <ChevronUp className="h-3 w-3" /> : 
                          <ChevronDown className="h-3 w-3" />
                      )}
                    </div>
                  </th>
                </tr>
              </thead>
              <tbody>
                {sortedDocuments.map((doc) => (
                  <tr 
                    key={doc.id} 
                    className={`border-b last:border-b-0 hover:bg-muted/20 ${(doc.status === "New" || doc.status === "Processed" || doc.status === "Error") && !isProcessing ? "cursor-pointer" : ""}`}
                    onClick={(e) => (doc.status === "New" || doc.status === "Processed" || doc.status === "Error") && !isProcessing && handleItemClick(doc, e)}
                  >
                    <td className="pl-3 py-3" onClick={(e) => e.stopPropagation()}>
                      <input
                        type="checkbox"
                        className="rounded border-border text-primary focus:ring-primary h-4 w-4"
                        checked={isSelected(doc.id)}
                        onChange={(e) => {
                          e.stopPropagation();
                          handleItemClick(doc, e);
                        }}
                        disabled={(doc.status !== "New" && doc.status !== "Processed" && doc.status !== "Error") || isProcessing}
                      />
                    </td>
                    <td className="px-3 py-3 font-medium text-foreground">
                      <div className="flex items-center gap-2">
                        <FileText className="h-4 w-4 text-muted-foreground" />
                        <span>{doc.name}</span>
                      </div>
                    </td>
                    <td className="px-3 py-3">
                      {doc.status === "New" && (
                        <span className="inline-flex items-center">
                          <span className="h-2 w-2 rounded-full bg-cyan-400 mr-2"></span>
                          <span>{doc.status}</span>
                        </span>
                      )}
                      {doc.status === "Processing" && (
                        <span className="inline-flex items-center">
                          <Loader2 className="h-4 w-4 text-yellow-500 mr-2 animate-spin" />
                          <span>{doc.status}</span>
                        </span>
                      )}
                      {doc.status === "Processed" && (
                        <span className="inline-flex items-center">
                          <CheckCircle className="h-4 w-4 text-green-500 mr-2" />
                          <span>{doc.status}</span>
                        </span>
                      )}
                      {doc.status === "Error" && (
                        <span className="inline-flex items-center">
                          <AlertCircle className="h-4 w-4 text-destructive mr-2" />
                          <span>{doc.status}</span>
                        </span>
                      )}
                    </td>
                    <td className="px-3 py-3">{doc.size} KB</td>
                  </tr>
                ))}
              </tbody>
            </table>
          )}
        </div>
      </div>

      {isProcessing && status && (
        <div className="border rounded-md p-4 bg-primary/5 mt-4">
          <div className="flex items-center gap-2 text-sm">
            <Loader2 className="h-4 w-4 animate-spin text-primary" />
            <span>{status}</span>
          </div>
          <div className="mt-2 h-1 w-full bg-muted overflow-hidden rounded-full">
            <div className="h-full bg-primary rounded-full animate-progress"></div>
          </div>
        </div>
      )}
    </>
  )
}

function InfoIcon(props: React.SVGProps<SVGSVGElement>) {
  return (
    <svg
      xmlns="http://www.w3.org/2000/svg"
      viewBox="0 0 24 24"
      fill="none"
      stroke="currentColor"
      strokeWidth="2"
      strokeLinecap="round"
      strokeLinejoin="round"
      {...props}
    >
      <circle cx="12" cy="12" r="10" />
      <path d="M12 16v-4" />
      <path d="M12 8h.01" />
    </svg>
  )
}
