import React, { useCallback, useEffect, useState } from "react";
import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs";
import { Label } from "@/components/ui/label";
import { Slider } from "@/components/ui/slider";
import { Button } from "@/components/ui/button";
import {
  Card,
  CardContent,
  CardDescription,
  CardHeader,
  CardTitle,
} from "@/components/ui/card";
import { Input } from "@/components/ui/input";
import { Separator } from "@/components/ui/separator";
import {
  FileText,
  Link2,
  Settings,
  Volume2,
  Mic,
  Circle,
  CircleDot,
  Loader2,
  Text,
} from "lucide-react";
import { useAppDispatch, useAppSelector } from "@/redux/hooks";
import {
  setActiveVoice,
  setMaxTokens,
  setSilenceDuration,
  setTemperature,
  setThreshold,
} from "@/redux/slices/settingsSlice";
import {
  setEmbeddingsText,
  clearEmbeddings,
  setisUploadingEmbeddings,
  setActiveChatPrompt,
  toggleSavingPrompt,
} from "@/redux/slices/chatSlice";
import api from "@/api/apiClient";
import { toast } from "sonner";
import { Textarea } from "./ui/textarea";
import { cn } from "@/lib/utils";

const voices = [
  { id: 0, name: "Tripati (F)", voice_name: "af" },
  { id: 1, name: "Bella (F)", voice_name: "af_bella" },
  { id: 2, name: "Sarah (F)", voice_name: "af_sarah" },
  { id: 3, name: "Adam (M)", voice_name: "am_adam" },
  { id: 4, name: "Michael (M)", voice_name: "am_michael" },
  { id: 5, name: "Emma (F)", voice_name: "bf_emma" },
  {
    id: 6,
    name: "Isabella (F)",
    voice_name: "bf_isabella",
  },
  { id: 7, name: "George (M)", voice_name: "bm_george" },
  { id: 8, name: "Lewis (M)", voice_name: "bm_lewis" },
  { id: 9, name: "Nicole (F)", voice_name: "af_nicole" },
  { id: 10, name: "Sky (M)", voice_name: "af_sky" },
];

const ControlPanel = () => {
  const [linkUrl, setLinkUrl] = useState("");
  const [text, settext] = useState("");
  const [title, setTitle] = useState("");
  const [summary, setSummary] = useState("");
  const [categories, setCategories] = useState("");
  const [selectedTab, setSelectedTab] = useState("voice");
  const [contextDeleting, setContextDeleting] = useState(false);
  const [selectedFile, setSelectedFile] = useState<File | null>(null);
  const dispatch = useAppDispatch();
  const { activeChat } = useAppSelector((state) => state.chats);
  const {
    activeChatContext,
    uploadingEmbeddings,
    activeChatPrompt,
    savingPrompt,
  } = useAppSelector((state) => state.chat);
  const [localPromptState, setLocalPromptState] = useState("");

  useEffect(() => {
    setLocalPromptState(activeChatPrompt);
  }, [activeChatPrompt]);

  const { activeVoice, temperature, maxTokens, silenceDuration, threshold } =
    useAppSelector((state) => state.settings);

  const handleFileChange = (e: React.ChangeEvent<HTMLInputElement>) => {
    if (e.target.files && e.target.files[0]) {
      setSelectedFile(e.target.files[0]);
    }
  };

  const handleEmbeddingList = async (
    name: string,
    title: string,
    summary: string,
    categories: string
  ) => {
    let categoriesList = [];
    if (categories != null) {
      if (typeof categories === "string") {
        categoriesList = categories
          .split(",")
          .map((cat) => cat.trim())
          .filter((cat) => cat.length > 0);
      } else if (Array.isArray(categories)) {
        categoriesList = categories.map((cat) => String(cat));
      } else {
        categoriesList = [String(categories)];
      }
    }

    dispatch(
      setEmbeddingsText({
        name: name,
        title: title,
        summary: summary,
        categories: categoriesList,
      })
    );
  };

  const cleatMetaData = () => {
    setTitle("");
    setSummary("");
    setCategories("");
  };

  const handleSavePrompt = async () => {
    if (localPromptState === activeChatPrompt) return;
    setLocalPromptState(activeChatPrompt);
    dispatch(toggleSavingPrompt());
    try {
      if (!activeChatPrompt) {
        toast.error("Please add prompt to save the prompt.");
        return;
      }
      const response = await api.post("/prompt", {
        sessionId: activeChat,
        prompt: localPromptState,
      });
      if (!response.success) {
        toast.error("Failed to save prompt. Please try again");
        return;
      }
      dispatch(setActiveChatPrompt(localPromptState));
      toast.success("System Prompt saved successfully.");
    } catch (_) {
      toast.error("Failed to save prompt. Please try again");
    } finally {
      dispatch(toggleSavingPrompt());
    }
  };

  const handleLinkAdd = useCallback(async () => {
    try {
      dispatch(setisUploadingEmbeddings(true));
      if (!linkUrl.trim()) {
        toast.error("Please provide a url");
        return;
      }
      if (!activeChat) {
        toast.error("Please select or create a chat.");
        return;
      }
      const response = await api.post("/rag/link", {
        link: linkUrl,
        sessionId: activeChat,
        title: title,
        summary: summary,
        categories: categories,
      });
      if (!response.success) {
        toast.error("failed to process link. Please try again");
        return;
      }
      await handleEmbeddingList(linkUrl, title, summary, categories);
      setLinkUrl("");
    } catch (error) {
      console.error("Error in processing link : ", error);
      if (
        error.response &&
        error.response.data &&
        error.response.data.message
      ) {
        toast.error(error.response.data.message);
      } else {
        // Display a generic error message
        toast.error("Failed to process link. Please try again.");
      }
      setLinkUrl("");
    } finally {
      dispatch(setisUploadingEmbeddings(false));
      // cleatMetaData();
    }
  }, [activeChat, linkUrl, dispatch, title, summary, categories]);

  const handleTextUpload = useCallback(async () => {
    try {
      dispatch(setisUploadingEmbeddings(true));
      console.log("MEtaData : ", { title, summary, categories });
      if (!text.trim()) {
        toast.error("Please provide text");
        return;
      }
      if (!activeChat) {
        toast.error("Please select or create a chat.");
        return;
      }
      const name = `${text.slice(0, 10)}...`;
      const response = await api.post("/rag/text", {
        text: text,
        sessionId: activeChat,
        title: title,
        name: name,
        summary: summary,
        categories: categories,
      });
      if (!response.success) {
        toast.error("failed to process text. Please try again");
        return;
      }
      await handleEmbeddingList(name, title, summary, categories);
    } catch (error) {
      console.error("Error in processing text : ", error);
      if (
        error.response &&
        error.response.data &&
        error.response.data.message
      ) {
        toast.error(error.response.data.message);
      } else {
        toast.error("Failed to process text. Please try again.");
      }
    } finally {
      settext("");
      dispatch(setisUploadingEmbeddings(false));
      cleatMetaData();
    }
  }, [activeChat, text, dispatch, title, summary, categories]);

  const handlePdfUpload = useCallback(async () => {
    dispatch(setisUploadingEmbeddings(true));
    if (!activeChat) {
      toast.error("Please select or create a chat.");
      return;
    }
    if (!selectedFile) {
      toast.error("Please select a PDF file to upload.");
      return;
    }
    const form = new FormData();
    form.append("pdfFile", selectedFile);
    form.append("name", selectedFile.name);
    form.append("title", title);
    form.append("summary", summary);
    form.append("categories", categories);
    form.append("sessionId", activeChat);

    const config = {
      headers: {
        "Content-Type": "multipart/form-data",
      },
    };

    try {
      const response = await api.post("/rag/pdf", form, config);
      if (!response.success) {
        toast.error("Failed to upload PDF. Please try again.");
      }
      await handleEmbeddingList(selectedFile.name, title, summary, categories);
      setSelectedFile(null);
      toast.success("PDF uploaded successfully!");
    } catch (error) {
      console.error("Error uploading PDF:", error);
      toast.error("Failed to upload PDF. Please try again.");
    } finally {
      dispatch(setisUploadingEmbeddings(false));
      cleatMetaData();
    }
  }, [selectedFile, activeChat, dispatch, title, summary, categories]);

  const handleDelete = async () => {
    try {
      if (!activeChat) {
        toast.error("Please select a chat first");
        return;
      }
      const response = await api.post("/rag/clear-context", {
        sessionId: activeChat,
      });
      if (response.success) {
        toast.success("Context cleard successfully");
        dispatch(clearEmbeddings());
        return;
      } else {
        toast.error("Failed to clear embeddings. Please try again");
      }
    } catch (error) {
      toast.error("Failed to clear embeddings. Please try again");
    } finally {
      setContextDeleting(false);
    }
  };

  const metadataForData = () => {
    return (
      <div className="w-full space-y-2">
        <Input
          type="url"
          placeholder="Title"
          className="flex-1 bg-black/60 border-white/20 text-white placeholder:text-gray-500 mt-2"
          value={title}
          onChange={(e) => setTitle(e.target.value)}
        />

        <Textarea
          className="border border-white/20 bg-transparent text-white"
          value={summary}
          rows={5}
          placeholder="Provide a summary of the content that can help improve outcomes."
          onChange={(e) => setSummary(e.target.value)}
        />
        <Textarea
          className="border border-white/20 bg-transparent text-white"
          value={categories}
          rows={5}
          placeholder={`Provide Categories (separated by commas) \neg: React New Features, Kokoro TTS Model, VocRT Documentation`}
          onChange={(e) => setCategories(e.target.value)}
        />
      </div>
    );
  };

  return (
    <div className="w-full lg:w-80 h-full bg-black overflow-y-auto p-4 border-l border-white/10 [&::-webkit-scrollbar]:hidden [-ms-overflow-style:none] [scrollbar-width:none]">
      <div className="relative overflow-hidden text-sm">
        <Tabs
          defaultValue="voice"
          value={selectedTab}
          onValueChange={setSelectedTab}
          className="w-full relative z-10"
        >
          <TabsList className="grid grid-cols-3 w-full bg-black border border-white/20 m-auto">
            <TabsTrigger
              value="voice"
              className="data-[state=active]:bg-white/10 data-[state=active]:text-white"
            >
              <Mic className="h-4 w-4 mr-2" />
              Voice
            </TabsTrigger>
            <TabsTrigger
              value="ai"
              className="data-[state=active]:bg-white/10 data-[state=active]:text-white"
            >
              AI Settings
            </TabsTrigger>
            <TabsTrigger
              value="embeddings"
              className="data-[state=active]:bg-white/10 data-[state=active]:text-white"
            >
              <Link2 className="h-4 w-4 mr-2" />
              Context
            </TabsTrigger>
          </TabsList>

          <TabsContent value="voice" className="mt-4">
            <Card className="bg-black/90 border border-white/20 backdrop-blur-lg">
              <CardHeader>
                <CardTitle className="text-white flex items-center">
                  <Volume2 className="h-5 w-5 mr-2 text-gray-400" />
                  Voice Selection
                </CardTitle>
                <CardDescription className="text-gray-400">
                  Choose a voice for your AI assistant
                </CardDescription>
              </CardHeader>
              <CardContent>
                {voices.map((voice) => (
                  <div
                    key={voice.id}
                    onClick={() => {
                      dispatch(setActiveVoice(voice?.voice_name));
                    }}
                    className={`flex items-center space-x-2 rounded-md border border-white/20 p-2 hover:bg-white/5 transition cursor-pointer mb-2 ${
                      activeVoice === voice?.voice_name ? "bg-white/10" : ""
                    }`}
                  >
                    <div className="icon-container">
                      {activeVoice === voice?.voice_name ? (
                        <CircleDot className="text-white" />
                      ) : (
                        <Circle className="text-white" />
                      )}
                    </div>
                    <div className="flex-1 cursor-pointer text-white">
                      {voice.name}
                    </div>
                    {voice.id === 0 && (
                      <div className="text-xs bg-white/10 text-gray-300 px-2 py-1 rounded">
                        Default
                      </div>
                    )}
                  </div>
                ))}
              </CardContent>
            </Card>
          </TabsContent>

          <TabsContent
            value="ai"
            className="mt-4 space-y-2 overflow-x-hidden overflow-y-auto"
          >
            <>
              <Card className="bg-black/90 border border-white/20 backdrop-blur-lg">
                <CardHeader>
                  <CardTitle className="text-white flex items-center">
                    <Settings className="h-5 w-5 mr-2 text-gray-400" />
                    System Prompt
                  </CardTitle>
                  <CardDescription className="text-gray-400">
                    Set of instructions, guidelines, and contextual information
                  </CardDescription>
                </CardHeader>
                <CardContent className="space-y-6">
                  <div className="space-y-2">
                    <Textarea
                      className="border border-white bg-transparent text-white"
                      id="text-upload"
                      placeholder="You are a helpful assistant."
                      value={localPromptState}
                      rows={10}
                      onChange={(e) => {
                        setLocalPromptState(e.target.value);
                      }}
                    />
                    <Button
                      className="w-full mt-2 bg-white/10 hover:bg-white/20 text-white border border-white/20"
                      onClick={handleSavePrompt}
                      disabled={
                        savingPrompt || activeChatPrompt === localPromptState
                      }
                    >
                      {savingPrompt ? (
                        <Loader2 className="animate-spin" />
                      ) : (
                        "Save"
                      )}
                    </Button>

                    <CardHeader>
                      <CardTitle className="text-white flex items-center">
                        <Settings className="h-5 w-5 mr-2 text-gray-400" />
                        AI Parameters
                      </CardTitle>
                      <CardDescription className="text-gray-400">
                        Adjust the AI response settings
                      </CardDescription>
                    </CardHeader>
                    <CardContent className="space-y-6">
                      <div className="space-y-2">
                        <div className="flex justify-between">
                          <Label
                            htmlFor="temperature"
                            className="text-white flex items-center"
                          >
                            Silence Duration: {silenceDuration.toFixed(1)}
                          </Label>
                        </div>
                        <Slider
                          id="silenceDuration"
                          min={0}
                          max={2}
                          step={0.1}
                          value={[silenceDuration]}
                          onValueChange={(value) => {
                            dispatch(setSilenceDuration(value[0]));
                          }}
                          className="py-4"
                        />
                        <p className="text-xs text-gray-400">
                          Lower values make VocRT to wait for short duration of
                          silence. Higher values increase latency.
                        </p>
                      </div>
                      <Separator className="bg-white/10" />
                      <div className="space-y-2">
                        <div className="flex justify-between">
                          <Label
                            htmlFor="threshold"
                            className="text-white flex items-center"
                          >
                            Threshold: {threshold}
                          </Label>
                        </div>
                        <Slider
                          id="threshold"
                          min={5}
                          max={95}
                          step={1}
                          value={[threshold]}
                          onValueChange={(value) => {
                            dispatch(setThreshold(value[0]));
                          }}
                          className="py-4 ease-in transition-all duration-300"
                        />
                        <p className="text-xs text-gray-400">
                          Lower values make VocRT to listen to low amplitude
                          voice. Higher values make VocRT to listen to your
                          Voice.
                        </p>
                      </div>
                      {/* <Separator className="bg-white/10" />
                      <div className="space-y-2">
                        <div className="flex justify-between">
                          <Label
                            htmlFor="temperature"
                            className="text-white flex items-center"
                          >
                            Temperature: {temperature.toFixed(1)}
                          </Label>
                        </div>
                        <Slider
                          id="temperature"
                          min={0}
                          max={1}
                          step={0.1}
                          value={[temperature]}
                          onValueChange={(value) => {
                            dispatch(setTemperature(value[0]));
                          }}
                          className="py-4"
                        />
                        <p className="text-xs text-gray-400">
                          Lower values make responses more focused. Higher
                          values make responses more creative.
                        </p>
                      </div> */}

                      <Separator className="bg-white/10" />

                      {/* <div className="space-y-2">
                        <div className="flex justify-between">
                          <Label htmlFor="max-tokens" className="text-white">
                            Max Tokens: {maxTokens}
                          </Label>
                        </div>
                        <Slider
                          id="max-tokens"
                          min={50}
                          max={500}
                          step={10}
                          value={[maxTokens]}
                          onValueChange={(value) => {
                            dispatch(setMaxTokens(value[0]));
                          }}
                          className="py-4"
                        />
                        <p className="text-xs text-gray-400">
                          Controls the maximum length of the AI's response.
                        </p>
                      </div> */}
                    </CardContent>
                  </div>
                </CardContent>
              </Card>
            </>
          </TabsContent>

          <TabsContent value="embeddings" className="mt-4">
            <Card className="bg-black/90 border border-white/20 backdrop-blur-lg">
              <CardHeader>
                <CardTitle className="text-white flex items-center">
                  <Link2 className="h-5 w-5 mr-2 text-gray-400" />
                  Context & Embeddings
                </CardTitle>
                <CardDescription className="text-gray-400">
                  Add additional context from various sources
                </CardDescription>
              </CardHeader>
              <CardContent className="space-y-4">
                <Tabs defaultValue="text" className="w-full">
                  <TabsList className="grid grid-cols-3 space-x-2 w-full bg-black border border-white/20">
                    <TabsTrigger
                      value="text"
                      className="text-xs data-[state=active]:bg-white/10 data-[state=active]:text-white"
                    >
                      <Text className="h-3 w-3 mr-1" /> Text
                    </TabsTrigger>
                    <TabsTrigger
                      value="pdf"
                      className="text-xs data-[state=active]:bg-white/10 data-[state=active]:text-white"
                    >
                      <FileText className="h-3 w-3 mr-1" /> PDF
                    </TabsTrigger>
                    <TabsTrigger
                      value="link"
                      className="text-xs data-[state=active]:bg-white/10 data-[state=active]:text-white"
                    >
                      <Link2 className="h-3 w-3 mr-1" /> Link
                    </TabsTrigger>
                  </TabsList>

                  <TabsContent value="text" className="mt-4 w-full">
                    <Textarea
                      className="border border-white bg-transparent text-white"
                      id="text-upload"
                      placeholder="Add Context..."
                      value={text}
                      rows={8}
                      onChange={(e) => {
                        settext(e.target.value);
                      }}
                    />
                    {metadataForData()}
                    <Button
                      className="w-full mt-2 bg-white/10 hover:bg-white/20 text-white border border-white/20"
                      onClick={handleTextUpload}
                      disabled={uploadingEmbeddings}
                    >
                      {uploadingEmbeddings ? (
                        <Loader2 className="animate-spin" />
                      ) : (
                        "Process Text"
                      )}
                    </Button>
                  </TabsContent>

                  <TabsContent value="pdf" className="mt-4">
                    <div
                      className={cn(
                        "border-2 border-dashed border-white/20 rounded-md p-6 text-center bg-white/5 hover:bg-white/10 transition cursor-pointer",
                        uploadingEmbeddings
                          ? "hover:cursor-not-allowed"
                          : "hover:cursor-pointer"
                      )}
                    >
                      <Input
                        type="file"
                        className={cn(
                          "hidden",
                          uploadingEmbeddings
                            ? "hover:cursor-not-allowed"
                            : "hover:cursor-pointer"
                        )}
                        id="pdf-upload"
                        accept=".pdf,.csv,.ppt,.pptx,.doc,.docx,.xls,.xlsx,.txt"
                        onChange={handleFileChange}
                        disabled={uploadingEmbeddings}
                      />
                      <Label
                        htmlFor="pdf-upload"
                        className={cn(
                          "cursor-pointer",
                          uploadingEmbeddings
                            ? "hover:cursor-not-allowed"
                            : "hover:cursor-pointer"
                        )}
                      >
                        <FileText className="h-10 w-10 mx-auto mb-2 text-gray-400" />
                        <p
                          className={cn(
                            "text-sm text-white mb-1",
                            uploadingEmbeddings
                              ? "hover:cursor-not-allowed"
                              : "hover:cursor-pointer"
                          )}
                        >
                          {selectedFile ? selectedFile.name : "Upload Document"}
                        </p>
                        <p className="text-xs text-gray-400">
                          Drag & drop or click to browse
                        </p>
                        <p className="text-xs text-gray-400 mt-3">
                          Accept pdf, csv, ppt, pptx, doc, docx, xls, xlsx, txt
                        </p>
                      </Label>
                    </div>
                    {selectedFile && metadataForData()}
                    {(selectedFile || uploadingEmbeddings) && (
                      <Button
                        className="w-full mt-2 bg-white/10 hover:bg-white/20 text-white border border-white/20"
                        onClick={handlePdfUpload}
                        disabled={uploadingEmbeddings}
                      >
                        {uploadingEmbeddings ? (
                          <Loader2 className="animate-spin" />
                        ) : (
                          "Process Document"
                        )}
                      </Button>
                    )}
                  </TabsContent>

                  <TabsContent value="link" className="mt-4 space-y-3 w-full">
                    <div className="">
                      <Input
                        type="url"
                        placeholder="https://example.com"
                        className="flex-1 bg-black/60 border-white/20 text-white placeholder:text-gray-500"
                        value={linkUrl}
                        onChange={(e) => setLinkUrl(e.target.value)}
                      />
                      {metadataForData()}
                      <Button
                        className="bg-white/10 hover:bg-white/20 text-white border border-white/20 w-full mt-3"
                        onClick={handleLinkAdd}
                      >
                        {uploadingEmbeddings ? (
                          <Loader2 className="animate-spin" />
                        ) : (
                          <>
                            <Link2 className="h-4 w-4 mr-1" /> Add
                          </>
                        )}
                      </Button>
                    </div>
                  </TabsContent>
                </Tabs>

                {activeChatContext && activeChatContext.length > 0 && (
                  <>
                    <h4 className="text-sm font-medium text-white mb-2">
                      Added Context:
                    </h4>
                    <Separator className="bg-white/10 my-4" />

                    {activeChatContext.map((item, index) => (
                      <>
                        <div>
                          <div className="bg-white/5 p-3 rounded-md text-sm text-gray-300 max-h-40 overflow-y-auto border border-white/10">
                            {item?.title} - {item?.name}
                          </div>
                        </div>
                      </>
                    ))}

                    <Button
                      variant="outline"
                      className="w-full border-white/20 text-gray-900 hover:bg-white/10 hover:text-white"
                      onClick={() => {
                        setContextDeleting(true);
                        handleDelete();
                      }}
                      disabled={contextDeleting}
                    >
                      {contextDeleting ? "Deleting..." : "Clear All Context"}
                    </Button>
                  </>
                )}
              </CardContent>
            </Card>
          </TabsContent>
        </Tabs>
      </div>
    </div>
  );
};

export default ControlPanel;
