import { yupResolver } from '@hookform/resolvers/yup'
import { Add } from '@mui/icons-material'
import UploadIcon from '@mui/icons-material/Upload'
import {
  Box,
  Button,
  CircularProgress,
  Stack,
  Typography,
  alpha,
} from '@mui/material'
import { useEffect, useState } from 'react'
import { Controller, useFieldArray, useForm } from 'react-hook-form'
import { useMutation, useQuery, useQueryClient } from 'react-query'
import { toast } from 'react-toastify'
import * as yup from 'yup'
import { axiosErrorToast } from '../../../config/axios'
import ActionButton from '../../ActionButton'
import { FormDatePicker, FormSingleSelect, FormTextField } from '../../HookForm'
import FormLabel from '../../HookForm/FormLabel'
import ImageUpload from '../../ImageUpload'
import AsyncSearchSelect from '../../Input/AsyncSearchSelect/AsyncSearchSelect'
import MediaRow from '../../MediaRow/MediaRow'
import Spinner from '../../Spinner'
import { Media } from '../../UploadButton/types'
import { StyledDeleteButton } from '../PaperPublication/Styles'
import { StyledUploadContainer } from '../Styles'
import { FileRender } from './FileRender'
import { StyledStack, StyledTypography } from './Styles'
import {
  FundingSources,
  PatentStatus,
  createProject,
  fetchFacultyUsers,
  fetchPrograms,
  uploadFiles,
} from './services'

export const schema = yup.object().shape({
  title: yup.string().required('Project title is required'),
  programName: yup.string().required('Research Area is required'),
  description: yup.string().required('Description is required'),
  projectLeadIds: yup
    .array()
    .min(1, 'Need at least 1 project lead')
    .required('Lead Researcher is required'),
  projectMemberIds: yup
    .array()
    .min(1, 'Need at least 1 project member')
    .required('Project Member is required'),
  fundingSource: yup.string().required('Funding source is required'),
  patentStatus: yup.string().required('Patent Status should not be empty'),
  startDate: yup.string().required('Start date is required').nullable(),
  fundingAmount: yup.string().required('Funding Amount is required'),
  endDate: yup.string().required('End date is required').nullable(),
  coverImage: yup.array().min(1).required('Cover Image is required').nullable(),
  keywords: yup
    .array()
    .of(
      yup.object().shape({
        keyword: yup.string().required('Keyword is required'),
      }),
    )
    .min(1, 'Need at least 1 keyword')
    .required('Keyword minimum of 1 is required'),
})

function ResearchProjectForm({
  data,
  close,
}: {
  data?: any
  close: () => void
}) {
  const [coverMedia, setCoverMedia] = useState<Media[]>([])
  const [attachmentMedia, setAttachmentMedia] = useState<Media[]>([])
  const queryClient = useQueryClient()

  const { control, handleSubmit, watch, setValue } = useForm({
    resolver: yupResolver(schema),
    defaultValues: {
      ...data,
      keywords:
        data?.keywords?.map((item) => {
          return { keyword: item }
        }) || [],
      projectMemberIds:
        data?.projectMembers?.map((item) => {
          return {
            value: item?.userDetails?._id,
            label: item?.userDetails?.fullName,
          }
        }) || [],

      projectLeadIds:
        data?.projectMembers
          ?.filter((item) => item?.isLead == true)
          .map((item) => {
            return {
              value: item?.userDetails?._id,
              label: item?.userDetails?.fullName,
            }
          }) || [],
      attachment:
        data?.attachments?.map((item) => {
          return {
            key: item?.key,
            url: item?.url,
            type: item?.mediaType,
          }
        }) || [],
      coverImage: data
        ? [
            {
              key: data?.coverImage?.key,
              url: data?.coverImage?.url,
              type: data?.coverImage?.mediaType,
            },
          ]
        : [],
    },
  })

  const { isLoading: loadingUsers, data: options } = useQuery('programs', () =>
    fetchPrograms(),
  )
  const { fields, append, remove } = useFieldArray({
    control,
    name: 'keywords',
  })

  const handleDeleteImage = (key) => {
    setCoverMedia((prev) => prev.filter((m) => m.key !== key))
  }
  const { mutate, isLoading: creatingProject } = useMutation(createProject, {
    onSuccess: (res) => {
      close()
      toast.success(
        data ? 'Project Updated successfully' : `Project created successfully`,
      )
      queryClient.invalidateQueries('research-projects')
    },
    onError: (err) => {
      axiosErrorToast(err)
    },
  })

  const onSubmit = async (formData) => {
    const postBody = {
      ...formData,
      imageKey: coverMedia[0]?.key,
      attachmentKeys: attachmentMedia?.map((item) => item?.key) ?? [],
      projectLeadIds:
        formData?.projectLeadIds?.map((item) => item?.value.toString()) ?? [],
      projectMemberIds:
        formData?.projectMemberIds?.map((item) => item?.value.toString()) ?? [],
      keywords: formData?.keywords?.map((item) => item?.keyword),
    }
    mutate(postBody)
  }
  const { mutate: uploadFile, isLoading: uploadingFile } = useMutation(
    uploadFiles,
    {
      onSuccess: (res) => {
        setValue('attachment', [
          ...watch('attachment'),
          { fileName: res?.originalFileName, key: res?.key, url: res?.url },
        ])
        setAttachmentMedia((prev) => [
          ...prev,
          {
            key: res?.key,
            type: 'file',
            url: res.url,
            fileName: res.originalFileName,
          },
        ])
      },
      onError: (err) => {
        // eslint-disable-next-line no-console
        console.log(err)
        axiosErrorToast(err)
      },
    },
  )

  const handleFileInput = (e) => {
    let filesData = e.target.files
    let fileArray = Object.keys(filesData)
    fileArray.forEach(async (file) => {
      const fileData = new FormData()
      fileData.append('file', filesData[file])
      fileData.append('subType', 'attachment')
      uploadFile(fileData)
    })
  }

  const onFileUploaded = (res: any) => {
    setValue('coverImage', [{ key: res.key, type: 'image', url: res.url }])
    setCoverMedia([{ type: 'image', url: res.url, key: res.key }])
  }
  const onError = (err) => {
    // eslint-disable-next-line no-console
    console.log(err)
  }

  useEffect(() => {
    if (watch('keywords').length == 0) {
      append({ keyword: '' })
    }

    data && data?.coverImage?.url
      ? setCoverMedia([
          {
            key: data?.coverImage?.key,
            url: data?.coverImage?.url,
            type: data?.coverImage?.mediaType,
          },
        ])
      : setCoverMedia([])

    data && data?.attachments?.length
      ? setAttachmentMedia(
          data?.attachments?.map((item) => {
            return {
              key: item?.key,
              url: item?.url,
              type: item?.mediaType,
              fileName: item?.originalFileName,
            }
          }),
        )
      : setAttachmentMedia([])
  }, [data])

  if (loadingUsers) {
    return <Spinner />
  }

  return (
    <>
      <form onSubmit={handleSubmit(onSubmit, onError)}>
        <FormLabel label={'Cover Image'} required={true} />
        <Stack gap={3.5}>
          <>
            {!coverMedia.length ? (
              <Controller
                name={'coverImage'}
                control={control}
                render={({ field, fieldState: { error } }) => (
                  <>
                    <ImageUpload
                      onFileUploaded={(res) => {
                        onFileUploaded(res)
                      }}
                      postUrl="/square/research-projects/upload"
                      postBody={{ subType: 'image' }}
                    />

                    {error && (
                      <StyledTypography>{error?.message}</StyledTypography>
                    )}
                  </>
                )}
              />
            ) : (
              <MediaRow list={coverMedia} onDelete={handleDeleteImage} />
            )}
          </>
          <FormTextField
            name="title"
            label={'Research Project Title'}
            control={control}
            required
          />
          <FormSingleSelect
            label="Research Areas/Field"
            control={control}
            name="programName"
            options={options?.map((item) => ({
              value: item.branchName,
              label: item.branchName,
            }))}
            required
          />

          <FormTextField
            label="Description/Abstract"
            name="description"
            control={control}
            multiline
            minRows={4}
            required
          />
          <Box
            sx={{
              display: 'flex',
              gap: '20px',
              alignItems: 'center',
              justifyContent: 'center',
            }}
          >
            <FormDatePicker
              maxDate={watch('endDate')}
              name="startDate"
              label="Start date "
              control={control}
              required
            />

            <FormDatePicker
              name="endDate"
              label="End date "
              control={control}
              required
              minDate={watch('startDate')}
            />
          </Box>
          <StyledStack direction={'row'}>
            <Typography variant="h3">Keywords</Typography>
            <Button
              variant="text"
              startIcon={<Add />}
              size="small"
              onClick={() => append({ keyword: '' })}
            >
              Add
            </Button>
          </StyledStack>
          {fields?.map((field, index) => (
            <Box key={field?.id}>
              <StyledStack
                direction={'row'}
                gap={2}
                sx={{ alignItems: 'flex-end' }}
              >
                <FormTextField
                  name={`keywords.${index}.keyword`}
                  label={`Keyword ${index + 1}`}
                  control={control}
                  required
                />

                <StyledDeleteButton onClick={() => remove(index)} />
              </StyledStack>
            </Box>
          ))}
          <Controller
            name={'projectLeadIds'}
            control={control}
            render={({ field, fieldState: { error } }) => (
              <>
                <AsyncSearchSelect
                  label="Lead Researcher"
                  fetchFn={fetchFacultyUsers}
                  onChange={(value) => {
                    setValue('projectLeadIds', value)
                  }}
                  initialOptions={watch('projectLeadIds')}
                  required
                />
                {error && <StyledTypography>{error?.message}</StyledTypography>}
              </>
            )}
          />

          <Controller
            name={'projectMemberIds'}
            control={control}
            render={({ field, fieldState: { error } }) => (
              <>
                <AsyncSearchSelect
                  label="Project Members"
                  fetchFn={fetchFacultyUsers}
                  onChange={(value) => {
                    setValue('projectMemberIds', value)
                  }}
                  initialOptions={watch('projectMemberIds')}
                  required
                />
                {error && <StyledTypography>{error?.message}</StyledTypography>}
              </>
            )}
          />
          <FormSingleSelect
            label={'Funding Source'}
            name="fundingSource"
            control={control}
            options={
              Object.keys(FundingSources)?.map((key) => ({
                label: FundingSources[key],
                value: key,
              })) ?? []
            }
            required
          />

          <FormTextField
            label={'Funding Amount'}
            name="fundingAmount"
            control={control}
            type="number"
            required
          />

          <FormSingleSelect
            label={'Patent Status'}
            name="patentStatus"
            control={control}
            options={
              Object.keys(PatentStatus)?.map((key) => ({
                label: PatentStatus[key],
                value: key,
              })) ?? []
            }
            required
          />
          <Box>
            <Typography
              sx={{
                color: alpha('#121212', 0.5),
                lineHeight: 2,
              }}
            >
              Add Files
            </Typography>
            {attachmentMedia.length !== 0 && (
              <FileRender
                state={attachmentMedia}
                setState={setAttachmentMedia}
                setValue={setValue}
              />
            )}
            <Controller
              name={'attachment'}
              control={control}
              render={({ field, fieldState: { error } }) => (
                <>
                  <StyledUploadContainer htmlFor="file">
                    <UploadIcon />
                    <Typography variant="subtitle2" sx={{ margin: '0px 10px' }}>
                      Upload Files
                    </Typography>
                    {uploadingFile && <CircularProgress size={20} />}
                  </StyledUploadContainer>

                  {error && (
                    <StyledTypography>{error?.message}</StyledTypography>
                  )}
                </>
              )}
            />
            <input
              id="file"
              type="file"
              hidden
              multiple
              onChange={handleFileInput}
            />
          </Box>
        </Stack>
        <Stack direction="row" gap={2} mt={3}>
          <ActionButton variant="outlined" fullWidth onClick={close}>
            Cancel
          </ActionButton>
          <ActionButton type="submit" fullWidth loading={creatingProject}>
            {data ? 'Update Project' : 'Add Project'}
          </ActionButton>
        </Stack>
      </form>
    </>
  )
}

export default ResearchProjectForm
