import { useCallback, useEffect, useState } from 'react'
import Cropper, { type Area } from 'react-easy-crop'
import { ImagePlus, X } from 'lucide-react'
import { getCroppedImage } from '../utils/cropImage'
import { useT } from '../i18n/useT'
import styles from './ImageCropper.module.css'

interface ImageCropperProps {
  value: string | null
  onChange: (value: string | null) => void
  /** Crop aspect ratio. Defaults to square (1). */
  aspect?: number
  outputFormat?: 'jpeg' | 'png'
  accept?: string
  uploadLabel?: string
  hint?: string
  changeLabel?: string
}

export function ImageCropper({
  value,
  onChange,
  aspect = 1,
  outputFormat = 'jpeg',
  accept = 'image/*',
  uploadLabel,
  hint,
  changeLabel,
}: ImageCropperProps) {
  const t = useT()
  const resolvedUploadLabel = uploadLabel ?? t('products.form.thumbnailUpload')
  const resolvedHint = hint ?? t('products.form.thumbnailHint')
  const resolvedChangeLabel = changeLabel ?? t('products.form.thumbnailChange')
  const [imageSrc, setImageSrc] = useState<string | null>(null)
  const [crop, setCrop] = useState({ x: 0, y: 0 })
  const [zoom, setZoom] = useState(1)
  const [croppedArea, setCroppedArea] = useState<Area | null>(null)

  useEffect(() => {
    setCrop({ x: 0, y: 0 })
    setZoom(1)
    setCroppedArea(null)
  }, [aspect])

  const onCropComplete = useCallback((_: Area, pixels: Area) => {
    setCroppedArea(pixels)
  }, [])

  function handleFile(e: React.ChangeEvent<HTMLInputElement>) {
    const file = e.target.files?.[0]
    if (!file) return
    const reader = new FileReader()
    reader.onload = () => {
      setImageSrc(reader.result as string)
      setCrop({ x: 0, y: 0 })
      setZoom(1)
      setCroppedArea(null)
    }
    reader.readAsDataURL(file)
    e.target.value = ''
  }

  async function applyCrop() {
    if (!imageSrc || !croppedArea) return
    const cropped = await getCroppedImage(imageSrc, croppedArea, outputFormat)
    onChange(cropped)
    setImageSrc(null)
    setZoom(1)
    setCrop({ x: 0, y: 0 })
  }

  function cancelCrop() {
    setImageSrc(null)
    setZoom(1)
    setCrop({ x: 0, y: 0 })
  }

  function removeThumbnail() {
    onChange(null)
  }

  const isPortrait = aspect < 1
  const frameStyle: React.CSSProperties = isPortrait
    ? {
        aspectRatio: `${aspect}`,
        height: 'min(480px, 65vh)',
        width: 'auto',
        maxWidth: '100%',
        marginInline: 'auto',
      }
    : {
        aspectRatio: `${aspect}`,
        width: '100%',
        maxHeight: 'min(420px, 55vh)',
      }

  return (
    <div className={styles.wrapper}>
      {value && !imageSrc && (
        <div className={styles.preview}>
          <img src={value} alt={resolvedUploadLabel} className={styles.previewImgNatural} />
          <button
            type="button"
            className={styles.removeBtn}
            onClick={removeThumbnail}
            aria-label={t('products.form.thumbnailRemove')}
          >
            <X size={16} />
          </button>
        </div>
      )}

      {!value && !imageSrc && (
        <label className={styles.uploadZone} style={frameStyle}>
          <ImagePlus size={28} />
          <span>{resolvedUploadLabel}</span>
          <span className={styles.hint}>{resolvedHint}</span>
          <input type="file" accept={accept} onChange={handleFile} hidden />
        </label>
      )}

      {imageSrc && (
        <div className={styles.cropPanel}>
          <div className={`${styles.cropArea} ${isPortrait ? styles.cropAreaPortrait : ''}`} style={frameStyle}>
            <Cropper
              key={String(aspect)}
              image={imageSrc}
              crop={crop}
              zoom={zoom}
              aspect={aspect}
              onCropChange={setCrop}
              onZoomChange={setZoom}
              onCropComplete={onCropComplete}
            />
          </div>
          <div className={styles.cropControls}>
            <label className={styles.zoomLabel}>
              {t('products.form.zoom')}
              <input
                type="range"
                min={1}
                max={3}
                step={0.05}
                value={zoom}
                onChange={(e) => setZoom(Number(e.target.value))}
              />
            </label>
            <div className={styles.cropActions}>
              <button type="button" className={styles.cancelBtn} onClick={cancelCrop}>
                {t('products.form.cancel')}
              </button>
              <button
                type="button"
                className={styles.applyBtn}
                onClick={() => void applyCrop()}
                disabled={!croppedArea}
              >
                {t('products.form.applyCrop')}
              </button>
            </div>
          </div>
        </div>
      )}

      {value && !imageSrc && (
        <label className={styles.changeBtn}>
          {resolvedChangeLabel}
          <input type="file" accept={accept} onChange={handleFile} hidden />
        </label>
      )}
    </div>
  )
}
