/* eslint-disable react-hooks/exhaustive-deps */
import { useState, useEffect } from 'react';
import cleanupPreset from '~/utils/cleanupPreset.js';
import { useRecoilValue, useRecoilState } from 'recoil';
import EditPresetDialog from '../../Endpoints/EditPresetDialog';
import EndpointItems from './EndpointItems';
import PresetItems from './PresetItems';
import { Trash2 } from 'lucide-react';
import FileUpload from './FileUpload';
import getIcon from '~/utils/getIcon';
import getDefaultConversation from '~/utils/getDefaultConversation';
import { useDeletePresetMutation, useCreatePresetMutation } from '@librechat/data-provider';
import {
  Button,
  DropdownMenu,
  DropdownMenuContent,
  DropdownMenuLabel,
  DropdownMenuRadioGroup,
  DropdownMenuSeparator,
  DropdownMenuTrigger,
  DialogTemplate,
  Dialog,
  DialogTrigger,
} from '../../ui/';
import { cn } from '~/utils/';

import store from '~/store';

export default function NewConversationMenu() {
  const [menuOpen, setMenuOpen] = useState(false);
  const [showPresets, setShowPresets] = useState(true);
  const [showEndpoints, setShowEndpoints] = useState(true);
  const [presetModelVisible, setPresetModelVisible] = useState(false);
  const [preset, setPreset] = useState(false);
  const [conversation, setConversation] = useRecoilState(store.conversation) || {};
  const [messages, setMessages] = useRecoilState(store.messages);
  const availableEndpoints = useRecoilValue(store.availableEndpoints);
  const endpointsConfig = useRecoilValue(store.endpointsConfig);
  const [presets, setPresets] = useRecoilState(store.presets);
  const modularEndpoints = new Set(['gptPlugins', 'anthropic', 'google', 'openAI']);

  const { endpoint, conversationId } = conversation;
  const { newConversation } = store.useConversation();

  const deletePresetsMutation = useDeletePresetMutation();
  const createPresetMutation = useCreatePresetMutation();

  const importPreset = (jsonData) => {
    createPresetMutation.mutate(
      { ...jsonData },
      {
        onSuccess: (data) => {
          setPresets(data);
        },
        onError: (error) => {
          console.error('Error uploading the preset:', error);
        },
      },
    );
  };

  const onFileSelected = (jsonData) => {
    const jsonPreset = { ...cleanupPreset({ preset: jsonData, endpointsConfig }), presetId: null };
    importPreset(jsonPreset);
  };

  // update the default model when availableModels changes
  // typically, availableModels changes => modelsFilter or customGPTModels changes
  useEffect(() => {
    const isInvalidConversation = !availableEndpoints.find((e) => e === endpoint);
    if (conversationId == 'new' && isInvalidConversation) {
      newConversation();
    }
  }, [availableEndpoints]);

  // save selected model to localStorage
  useEffect(() => {
    if (endpoint) {
      const lastSelectedModel = JSON.parse(localStorage.getItem('lastSelectedModel')) || {};
      localStorage.setItem(
        'lastSelectedModel',
        JSON.stringify({ ...lastSelectedModel, [endpoint]: conversation.model }),
      );
      localStorage.setItem('lastConversationSetup', JSON.stringify(conversation));
    }

    if (endpoint === 'bingAI') {
      const lastBingSettings = JSON.parse(localStorage.getItem('lastBingSettings')) || {};
      const { jailbreak, toneStyle } = conversation;
      localStorage.setItem(
        'lastBingSettings',
        JSON.stringify({ ...lastBingSettings, jailbreak, toneStyle }),
      );
    }
  }, [conversation]);

  // set the current model
  const onSelectEndpoint = (newEndpoint) => {
    setMenuOpen(false);
    if (!newEndpoint) {
      return;
    } else {
      newConversation({}, { endpoint: newEndpoint });
    }
  };

  // set the current model
  const onSelectPreset = (newPreset) => {
    setMenuOpen(false);

    if (modularEndpoints.has(endpoint) && modularEndpoints.has(newPreset?.endpoint)) {
      const currentConvo = getDefaultConversation({
        conversation,
        endpointsConfig,
        preset: newPreset,
      });

      setConversation(currentConvo);
      setMessages(messages);
      return;
    }

    if (!newPreset) {
      return;
    }

    newConversation({}, newPreset);
  };

  const onChangePreset = (preset) => {
    setPresetModelVisible(true);
    setPreset(preset);
  };

  const clearAllPresets = () => {
    deletePresetsMutation.mutate({ arg: {} });
  };

  const onDeletePreset = (preset) => {
    deletePresetsMutation.mutate({ arg: preset });
  };

  const icon = getIcon({
    size: 32,
    ...conversation,
    isCreatedByUser: false,
    error: false,
    button: true,
  });

  return (
    <Dialog className="z-[100]">
      <DropdownMenu open={menuOpen} onOpenChange={setMenuOpen}>
        <DropdownMenuTrigger asChild>
          <Button
            id="new-conversation-menu"
            variant="outline"
            className={
              'group relative mb-[-12px] ml-0 mt-[-8px] items-center rounded-md border-0 p-1 outline-none focus:ring-0 focus:ring-offset-0 dark:data-[state=open]:bg-opacity-50 md:left-1 md:ml-[-12px] md:pl-1'
            }
          >
            {icon}
            <span className="max-w-0 overflow-hidden whitespace-nowrap px-0 text-slate-600 transition-all group-hover:max-w-[80px] group-hover:px-2 group-data-[state=open]:max-w-[80px] group-data-[state=open]:px-2 dark:text-slate-300">
              New Topic
            </span>
          </Button>
        </DropdownMenuTrigger>
        <DropdownMenuContent
          className="z-[100] w-96 dark:bg-gray-900"
          onCloseAutoFocus={(event) => event.preventDefault()}
        >
          <DropdownMenuLabel
            className="cursor-pointer dark:text-gray-300"
            onClick={() => setShowEndpoints((prev) => !prev)}
          >
            {showEndpoints ? 'Hide ' : 'Show '} Endpoints
          </DropdownMenuLabel>
          <DropdownMenuSeparator />
          <DropdownMenuRadioGroup
            value={endpoint}
            onValueChange={onSelectEndpoint}
            className="flex flex-col gap-1 overflow-y-auto"
          >
            {showEndpoints &&
              (availableEndpoints.length ? (
                <EndpointItems
                  selectedEndpoint={endpoint}
                  endpoints={availableEndpoints}
                  onSelect={onSelectEndpoint}
                />
              ) : (
                <DropdownMenuLabel className="dark:text-gray-300">
                  No endpoint available.
                </DropdownMenuLabel>
              ))}
          </DropdownMenuRadioGroup>

          <div className="mt-2 w-full" />

          <DropdownMenuLabel className="flex items-center dark:text-gray-300">
            <span
              className="mr-auto cursor-pointer "
              onClick={() => setShowPresets((prev) => !prev)}
            >
              {showPresets ? 'Hide ' : 'Show '} Presets
            </span>
            <FileUpload onFileSelected={onFileSelected} />
            <Dialog>
              <DialogTrigger asChild>
                <label
                  htmlFor="file-upload"
                  className="mr-1 flex h-[32px] h-auto cursor-pointer  items-center rounded bg-transparent px-2 py-1 text-xs font-medium font-normal text-gray-600 transition-colors hover:bg-slate-200 hover:text-red-700 dark:bg-transparent dark:text-gray-300 dark:hover:bg-gray-800 dark:hover:text-green-500"
                >
                  {/* <Button
                  type="button"
                  className="h-auto bg-transparent px-2 py-1 text-xs font-medium font-normal text-red-700 hover:bg-slate-200 hover:text-red-700 dark:bg-transparent dark:text-red-400 dark:hover:bg-gray-800 dark:hover:text-red-400"
                > */}
                  <Trash2 className="mr-1 flex w-[22px] items-center stroke-1" />
                  Clear All
                  {/* </Button> */}
                </label>
              </DialogTrigger>
              <DialogTemplate
                title="Clear presets"
                description="Are you sure you want to clear all presets? This is irreversible."
                selection={{
                  selectHandler: clearAllPresets,
                  selectClasses: 'bg-red-600 hover:bg-red-700 dark:hover:bg-red-800 text-white',
                  selectText: 'Clear',
                }}
              />
            </Dialog>
          </DropdownMenuLabel>
          <DropdownMenuSeparator />
          <DropdownMenuRadioGroup
            onValueChange={onSelectPreset}
            className={cn(
              'overflow-y-auto overflow-x-hidden',
              showEndpoints ? 'max-h-[210px]' : 'max-h-[315px]',
            )}
          >
            {showPresets &&
              (presets.length ? (
                <PresetItems
                  presets={presets}
                  onSelect={onSelectPreset}
                  onChangePreset={onChangePreset}
                  onDeletePreset={onDeletePreset}
                />
              ) : (
                <DropdownMenuLabel className="dark:text-gray-300">No preset yet.</DropdownMenuLabel>
              ))}
          </DropdownMenuRadioGroup>
        </DropdownMenuContent>
      </DropdownMenu>
      <EditPresetDialog
        open={presetModelVisible}
        onOpenChange={setPresetModelVisible}
        preset={preset}
      />
    </Dialog>
  );
}
