'use client'

// React Imports
import { useEffect, useState } from 'react'

// MUI Imports
import type { BoxProps } from '@mui/material/Box'
import Button from '@mui/material/Button'
import IconButton from '@mui/material/IconButton'
import List from '@mui/material/List'
import ListItem from '@mui/material/ListItem'
import Typography from '@mui/material/Typography'
import Chip from '@mui/material/Chip'
import LinearProgress from '@mui/material/LinearProgress'
import { styled } from '@mui/material/styles'

// Third-party Imports
import { useDropzone } from 'react-dropzone'

// Component Imports
import Link from '@components/Link'
import CustomAvatar from '@core/components/mui/Avatar'

// Styled Component Imports
import AppReactDropzone from '@/libs/styles/AppReactDropzone'

type FileProp = {
  name: string
  type: string
  size: number
}

type UploadedImage = {
  id: string
  url: string
  name: string
  size: number
}

type UploadProgress = {
  [fileId: string]: number
}

interface MultipleImageUploadProps {
  // Required props
  onUpload: (files: File[]) => Promise<string[]> | string[] // Returns array of image URLs
  onSingleUpload?: (file: File) => Promise<string> | string // For individual file upload

  // Optional customization props
  title?: string | null
  currentImages?: UploadedImage[]
  onImagesChange?: (images: UploadedImage[]) => void
  onImageRemove?: (imageId: string) => void

  // Upload state
  isUploading?: boolean
  uploadProgress?: UploadProgress

  // Limits
  maxFiles?: number
  maxFileSize?: number // in bytes
  acceptedFileTypes?: string[]

  // UI customization
  showUrlOption?: boolean
  uploadButtonText?: string
  browseButtonText?: string
  dragDropText?: string
  replaceText?: string
  maxFilesText?: string

  // Style customization
  className?: string
  disabled?: boolean

  // Upload modes
  uploadMode?: 'batch' | 'individual' // batch: upload all at once, individual: upload one by one
}

// Styled Dropzone Component
const Dropzone = styled(AppReactDropzone)<BoxProps>(({ theme }) => ({
  '& .dropzone': {
    minHeight: 'unset',
    padding: theme.spacing(12),
    [theme.breakpoints.down('sm')]: {
      paddingInline: theme.spacing(5)
    },
    '&+.MuiList-root .MuiListItem-root .file-name': {
      fontWeight: theme.typography.body1.fontWeight
    }
  }
}))

const MultipleImageUpload: React.FC<MultipleImageUploadProps> = ({
  onUpload,
  onSingleUpload,
  title = null,
  currentImages = [],
  onImagesChange,
  onImageRemove,
  isUploading = false,
  uploadProgress = {},
  maxFiles = 10,
  maxFileSize = 5 * 1024 * 1024, // 5MB default
  acceptedFileTypes = ['image/*'],
  showUrlOption = true,
  uploadButtonText = 'Upload All',
  browseButtonText = 'Browse Images',
  dragDropText = 'Drag and Drop Your Images Here.',
  replaceText = 'Drop Images to Add More',
  maxFilesText = 'Maximum {max} files allowed',
  className = '',
  disabled = false,
  uploadMode = 'batch'
}) => {
  // States
  const [files, setFiles] = useState<File[]>([])
  const [error, setError] = useState<string>('')
  const [individualUploading, setIndividualUploading] = useState<Set<string>>(new Set())

  const handleBatchUpload = async () => {
    if (!files.length) return

    try {
      setError('')
      const imageUrls = await onUpload(files)

      if (Array.isArray(imageUrls)) {
        const newImages: UploadedImage[] = files.map((file, index) => ({
          id: `${Date.now()}-${index}`,
          url: imageUrls[index],
          name: file.name,
          size: file.size
        }))

        const updatedImages = [...currentImages, ...newImages]
        onImagesChange?.(updatedImages)
        setFiles([]) // Clear files after successful upload
      }
    } catch (err) {
      setError(err instanceof Error ? err.message : 'Upload failed')
    }
  }

  const handleIndividualUpload = async (file: File, fileIndex: number) => {
    if (!onSingleUpload) return

    const fileId = `${file.name}-${fileIndex}`
    setIndividualUploading(prev => new Set(prev).add(fileId))

    try {
      setError('')
      const imageUrl = await onSingleUpload(file)

      if (typeof imageUrl === 'string') {
        const newImage: UploadedImage = {
          id: `${Date.now()}-${fileIndex}`,
          url: imageUrl,
          name: file.name,
          size: file.size
        }

        const updatedImages = [...currentImages, newImage]
        onImagesChange?.(updatedImages)

        // Remove uploaded file from pending files
        setFiles(prev => prev.filter((_, index) => index !== fileIndex))
      }
    } catch (err) {
      setError(err instanceof Error ? err.message : 'Upload failed')
    } finally {
      setIndividualUploading(prev => {
        const newSet = new Set(prev)
        newSet.delete(fileId)
        return newSet
      })
    }
  }

  // Hooks
  const { getRootProps, getInputProps } = useDropzone({
    onDrop: (acceptedFiles: File[]) => {
      setError('')

      if (acceptedFiles.length === 0) return

      const totalFiles = currentImages.length + files.length + acceptedFiles.length

      if (totalFiles > maxFiles) {
        setError(`Cannot upload more than ${maxFiles} files. Current: ${currentImages.length + files.length}`)
        return
      }

      // Validate file sizes
      const invalidFiles = acceptedFiles.filter(file => file.size > maxFileSize)
      if (invalidFiles.length > 0) {
        setError(`Some files exceed ${formatFileSize(maxFileSize)} limit`)
        return
      }

      // Add to existing files
      setFiles(prev => [...prev, ...acceptedFiles])
    },
    accept: acceptedFileTypes.reduce((acc, type) => ({ ...acc, [type]: [] }), {}),
    disabled: disabled || isUploading,
    multiple: true
  })

  const formatFileSize = (bytes: number): string => {
    if (bytes === 0) return '0 Bytes'
    const k = 1024
    const sizes = ['Bytes', 'KB', 'MB', 'GB']
    const i = Math.floor(Math.log(bytes) / Math.log(k))
    return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i]
  }

  const renderFilePreview = (file: FileProp) => {
    if (file.type.startsWith('image')) {
      return (
        <img
          width={38}
          height={38}
          alt={file.name}
          src={URL.createObjectURL(file as any)}
          className='rounded object-cover'
        />
      )
    } else {
      return <i className='tabler-file-description' />
    }
  }

  const handleRemoveFile = (fileIndex: number) => {
    setFiles(prev => prev.filter((_, index) => index !== fileIndex))
    setError('')
  }

  const handleRemoveCurrentImage = (imageId: string) => {
    onImageRemove?.(imageId)
  }

  const handleRemoveAllFiles = () => {
    setFiles([])
    setError('')
  }

  const isIndividualUploading = (file: File, index: number) => {
    const fileId = `${file.name}-${index}`
    return individualUploading.has(fileId)
  }

  const fileList = files.map((file: File, index: number) => {
    const isFileUploading = isIndividualUploading(file, index)
    const progress = uploadProgress[`${file.name}-${index}`] || 0

    return (
      <ListItem key={`${file.name}-${index}`} className='pis-4 plb-3'>
        <div className='file-details flex-1'>
          <div className='file-preview'>{renderFilePreview(file)}</div>
          <div className='flex-1'>
            <Typography className='file-name font-medium' color='text.primary'>
              {file.name}
            </Typography>
            <Typography className='file-size' variant='body2'>
              {formatFileSize(file.size)}
            </Typography>
            {isFileUploading && progress > 0 && (
              <LinearProgress variant='determinate' value={progress} className='mt-1' />
            )}
          </div>
        </div>
        <div className='flex items-center gap-2'>
          {uploadMode === 'individual' && onSingleUpload && (
            <Button
              variant='outlined'
              size='small'
              onClick={() => handleIndividualUpload(file, index)}
              disabled={isUploading || isFileUploading}
            >
              {isFileUploading ? 'Uploading...' : 'Upload'}
            </Button>
          )}
          <IconButton onClick={() => handleRemoveFile(index)} disabled={isUploading || isFileUploading}>
            <i className='tabler-x text-xl' />
          </IconButton>
        </div>
      </ListItem>
    )
  })

  const currentImagesList = currentImages.map(image => (
    <ListItem key={image.id} className='pis-4 plb-3'>
      <div className='file-details flex-1'>
        <div className='file-preview'>
          <img width={38} height={38} alt={image.name} src={image.url} className='rounded object-cover' />
        </div>
        <div className='flex-1'>
          <Typography className='file-name font-medium' color='text.primary'>
            {image.name}
          </Typography>
          <Typography className='file-size' variant='body2'>
            {formatFileSize(image.size)}
          </Typography>
        </div>
      </div>
      <div className='flex items-center gap-2'>
        <Chip label='Uploaded' color='success' size='small' />
        {onImageRemove && (
          <IconButton onClick={() => handleRemoveCurrentImage(image.id)} color='error' disabled={isUploading}>
            <i className='tabler-x text-xl' />
          </IconButton>
        )}
      </div>
    </ListItem>
  ))

  return (
    <Dropzone className={className}>
      {/* Conditional title and URL option header */}
      {title && (
        <div className='flex justify-between items-center mb-4'>
          <Typography variant='h6' component='h2'>
            {title}
          </Typography>
          {showUrlOption && (
            <Typography component={Link} color='primary.main' className='font-medium'>
              Add media from URL
            </Typography>
          )}
        </div>
      )}

      {/* File limits info */}
      <div className='flex justify-between items-center mb-4'>
        <Typography variant='body2' color='text.secondary'>
          {maxFilesText.replace('{max}', maxFiles.toString())}
        </Typography>
        <Typography variant='body2' color='text.secondary'>
          {currentImages.length + files.length} / {maxFiles} files
        </Typography>
      </div>

      <div {...getRootProps({ className: 'dropzone' })}>
        <input {...getInputProps()} />
        <div className='flex items-center flex-col gap-2 text-center'>
          <CustomAvatar variant='rounded' skin='light' color='secondary'>
            <i className='tabler-upload' />
          </CustomAvatar>
          <Typography variant='h4'>
            {currentImages.length > 0 || files.length > 0 ? replaceText : dragDropText}
          </Typography>
          <Typography color='text.disabled'>or</Typography>
          <Button variant='tonal' size='small' disabled={disabled || isUploading}>
            {browseButtonText}
          </Button>
        </div>
      </div>

      {/* Error Message */}
      {error && (
        <Typography color='error' variant='body2' className='mt-2 text-center'>
          {error}
        </Typography>
      )}

      {/* Current uploaded images */}
      {currentImages.length > 0 && (
        <div className='mt-4'>
          <Typography variant='subtitle2' className='mb-2'>
            Uploaded Images ({currentImages.length}):
          </Typography>
          <List>{currentImagesList}</List>
        </div>
      )}

      {/* Pending files list and upload buttons */}
      {files.length > 0 && (
        <div className='mt-4'>
          <Typography variant='subtitle2' className='mb-2'>
            Pending Files ({files.length}):
          </Typography>
          <List>{fileList}</List>
          <div className='buttons flex gap-2 mt-3'>
            <Button color='error' variant='tonal' onClick={handleRemoveAllFiles} disabled={isUploading}>
              Remove All
            </Button>
            {uploadMode === 'batch' && (
              <Button variant='contained' onClick={handleBatchUpload} disabled={isUploading || files.length === 0}>
                {isUploading ? 'Uploading...' : `${uploadButtonText} (${files.length})`}
              </Button>
            )}
          </div>
        </div>
      )}
    </Dropzone>
  )
}

export default MultipleImageUpload

// ===== USAGE EXAMPLES =====

// 1. Batch upload mode (upload all files at once)
// const [images, setImages] = useState<UploadedImage[]>([])
//
// <MultipleImageUpload
//   title="Product Images"
//   onUpload={handleBatchUpload}
//   currentImages={images}
//   onImagesChange={setImages}
//   onImageRemove={(id) => setImages(prev => prev.filter(img => img.id !== id))}
//   maxFiles={5}
//   uploadMode="batch"
// />

// 2. Individual upload mode (upload files one by one)
// <MultipleImageUpload
//   title="Gallery Images"
//   onUpload={handleBatchUpload}
//   onSingleUpload={handleSingleUpload}
//   currentImages={images}
//   onImagesChange={setImages}
//   onImageRemove={(id) => setImages(prev => prev.filter(img => img.id !== id))}
//   maxFiles={10}
//   uploadMode="individual"
//   uploadProgress={uploadProgress}
// />

// 3. Without title, custom limits
// <MultipleImageUpload
//   title={null}
//   onUpload={handleBatchUpload}
//   currentImages={images}
//   onImagesChange={setImages}
//   maxFiles={3}
//   maxFileSize={2 * 1024 * 1024} // 2MB
//   acceptedFileTypes={['image/jpeg', 'image/png']}
// />

// 4. Example upload handlers
// const handleBatchUpload = async (files: File[]): Promise<string[]> => {
//   const formData = new FormData()
//   files.forEach(file => formData.append('images', file))
//
//   const response = await fetch('/api/upload-multiple', {
//     method: 'POST',
//     body: formData
//   })
//
//   const result = await response.json()
//   return result.urls // Array of uploaded image URLs
// }
//
// const handleSingleUpload = async (file: File): Promise<string> => {
//   const formData = new FormData()
//   formData.append('image', file)
//
//   const response = await fetch('/api/upload-single', {
//     method: 'POST',
//     body: formData
//   })
//
//   const result = await response.json()
//   return result.url // Single uploaded image URL
// }
