import { Collapse } from '@/components/collapse';
import { Button } from '@/components/ui/button';
import {
  Form,
  FormControl,
  FormField,
  FormItem,
  FormLabel,
  FormMessage,
} from '@/components/ui/form';
import { RAGFlowSelect } from '@/components/ui/select';
import { Switch } from '@/components/ui/switch';
import { Textarea } from '@/components/ui/textarea';
import { FormTooltip } from '@/components/ui/tooltip';
import { WebhookAlgorithmList } from '@/constants/agent';
import { zodResolver } from '@hookform/resolvers/zod';
import { t } from 'i18next';
import { Plus } from 'lucide-react';
import { memo, useEffect, useRef } from 'react';
import { useForm, useWatch } from 'react-hook-form';
import { useTranslation } from 'react-i18next';
import { z } from 'zod';
import { AgentDialogueMode } from '../../constant';
import { INextOperatorForm } from '../../interface';
import { ParameterDialog } from './parameter-dialog';
import { QueryTable } from './query-table';
import { useEditQueryRecord } from './use-edit-query';
import { useHandleModeChange } from './use-handle-mode-change';
import { useValues } from './use-values';
import { useWatchFormChange } from './use-watch-change';
import { WebHook } from './webhook';

const ModeOptions = [
  { value: AgentDialogueMode.Conversational, label: t('flow.conversational') },
  { value: AgentDialogueMode.Task, label: t('flow.task') },
  { value: AgentDialogueMode.Webhook, label: t('flow.webhook.name') },
];

const FormSchema = z.object({
  enablePrologue: z.boolean().optional(),
  prologue: z.string().trim().optional(),
  mode: z.string(),
  inputs: z
    .array(
      z.object({
        key: z.string(),
        type: z.string(),
        value: z.string(),
        optional: z.boolean(),
        name: z.string(),
        options: z.array(z.union([z.number(), z.string(), z.boolean()])),
      }),
    )
    .optional(),
  methods: z.string().optional(),
  content_types: z.string().optional(),
  security: z
    .object({
      auth_type: z.string(),
      ip_whitelist: z.array(z.object({ value: z.string() })),
      rate_limit: z.object({
        limit: z.number(),
        per: z.string().optional(),
      }),
      max_body_size: z.string(),
      jwt: z
        .object({
          algorithm: z.string().default(WebhookAlgorithmList[0]).optional(),
        })
        .optional(),
    })
    .optional(),
  schema: z.record(z.any()).optional(),
  response: z
    .object({
      status: z.number(),
      headers_template: z.array(
        z.object({ key: z.string(), value: z.string() }),
      ),
      body_template: z.array(z.object({ key: z.string(), value: z.string() })),
    })
    .optional(),
  execution_mode: z.string().optional(),
});

export type BeginFormSchemaType = z.infer<typeof FormSchema>;

function BeginForm({ node }: INextOperatorForm) {
  const { t } = useTranslation();

  const values = useValues(node);

  const form = useForm({
    defaultValues: values,
    resolver: zodResolver(FormSchema),
  });

  useWatchFormChange(node?.id, form);

  const inputs = useWatch({ control: form.control, name: 'inputs' });
  const mode = useWatch({ control: form.control, name: 'mode' });

  const enablePrologue = useWatch({
    control: form.control,
    name: 'enablePrologue',
  });

  const previousModeRef = useRef(mode);

  const { handleModeChange } = useHandleModeChange(form);

  useEffect(() => {
    if (
      previousModeRef.current === AgentDialogueMode.Task &&
      mode === AgentDialogueMode.Conversational
    ) {
      form.setValue('enablePrologue', true);
    }
    previousModeRef.current = mode;
  }, [mode, form]);

  const {
    ok,
    currentRecord,
    visible,
    hideModal,
    showModal,
    otherThanCurrentQuery,
    handleDeleteRecord,
  } = useEditQueryRecord({
    form,
    node,
  });

  return (
    <section className="px-5 space-y-5">
      <Form {...form}>
        <FormField
          control={form.control}
          name={'mode'}
          render={({ field }) => (
            <FormItem>
              <FormLabel tooltip={t('flow.modeTip')}>
                {t('flow.mode')}
              </FormLabel>
              <FormControl>
                <RAGFlowSelect
                  placeholder={t('common.pleaseSelect')}
                  options={ModeOptions}
                  {...field}
                  onChange={(val) => {
                    handleModeChange(val);
                    field.onChange(val);
                  }}
                ></RAGFlowSelect>
              </FormControl>
              <FormMessage />
            </FormItem>
          )}
        />
        {mode === AgentDialogueMode.Conversational && (
          <FormField
            control={form.control}
            name={'enablePrologue'}
            render={({ field }) => (
              <FormItem>
                <FormLabel tooltip={t('flow.openingSwitchTip')}>
                  {t('flow.openingSwitch')}
                </FormLabel>
                <FormControl>
                  <Switch
                    checked={field.value}
                    onCheckedChange={field.onChange}
                  />
                </FormControl>
                <FormMessage />
              </FormItem>
            )}
          />
        )}
        {mode === AgentDialogueMode.Conversational && enablePrologue && (
          <FormField
            control={form.control}
            name={'prologue'}
            render={({ field }) => (
              <FormItem>
                <FormLabel tooltip={t('chat.setAnOpenerTip')}>
                  {t('flow.openingCopy')}
                </FormLabel>
                <FormControl>
                  <Textarea
                    rows={5}
                    {...field}
                    placeholder={t('common.pleaseInput')}
                  ></Textarea>
                </FormControl>
                <FormMessage />
              </FormItem>
            )}
          />
        )}
        {mode === AgentDialogueMode.Webhook && <WebHook></WebHook>}
        {mode !== AgentDialogueMode.Webhook && (
          <>
            {/* Create a hidden field to make Form instance record this */}
            <FormField
              control={form.control}
              name={'inputs'}
              render={() => <div></div>}
            />
            <Collapse
              title={
                <div>
                  {t('flow.input')}
                  <FormTooltip tooltip={t('flow.beginInputTip')}></FormTooltip>
                </div>
              }
              rightContent={
                <Button
                  variant={'ghost'}
                  onClick={(e) => {
                    e.preventDefault();
                    showModal();
                  }}
                >
                  <Plus />
                </Button>
              }
            >
              <QueryTable
                data={inputs}
                showModal={showModal}
                deleteRecord={handleDeleteRecord}
              ></QueryTable>
            </Collapse>
            {visible && (
              <ParameterDialog
                hideModal={hideModal}
                initialValue={currentRecord}
                otherThanCurrentQuery={otherThanCurrentQuery}
                submit={ok}
              ></ParameterDialog>
            )}
          </>
        )}
      </Form>
    </section>
  );
}

export default memo(BeginForm);
