import { Upload, Button, Flex, Typography, Space, Progress, Card } from 'antd'
import PropTypes from 'prop-types'
import { ApiServerContext } from '../context/ApiServerContext'
import UploadIcon from '../../Icons/UploadIcon'
import {
  useCallback,
  useContext,
  useEffect,
  useMemo,
  useRef,
  useState
} from 'react'
import ObjectSelect from './ObjectSelect'
import FileList from './FileList'
import PlusIcon from '../../Icons/PlusIcon'
import { LoadingOutlined } from '@ant-design/icons'
import FileIcon from '../../Icons/FileIcon'

const { Text } = Typography

const getFileIdentity = (value, multiple) => {
  if (multiple) {
    return Array.isArray(value)
      ? value.map((file) => file?._id || file).join(',')
      : ''
  }

  return value?._id || value || ''
}

const FileUpload = ({
  value,
  onChange,
  minimal = false,
  multiple = true,
  defaultPreviewOpen = false,
  showPreview = true,
  showInfo,
  masterFilter = []
}) => {
  const { uploadFile } = useContext(ApiServerContext)
  const [uploading, setUploading] = useState(false)
  const [uploadProgress, setUploadProgress] = useState(0)
  const onChangeRef = useRef(onChange)

  useEffect(() => {
    onChangeRef.current = onChange
  }, [onChange])

  // Track current files using useState
  const [currentFiles, setCurrentFiles] = useState(() => {
    if (multiple) {
      return Array.isArray(value) ? value : []
    } else {
      return value || null
    }
  })

  // Update currentFiles when value prop changes
  useEffect(() => {
    setCurrentFiles((prev) => {
      if (
        getFileIdentity(prev, multiple) === getFileIdentity(value, multiple)
      ) {
        return prev
      }

      return multiple ? (Array.isArray(value) ? value : []) : value || null
    })
  }, [value, multiple])

  // Track the selected file from ObjectSelect
  const [selectedFile, setSelectedFile] = useState(null)

  const hasNoItems = useMemo(
    () =>
      multiple
        ? !currentFiles ||
          !Array.isArray(currentFiles) ||
          currentFiles.length === 0
        : !currentFiles,
    [currentFiles, multiple]
  )

  const updateCurrentFiles = useCallback((nextFiles) => {
    setCurrentFiles(nextFiles)
    onChangeRef.current?.(nextFiles)
  }, [])

  const handleFileUpload = async (file) => {
    try {
      setUploading(true)
      const uploadedFile = await uploadFile(file, {}, (progress) => {
        setUploadProgress(progress)
      })
      setUploading(false)
      if (uploadedFile) {
        if (multiple) {
          // For multiple files, add to existing array
          const newFiles = [...currentFiles, uploadedFile]
          updateCurrentFiles(newFiles)
        } else {
          // For single file, replace the value
          updateCurrentFiles(uploadedFile)
        }
      }
    } catch (error) {
      console.error('File upload failed:', error)
    }
    return false // Prevent default upload behavior
  }

  // Handle adding selected file to the list
  const handleAddSelectedFile = () => {
    if (selectedFile) {
      if (multiple) {
        // For multiple files, add to existing array
        const newFiles = [...currentFiles, selectedFile]
        updateCurrentFiles(newFiles)
      } else {
        // For single file, replace the value
        updateCurrentFiles(selectedFile)
      }
      // Clear the selection
      setSelectedFile(null)
    }
  }

  if (minimal == true) {
    return (
      <Flex gap={'small'} vertical>
        <FileIcon file={currentFiles[0]} style={{ fontSize: '24px' }} />
        <Text>{currentFiles[0]?.name}</Text>
      </Flex>
    )
  }

  return (
    <Flex gap={'small'} vertical>
      {hasNoItems && uploading == false ? (
        <Flex gap={'small'} align='center' wrap>
          <Space.Compact style={{ flexGrow: 1, minWidth: 0 }}>
            <ObjectSelect
              type={'file'}
              value={selectedFile}
              onChange={setSelectedFile}
              style={{ width: '100%', minWidth: 0 }}
              masterFilter={
                masterFilter.length > 0
                  ? { extension: { $in: masterFilter } }
                  : {}
              }
            />
            <Button
              icon={<PlusIcon />}
              onClick={handleAddSelectedFile}
              disabled={!selectedFile}
            />
          </Space.Compact>
          <Text style={{ whiteSpace: 'nowrap' }} type='secondary'>
            or
          </Text>
          <Upload
            beforeUpload={handleFileUpload}
            showUploadList={false}
            multiple={multiple}
            accept={
              masterFilter.length > 0 ? masterFilter.join(',') : undefined
            }
          >
            <Button style={{ width: '100%' }} icon={<UploadIcon />}>
              Upload
            </Button>
          </Upload>
        </Flex>
      ) : null}
      {uploading == true ? (
        <Card styles={{ body: { padding: '10px 15px' } }}>
          <Flex gap={'small'} align='center'>
            <Text>Uploading...</Text>
            {uploadProgress > 0 ? (
              <>
                {uploadProgress >= 0 && uploadProgress < 100 ? (
                  <>
                    <Progress
                      percent={uploadProgress}
                      showInfo={false}
                      style={{ width: '100px', flexGrow: 1 }}
                      status='active'
                    />
                    <Text>{uploadProgress}%</Text>
                  </>
                ) : null}
                {uploadProgress == 100 ? <LoadingOutlined /> : null}
              </>
            ) : null}
          </Flex>
        </Card>
      ) : null}
      <FileList
        files={currentFiles}
        multiple={multiple}
        editing={true}
        showInfo={showInfo || false}
        showPreview={showPreview}
        defaultPreviewOpen={defaultPreviewOpen}
        onChange={(updatedFiles) => {
          updateCurrentFiles(updatedFiles)
        }}
      />
    </Flex>
  )
}

FileUpload.propTypes = {
  value: PropTypes.oneOfType([PropTypes.object, PropTypes.array]),
  onChange: PropTypes.func,
  multiple: PropTypes.bool,
  showPreview: PropTypes.bool,
  showInfo: PropTypes.bool,
  defaultPreviewOpen: PropTypes.bool,
  minimal: PropTypes.bool,
  masterFilter: PropTypes.array
}

export default FileUpload
