import {invoke} from "@forge/bridge";
import {
  Box, Button, Code,
  ErrorMessage,
  Form, FormFooter,
  FormSection,
  Heading, HelperMessage, Inline,
  Label, LoadingButton,
  RequiredAsterisk, Select,
  Stack, TextArea,
  Textfield,
  useForm, xcss
} from "@forge/react";
import React from "react";
import {
  GenerateField, SUMMARY_CLOSE_INFO_CONFIG_KEY,
  SummaryCloseInfoConfig
} from "../../../core/config";

interface SelectOption {
  label: string;
  value: any;
}

export interface SummaryCloseInfoConfigFormProps {
  projectKey: string;
  initialConfig: SummaryCloseInfoConfig;
  jiraFieldOptions: SelectOption[];
  fieldTypeOptions: SelectOption[];
}

export const SummaryCloseInfoConfigForm = ({
  projectKey,
  initialConfig,
  jiraFieldOptions,
  fieldTypeOptions
}: SummaryCloseInfoConfigFormProps) => {
  const { formState, handleSubmit, register, getFieldId, getValues } = useForm<SummaryCloseInfoConfig>({
    defaultValues: initialConfig
  });
  const { errors, isSubmitting, touchedFields } = formState;

  const saveConfig = async (newConfig: SummaryCloseInfoConfig) => {
    const storageKey = `${SUMMARY_CLOSE_INFO_CONFIG_KEY}_${projectKey}`;
    const oldConfig = await invoke<SummaryCloseInfoConfig>('storage.get', {
      key: storageKey
    });
    await invoke('storage.set', {
      key: storageKey,
      value: Object.assign(oldConfig, newConfig)
    });
  }

  return (
    <Form onSubmit={handleSubmit(saveConfig, (err) => {
      console.error(err)
    })}>
      <FormSection>
        <Stack space="space.200">
          {/*  Command  */}
          <Box>
            <Label labelFor={getFieldId('command')}>
              <Heading as="h6">
                Command Name<RequiredAsterisk />
              </Heading>
            </Label>
            <Textfield
              {...register('command', { required: true })}
              placeholder="Please input the comand of generator."
            />
            {
              errors?.command && (
                errors?.command?.message ?
                  <ErrorMessage>{errors?.command?.message}</ErrorMessage> :
                  <ErrorMessage>Please input a valid name for generator.</ErrorMessage>
              )
            }
            {!touchedFields?.command && !errors?.command && (
              <HelperMessage>
                The command name of the generator. For example, if the command is <Code>summary</Code>, you trigger with command <Code>/summary</Code>.
              </HelperMessage>
            )}
          </Box>
          {/*  Prompt  */}
          <Box>
            <Label labelFor={getFieldId('prompt')}>
              <Heading as="h6">
                Prompt <RequiredAsterisk />
              </Heading>
            </Label>
            <TextArea
              {...register('prompt', { required: true })}
              placeholder={"Please input the prompt."}
            />
            {
              errors?.prompt && (
                errors?.prompt?.message ?
                  <ErrorMessage>{errors?.prompt?.message}</ErrorMessage> :
                  <ErrorMessage>Please input a valid prompt for generator.</ErrorMessage>
              )
            }
            {!touchedFields?.prompt && !errors?.prompt && (
              <HelperMessage>
                You can use prompt to control AI to generate the content of composite specifications according to your instruction.
              </HelperMessage>
            )}
          </Box>
          {/*  Fields  */}
          <Box>
            <Label labelFor={getFieldId('fields')}>
              <Heading as="h6">
                Fields <RequiredAsterisk />
              </Heading>
            </Label>
            <Stack alignInline="start">
              <Box>
                <Button isDisabled={true} onClick={() => {
                  console.log('Add field')
                }}>Add field</Button>
              </Box>
              {
                (getValues('fields') || []).map((field: GenerateField, fieldIndex: number) => (
                  <Box xcss={xcss({ borderRadius: 'border.radius', paddingTop: 'space.100', paddingBottom: 'space.100' })}>
                    <Inline space="space.200">
                      <Stack space="space.025">
                        <Label labelFor={getFieldId(`fields.${fieldIndex}.name`)}>
                          Name
                          <RequiredAsterisk />
                        </Label>
                        <Textfield
                          {...register(`fields.${fieldIndex}.name`, { required: true })}
                          isCompact={true}
                        />
                        { errors?.fields?.[fieldIndex]?.name && (
                          errors?.fields?.[fieldIndex]?.name?.message ?
                            <ErrorMessage>{errors?.fields?.[fieldIndex]?.name?.message}</ErrorMessage> :
                            <ErrorMessage>Required</ErrorMessage>
                        )}
                      </Stack>
                      <Stack space="space.025">
                        <Label labelFor={getFieldId(`fields.${fieldIndex}.type`)}>
                          Type
                          <RequiredAsterisk />
                        </Label>
                        <Box xcss={xcss({ width: '120px' })}>
                          <Select
                            {...register(`fields.${fieldIndex}.type`, { required: true })}
                            defaultValue={fieldTypeOptions.find((option) => option.value === field.type)}
                            isSearchable={true}
                            appearance="default"
                            spacing="compact"
                            options={fieldTypeOptions}
                          />
                        </Box>
                      </Stack>
                      <Stack space="space.025">
                        <Label labelFor={getFieldId(`fields.${fieldIndex}.targetJiraFieldKey`)}>
                          Target Jira Field
                          <RequiredAsterisk />
                        </Label>
                        <Box xcss={xcss({ width: '180px' })}>
                          <Select
                            {...register(`fields.${fieldIndex}.targetJiraFieldKey`, { required: true })}
                            defaultValue={jiraFieldOptions.find((option) => option.value === field.targetJiraFieldKey)}
                            isSearchable={true}
                            appearance="default"
                            spacing="compact"
                            options={jiraFieldOptions}
                          />
                          { errors?.fields?.[fieldIndex]?.targetJiraFieldKey && (
                            errors?.fields?.[fieldIndex]?.targetJiraFieldKey?.message ?
                              <ErrorMessage>{errors?.fields?.[fieldIndex]?.targetJiraFieldKey?.message}</ErrorMessage> :
                              <ErrorMessage>Required</ErrorMessage>
                          )}
                        </Box>
                      </Stack>
                      <Stack space="space.025">
                        <Label labelFor={getFieldId(`fields.${fieldIndex}.action`)}>
                          Action
                        </Label>
                        <Box>
                          <Button appearance="danger" isDisabled={true} onClick={() => {
                            // TODO
                            console.log('Delete field')
                          }}>Delete</Button>
                        </Box>
                      </Stack>
                    </Inline>
                  </Box>
                ))
              }
            </Stack>
          </Box>
        </Stack>
      </FormSection>
      <FormFooter align="start">
        <LoadingButton appearance="primary" type="submit" isLoading={isSubmitting}>
          Save
        </LoadingButton>
      </FormFooter>
    </Form>
  )
}
