import { Input, Upload } from '@/components/ui'
import Button from '@/components/ui/Button'
import { FormContainer } from '@/components/ui/Form'
import Notification from '@/components/ui/Notification'
import toast from '@/components/ui/toast'
import { AVATAR_URL } from '@/constants/app.constant'
import { useStoreActions, useStoreState } from '@/store'
import { useLocalization } from '@/utils/hooks/useLocalization'
import dayjs from 'dayjs'
import type { FieldProps } from 'formik'
import { Field, Form, Formik } from 'formik'

import { useEffect, useRef, useState } from 'react'
import {
  CircleStencil,
  Cropper,
  CropperPreview,
  CropperPreviewRef,
  CropperRef,
} from 'react-advanced-cropper'
import 'react-advanced-cropper/dist/style.css'
import {
  FaFacebookMessenger,
  FaEnvelope,
  FaTrashAlt,
  FaUserCircle,
  FaPhone,
  FaPlus,
} from 'react-icons/fa'
import * as Yup from 'yup'
import isEmpty from 'lodash/isEmpty'
import FormRow from '@/views/shared/FormRow'
import FormDesription from '@/views/shared/FormDesription'
import { ProfileDto, UpdateProfileDto } from '@/proxy/account/models'
import { getProfile, updateProfile } from '@/services/account.service'

const schema = Yup.object().shape({
  name: Yup.string().min(3).max(50).required(),
  surname: Yup.string().min(3).max(50).required(),
})

const General = () => {
  const [loading, setLoading] = useState(true)
  const [profileData, setProfileData] = useState<ProfileDto>()
  const [formData, setFormData] = useState<UpdateProfileDto>()
  const [image, setImage] = useState<string | undefined>()

  const auth = useStoreState((state) => state.auth)
  const { setUser } = useStoreActions((actions) => actions.auth.user)

  const { translate } = useLocalization()
  const cropperRef = useRef<CropperRef>(null)
  const previewRef = useRef<CropperPreviewRef>(null)

  const fetchData = async () => {
    setLoading(true)
    const response = await getProfile()
    setProfileData(response.data)
    setImage(auth.user.avatar)
    setFormData({
      name: response.data.name,
      surname: response.data.surname,
    })
    setLoading(false)
  }

  useEffect(() => {
    if (isEmpty(profileData)) {
      fetchData()
    }
  }, [])

  const onChooseImage = async (file: File[]) => {
    if (file[0]) {
      setImage(URL.createObjectURL(file[0]))
    } else {
      setImage(undefined)
    }
  }

  const beforeUpload = (files: FileList | null, fileList: File[]) => {
    let valid: string | boolean = true

    const allowedFileType = ['image/jpeg', 'image/png', 'image/gif']
    const maxFileSize = 2000000

    if (fileList.length >= 1) {
      return `Sadece bir dosya seçebilirsiniz`
    }

    if (files) {
      for (const f of files) {
        if (!allowedFileType.includes(f.type)) {
          valid = '.jpg, .jpeg, .gif veya .png yükleyebilirsiniz'
        } else if (f.size >= maxFileSize) {
          valid = 'En fazla 2mb dosya yükleyebilirsiniz'
        }
      }
    }

    return valid
  }

  const onFormSubmit = async (
    values: UpdateProfileDto,
    setSubmitting: (isSubmitting: boolean) => void,
  ) => {
    const avatar = await getCroppedAvatar()
    const resp = await updateProfile({
      name: values.name,
      surname: values.surname,
      avatar: avatar ? new File([avatar], 'avatar') : undefined,
    })
    if (resp.status === 200) {
      setUser({
        ...auth.user,
        name: `${resp.data.name} ${resp.data.surname}`.trim(),
        avatar: AVATAR_URL(auth.user.id, auth.tenant.tenantId) + `?${dayjs().unix()}`,
      })

      toast.push(<Notification title={'Profil güncellendi'} type="success" />, {
        placement: 'top-end',
      })
    } else {
      toast.push(<Notification title={resp?.error?.message} type="danger" />, {
        placement: 'top-end',
      })
    }
    setSubmitting(false)
  }

  const getCroppedAvatar = () =>
    new Promise<Blob | null>((resolve, reject) => {
      const canvas = cropperRef.current?.getCanvas({
        minHeight: 100,
        minWidth: 100,
        maxHeight: 300,
        maxWidth: 300,
      })
      if (canvas) {
        canvas.toBlob((blob) => {
          if (blob) {
            resolve(blob)
          } else {
            reject()
          }
        }, 'image/jpeg')
      } else {
        resolve(null)
      }
    })

  if (loading) {
    return <></>
  }

  return (
    <Formik
      enableReinitialize
      initialValues={formData!}
      validationSchema={schema}
      onSubmit={(values, { setSubmitting }) => {
        setSubmitting(true)
        onFormSubmit(values, setSubmitting)
      }}
    >
      {({ touched, errors, isSubmitting, resetForm }) => {
        const validatorProps = { touched, errors }
        return (
          <Form>
            <FormContainer>
              <FormDesription
                title={translate('::Abp.Identity.Profile.General')}
                desc={translate('::Abp.Identity.Profile.General.Description')}
              />
              <FormRow
                name="email"
                label={translate('::Abp.Account.EmailAddress')}
                {...validatorProps}
              >
                <Input
                  type="text"
                  disabled
                  prefix={<FaEnvelope className="text-xl" />}
                  value={profileData?.email}
                ></Input>
              </FormRow>
              <FormRow
                name="phoneNumber"
                label={translate('::Abp.Identity.User.UserInformation.PhoneNumber')}
                {...validatorProps}
              >
                <Input
                  type="text"
                  disabled
                  prefix={<FaPhone className="text-xl" />}
                  value={profileData?.phoneNumber}
                ></Input>
              </FormRow>
              <FormRow name="phoneNumber" label={translate('::RocketUsername')} {...validatorProps}>
                <Input
                  type="text"
                  disabled
                  prefix={<FaFacebookMessenger className="text-xl" />}
                  value={profileData?.extraProperties?.['RocketUsername'] as string | undefined}
                ></Input>
              </FormRow>
              <FormRow
                name="name"
                label={translate('::Abp.Identity.User.UserInformation.Name')}
                {...validatorProps}
              >
                <Field
                  type="text"
                  autoComplete="off"
                  name="name"
                  placeholder="Name"
                  component={Input}
                  prefix={<FaUserCircle className="text-xl" />}
                />
              </FormRow>
              <FormRow
                name="surname"
                label={translate('::Abp.Identity.User.UserInformation.Surname')}
                {...validatorProps}
              >
                <Field
                  type="text"
                  autoComplete="off"
                  name="surname"
                  placeholder="Last Name"
                  component={Input}
                  prefix={<FaUserCircle className="text-xl" />}
                />
              </FormRow>
              <FormRow name="avatar" label="Avatar" alignCenter={false} {...validatorProps}>
                <Field name="avatar">
                  {({ field, form }: FieldProps) => {
                    return (
                      <>
                        <div>
                          <div className="flex flex-col lg:flex-row items-start gap-5">
                            {image ? (
                              <Cropper
                                ref={cropperRef}
                                src={image}
                                onUpdate={(cropper) => {
                                  setTimeout(() => {
                                    previewRef.current?.update(cropper)
                                  }, 100)
                                }}
                                className="cropper max-h-[300px] max-w-[300px]"
                                stencilComponent={CircleStencil}
                                minHeight={100}
                                minWidth={100}
                              />
                            ) : (
                              <img
                                className="cropper max-h-[300px] max-w-[300px]"
                                src={auth.user.avatar}
                              />
                            )}
                            <div className="flex flex-row gap-4">
                              <div className="flex flex-col">
                                <Upload
                                  className="cursor-pointer"
                                  showList={false}
                                  multiple={false}
                                  uploadLimit={1}
                                  beforeUpload={beforeUpload}
                                  onChange={onChooseImage}
                                >
                                  <Button icon={<FaPlus />} type="button"></Button>
                                </Upload>
                                <Button
                                  type="button"
                                  className="my-2"
                                  icon={<FaTrashAlt />}
                                  onClick={() => setImage(undefined)}
                                ></Button>
                              </div>
                              {image && (
                                <CropperPreview
                                  ref={previewRef}
                                  className="preview max-w-[100px] avatar-img avatar-circle border border-gray-400"
                                />
                              )}
                            </div>
                          </div>
                        </div>
                      </>
                    )
                  }}
                </Field>
              </FormRow>
              <div className="mt-4 ltr:text-right">
                <Button className="ltr:mr-2 rtl:ml-2" type="button" onClick={() => resetForm()}>
                  {translate('::Cancel')}
                </Button>
                <Button variant="solid" loading={isSubmitting} type="submit">
                  {isSubmitting ? translate('::SavingWithThreeDot') : translate('::Save')}
                </Button>
              </div>
            </FormContainer>
          </Form>
        )
      }}
    </Formik>
  )
}

export default General
