'use client'

import React, { useCallback, useState } from 'react'
import { useDropzone, Accept, FileRejection } from 'react-dropzone'
import { UploadCloudIcon, Check, Trash } from 'lucide-react'
import { cn } from '@/lib/utils/cn'
import { InformationCircleIcon } from '../icons/common'
import { ErrorIcon } from '../icons/form-icon'
import { useScopedI18n } from '@/locales/client'

export interface FileUploaderProps {
  value: File[]
  onChange: (files: File[]) => void
  label?: string
  underText?: string
  accept?: Accept
  multiple?: boolean
  className?: string
  maxFiles?: number
  hasError?: boolean
  errorMessage?: string
}

const ACCEPTED_FORMATS: Accept = {
  'application/pdf': ['.pdf'],
  'image/png': ['.png'],
  'image/jpeg': ['.jpg', '.jpeg'],
}

async function validateImageDimensions(file: File): Promise<boolean> {
  if (!file.type.startsWith('image/')) {
    return true
  }

  return new Promise((resolve) => {
    const image = new Image()
    image.src = URL.createObjectURL(file)
    image.onload = () => {
      URL.revokeObjectURL(image.src)
      resolve(image.width <= 800 && image.height <= 400)
    }
    image.onerror = () => {
      URL.revokeObjectURL(image.src)
      resolve(false)
    }
  })
}

export function FileUploader({
  value = [],
  onChange,
  label,
  underText,
  accept = ACCEPTED_FORMATS,
  multiple = true,
  className,
  maxFiles = 2,
  hasError,
  errorMessage,
}: FileUploaderProps) {
  const [rejectionError, setRejectionError] = useState<string | null>(null)

  const onDrop = useCallback(
    async (acceptedFiles: File[], fileRejections: FileRejection[]) => {
      setRejectionError(null)

      if (fileRejections.length > 0) {
        setRejectionError(fileRejections[0].errors[0].message)
        return
      }

      if (value.length + acceptedFiles.length > maxFiles) {
        setRejectionError(`You can only upload a maximum of ${maxFiles} files.`)
        return
      }

      const validFiles: File[] = []
      for (const file of acceptedFiles) {
        const isDimensionsValid = await validateImageDimensions(file)
        if (isDimensionsValid) {
          validFiles.push(file)
        } else {
          setRejectionError('Image dimensions must be under 800x400px.')
        }
      }

      if (validFiles.length > 0) {
        const newFiles = multiple ? [...value, ...validFiles] : validFiles
        onChange(newFiles)
      }
    },
    [value, multiple, onChange, maxFiles],
  )

  const { getRootProps, getInputProps, isDragActive } = useDropzone({
    onDrop,
    multiple,
    accept,
    disabled: maxFiles ? value.length >= maxFiles : false,
  })

  const removeFile = (idx: number) => {
    const updated = value.filter((_, i) => i !== idx)
    onChange(updated)
    if (rejectionError) {
      setRejectionError(null)
    }
  }

  const t = useScopedI18n('booking.documents')
  return (
    <div className={cn('space-y-2', className)}>
      {label && <label className="block text-grey-50 uppercase text-xs font-medium">{label}</label>}

      <div
        {...getRootProps()}
        className={cn(
          'border-2 border-dashed rounded-md p-6 text-center transition-colors cursor-pointer',
          'bg-neutral-800 border-neutral-600 hover:border-neutral-500',
          isDragActive && 'border-accent text-accent-foreground bg-neutral-700',
          maxFiles && value.length >= maxFiles && 'cursor-not-allowed opacity-50',
          rejectionError || (hasError && errorMessage) ? 'border-func-red-main' : '',
        )}
      >
        <input {...getInputProps()} />
        <div className="mx-auto size-10 rounded-xl bg-grey-500 flex items-center justify-center">
          <UploadCloudIcon size={24} className="stroke-grey-50" />
        </div>
        <div className="button-small-medium text-base-white mt-4">
          {isDragActive
            ? t('dropText')
            : t('clickText')}
        </div>
        <div className="text-center label-medium-regular text-grey-300 mt-4">
          PDF, PNG or JPG (max. 800x400px)
        </div>
      </div>
      {(rejectionError || (hasError && errorMessage)) && (
        <div className="flex items-center justify-start mt-2">
          <ErrorIcon width={20} height={20} className="text-func-red-main flex-shrink-0" />
          <p className={cn('label-medium-regular ml-1 text-func-red-main')}>
            {rejectionError || errorMessage}
          </p>
        </div>
      )}
      {underText && !rejectionError && !(hasError && errorMessage) && (
        <div className="flex items-center gap-1 mt-4">
          <InformationCircleIcon className="size-4 stroke-grey-200" />
          <div className="label-medium-regular text-grey-200 ">{underText}</div>
        </div>
      )}

      {value.length > 0 && (
        <ul className="space-y-4 mt-4">
          {value.map((file, idx) => (
            <li
              key={idx}
              className="w-full flex items-center justify-between bg-grey-700 p-4 rounded-2xl"
            >
              <div className="flex items-start gap-4">
                <div className="mx-auto size-10 rounded-xl bg-grey-500 flex items-center justify-center">
                  <Check size={24} className="stroke-beige-500" />
                </div>
                <div className="flex flex-col gap-1">
                  <div className="b3-semibold text-base-white">{file.name}</div>
                  <div className="label-medium-regular text-grey-100">
                    {(file.size / 1024).toFixed(1)} KB
                  </div>
                </div>
              </div>
              <div
                onClick={() => removeFile(idx)}
                className="size-10 rounded-xl bg-grey-500 flex items-center justify-center cursor-pointer hover:bg-grey-600"
              >
                <Trash size={24} className="stroke-base-white" />
              </div>
            </li>
          ))}
        </ul>
      )}
    </div>
  )
}
