import { memo, useCallback, useEffect, useMemo, useState } from 'react'
import { UploadFile } from 'antd/lib/upload/interface'
import { UploadOutlined } from '@ant-design/icons'
import { RcFile } from 'antd/lib/upload'
import { Upload, Button } from 'antd'

import { isDev } from '@utils'

import { notify, upload } from  './factory'
import { ErrorFetch } from './ErrorFetch'

export type UploadFormProps = {
  url: string
  disabled?: boolean
  accept?: string
  mimeTypes?: string | string[]
  style?: CSSStyleSheet
  formData: FormData
  onUploadStart?: () => void
  onUploadSuccess?: () => void
  onUploadComplete?: () => void
  onUploadError?: (error: unknown) => void
}

export const UploadForm = memo<UploadFormProps>(({ url, disabled, style, formData, mimeTypes, onUploadStart, onUploadSuccess, onUploadComplete, onUploadError }) => {
  const [fileList, setfileList] = useState<UploadFile<any>[]>([])

  const checkMimeTypes = useCallback((file: RcFile) => {
    const isAccepted = !mimeTypes || mimeTypes.includes(file.type)
    if (isAccepted) return false
    notify(`"${file.name}" является файлом неподходящего типа`, 'error')
    return Upload.LIST_IGNORE
  }, [mimeTypes])

  const accept = useMemo(() => Array.isArray(mimeTypes) ? mimeTypes.join(',') : mimeTypes, [mimeTypes])

  const handleFileSend = useCallback(async () => {
    onUploadStart?.()
    try {
      const formDataLocal = new FormData()
      fileList.forEach((val) => formDataLocal.append('files',  val.originFileObj as Blob))

      if(formData)
        for(const propName in formData)
          formDataLocal.append(propName, String(formData.get(propName)))

      const response = await upload(url, formDataLocal)
      if (!response.ok) {
        const errorText = await response.text()
        const error = new ErrorFetch(response.status, errorText)
        throw error
      } else {
        onUploadSuccess?.()
      }
    } catch(error) {
      if(isDev())
        console.error(error)
      onUploadError?.(error)
    } finally {
      setfileList([])
      onUploadComplete?.()
    }
  }, [fileList, formData, onUploadComplete, onUploadError, onUploadStart, onUploadSuccess, url])

  const isSendButtonEnabled = fileList.length > 0
  return(
    <div style={{ display: 'flex', ...style }}>
      <Upload
        name={'file'}
        accept={accept}
        disabled={disabled}
        fileList={fileList}
        onChange={(props) => setfileList(props.fileList)}
        beforeUpload={checkMimeTypes}
      >
        <Button disabled={disabled} icon={<UploadOutlined/>}>Загрузить файл</Button>
      </Upload>
      <Button
        type={'primary'}
        onClick={handleFileSend}
        disabled={!isSendButtonEnabled}
        style={{ marginLeft: '10px', display: isSendButtonEnabled ? '' : 'none' }}
      >
        Отправить
      </Button>
    </div>
  )
})

export default UploadForm
