import axios from 'axios';
import { useEffect, useState } from 'react';
import Settings from './Settings';
import Examples from './Google/Examples.jsx';
import exportFromJSON from 'export-from-json';
import AgentSettings from './Plugins/AgentSettings.jsx';
import { useSetRecoilState, useRecoilValue } from 'recoil';
import filenamify from 'filenamify';
import {
  MessagesSquared,
  GPTIcon,
  Input,
  Label,
  Button,
  Dropdown,
  Dialog,
  DialogClose,
  DialogButton,
  DialogTemplate,
} from '~/components/';
import { cn } from '~/utils/';
import cleanupPreset from '~/utils/cleanupPreset';
import { localize } from '~/localization/Translation';

import store from '~/store';

const EditPresetDialog = ({ open, onOpenChange, preset: _preset, title }) => {
  const lang = useRecoilValue(store.lang);
  const [preset, setPreset] = useState(_preset);
  const setPresets = useSetRecoilState(store.presets);
  const [showExamples, setShowExamples] = useState(false);
  const [showAgentSettings, setShowAgentSettings] = useState(false);

  const availableEndpoints = useRecoilValue(store.availableEndpoints);
  const endpointsConfig = useRecoilValue(store.endpointsConfig);

  const triggerExamples = () => setShowExamples((prev) => !prev);
  const triggerAgentSettings = () => setShowAgentSettings((prev) => !prev);

  const setOption = (param) => (newValue) => {
    let update = {};
    update[param] = newValue;
    setPreset((prevState) =>
      cleanupPreset({
        preset: {
          ...prevState,
          ...update,
        },
        endpointsConfig,
      }),
    );
  };

  const setAgentOption = (param) => (newValue) => {
    let editablePreset = JSON.stringify(_preset);
    editablePreset = JSON.parse(editablePreset);
    let { agentOptions } = editablePreset;
    agentOptions[param] = newValue;
    setPreset((prevState) =>
      cleanupPreset({
        preset: {
          ...prevState,
          agentOptions,
        },
        endpointsConfig,
      }),
    );
  };

  const setExample = (i, type, newValue = null) => {
    let update = {};
    let current = preset?.examples.slice() || [];
    let currentExample = { ...current[i] } || {};
    currentExample[type] = { content: newValue };
    current[i] = currentExample;
    update.examples = current;
    setPreset((prevState) =>
      cleanupPreset({
        preset: {
          ...prevState,
          ...update,
        },
        endpointsConfig,
      }),
    );
  };

  const addExample = () => {
    let update = {};
    let current = preset?.examples.slice() || [];
    current.push({ input: { content: '' }, output: { content: '' } });
    update.examples = current;
    setPreset((prevState) =>
      cleanupPreset({
        preset: {
          ...prevState,
          ...update,
        },
        endpointsConfig,
      }),
    );
  };

  const removeExample = () => {
    let update = {};
    let current = preset?.examples.slice() || [];
    if (current.length <= 1) {
      update.examples = [{ input: { content: '' }, output: { content: '' } }];
      setPreset((prevState) =>
        cleanupPreset({
          preset: {
            ...prevState,
            ...update,
          },
          endpointsConfig,
        }),
      );
      return;
    }
    current.pop();
    update.examples = current;
    setPreset((prevState) =>
      cleanupPreset({
        preset: {
          ...prevState,
          ...update,
        },
        endpointsConfig,
      }),
    );
  };

  const defaultTextProps =
    'rounded-md border border-gray-200 focus:border-slate-400 focus:bg-gray-50 bg-transparent text-sm shadow-[0_0_10px_rgba(0,0,0,0.05)] outline-none placeholder:text-gray-400 focus:outline-none focus:ring-gray-400 focus:ring-opacity-20 focus:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50 dark:border-gray-500 dark:bg-gray-700 focus:dark:bg-gray-600 dark:text-gray-50 dark:shadow-[0_0_15px_rgba(0,0,0,0.10)] dark:focus:border-gray-400 dark:focus:outline-none dark:focus:ring-0 dark:focus:ring-gray-400 dark:focus:ring-offset-0';

  const submitPreset = () => {
    axios({
      method: 'post',
      url: '/api/presets',
      data: cleanupPreset({ preset, endpointsConfig }),
      withCredentials: true,
    }).then((res) => {
      setPresets(res?.data);
    });
  };

  const exportPreset = () => {
    const fileName = filenamify(preset?.title || 'preset');
    exportFromJSON({
      data: cleanupPreset({ preset, endpointsConfig }),
      fileName,
      exportType: exportFromJSON.types.json,
    });
  };

  useEffect(() => {
    setPreset(_preset);
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [open]);

  const endpoint = preset?.endpoint;
  const isGoogle = endpoint === 'google';
  const isGptPlugins = endpoint === 'gptPlugins';
  const shouldShowSettings =
    (isGoogle && !showExamples) ||
    (isGptPlugins && !showAgentSettings) ||
    (!isGoogle && !isGptPlugins);

  return (
    <Dialog open={open} onOpenChange={onOpenChange}>
      <DialogTemplate
        title={`${title || localize(lang, 'com_endpoint_edit_preset')} - ${preset?.title}`}
        className="h-[675px] max-w-full sm:max-w-4xl "
        main={
          <div className="flex w-full flex-col items-center gap-2 md:h-[475px]">
            <div className="grid w-full gap-6 sm:grid-cols-2">
              <div className="col-span-1 flex flex-col items-start justify-start gap-2">
                <Label htmlFor="chatGptLabel" className="text-left text-sm font-medium">
                  {localize(lang, 'com_endpoint_preset_name')}
                </Label>
                <Input
                  id="chatGptLabel"
                  value={preset?.title || ''}
                  onChange={(e) => setOption('title')(e.target.value || '')}
                  placeholder={localize(lang, 'com_endpoint_set_custom_name')}
                  className={cn(
                    defaultTextProps,
                    'flex h-10 max-h-10 w-full resize-none px-3 py-2 focus:outline-none focus:ring-0 focus:ring-opacity-0 focus:ring-offset-0',
                  )}
                />
              </div>
              <div className="col-span-1 flex flex-col items-start justify-start gap-2">
                <Label htmlFor="endpoint" className="text-left text-sm font-medium">
                  {localize(lang, 'com_endpoint')}
                </Label>
                <Dropdown
                  id="endpoint"
                  value={preset?.endpoint || ''}
                  onChange={setOption('endpoint')}
                  options={availableEndpoints}
                  className={cn(
                    defaultTextProps,
                    'flex h-10 max-h-10 w-full resize-none focus:outline-none focus:ring-0 focus:ring-opacity-0 focus:ring-offset-0',
                  )}
                  containerClassName="flex w-full resize-none"
                />
                {preset?.endpoint === 'google' && (
                  <Button
                    type="button"
                    className="ml-1 flex h-auto w-full bg-transparent px-2 py-1 text-xs font-medium font-normal text-black hover:bg-slate-200 hover:text-black focus:ring-0 focus:ring-offset-0 dark:bg-transparent dark:text-white dark:hover:bg-gray-700 dark:hover:text-white dark:focus:outline-none dark:focus:ring-offset-0"
                    onClick={triggerExamples}
                  >
                    <MessagesSquared className="mr-1 w-[14px]" />
                    {(showExamples
                      ? localize(lang, 'com_endpoint_hide')
                      : localize(lang, 'com_endpoint_show')) +
                      localize(lang, 'com_endpoint_examples')}
                  </Button>
                )}
                {preset?.endpoint === 'gptPlugins' && (
                  <Button
                    type="button"
                    className="ml-1 flex h-auto w-full bg-transparent px-2 py-1 text-xs font-medium font-normal text-black hover:bg-slate-200 hover:text-black focus:ring-0 focus:ring-offset-0 dark:bg-transparent dark:text-white dark:hover:bg-gray-700 dark:hover:text-white dark:focus:outline-none dark:focus:ring-offset-0"
                    onClick={triggerAgentSettings}
                  >
                    <GPTIcon className="mr-1 mt-[2px] w-[14px]" size={14} />
                    {`Show ${showAgentSettings ? 'Completion' : 'Agent'} Settings`}
                    {localize(
                      lang,
                      'com_endpoint_show_what_settings',
                      showAgentSettings
                        ? localize(lang, 'com_endpoint_completion')
                        : localize(lang, 'com_endpoint_agent'),
                    )}
                  </Button>
                )}
              </div>
            </div>
            <div className="my-4 w-full border-t border-gray-300 dark:border-gray-500" />
            <div className="w-full p-0">
              {shouldShowSettings && <Settings preset={preset} setOption={setOption} />}
              {preset?.endpoint === 'google' &&
                showExamples &&
                !preset?.model?.startsWith('codechat-') && (
                <Examples
                  examples={preset.examples}
                  setExample={setExample}
                  addExample={addExample}
                  removeExample={removeExample}
                  edit={true}
                />
              )}
              {preset?.endpoint === 'gptPlugins' && showAgentSettings && (
                <AgentSettings
                  agent={preset.agentOptions.agent}
                  skipCompletion={preset.agentOptions.skipCompletion}
                  model={preset.agentOptions.model}
                  endpoint={preset.agentOptions.endpoint}
                  temperature={preset.agentOptions.temperature}
                  topP={preset.agentOptions.top_p}
                  freqP={preset.agentOptions.presence_penalty}
                  presP={preset.agentOptions.frequency_penalty}
                  setOption={setAgentOption}
                  tools={preset.tools}
                />
              )}
            </div>
          </div>
        }
        buttons={
          <>
            <DialogClose
              onClick={submitPreset}
              className="dark:hover:gray-400 border-gray-700 bg-green-600 text-white hover:bg-green-700 dark:hover:bg-green-800"
            >
              {localize(lang, 'com_endpoint_save')}
            </DialogClose>
          </>
        }
        leftButtons={
          <>
            <DialogButton onClick={exportPreset} className="dark:hover:gray-400 border-gray-700">
              {localize(lang, 'com_endpoint_export')}
            </DialogButton>
          </>
        }
      />
    </Dialog>
  );
};

export default EditPresetDialog;
