import { useState, useRef, useEffect, useCallback } from 'react'
import { Loader2, X, RotateCcw, ImagePlus } from 'lucide-react'
import { cn } from '@/lib/utils'
import { uploadsApi } from '@/api/uploads'
import type { FileUploadResponse, PendingUpload } from '@/types/upload'

interface RichTextInputProps {
  value: string
  onChange: (value: string) => void
  onFilesChange?: (uploads: FileUploadResponse[]) => void
  sessionId?: string
  placeholder?: string
  rows?: number
  className?: string
  disabled?: boolean
}

export function RichTextInput({
  value,
  onChange,
  onFilesChange,
  sessionId,
  placeholder,
  rows = 3,
  className,
  disabled,
}: RichTextInputProps) {
  const [pendingUploads, setPendingUploads] = useState<PendingUpload[]>([])
  const [isDragOver, setIsDragOver] = useState(false)
  const [isFocused, setIsFocused] = useState(false)
  const textareaRef = useRef<HTMLTextAreaElement>(null)
  const dragCounterRef = useRef(0)

  // Cleanup blob URLs on unmount
  useEffect(() => {
    return () => {
      pendingUploads.forEach((upload) => {
        URL.revokeObjectURL(upload.preview)
      })
    }
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [])

  const processFiles = useCallback(
    (files: File[]) => {
      const imageFiles = files.filter((f) => f.type.startsWith('image/'))
      if (imageFiles.length === 0) return

      const newUploads: PendingUpload[] = imageFiles.map((file) => ({
        id: crypto.randomUUID(),
        file,
        preview: URL.createObjectURL(file),
        status: 'uploading' as const,
      }))

      setPendingUploads((prev) => [...prev, ...newUploads])

      // Upload each file
      newUploads.forEach((upload) => {
        uploadsApi
          .upload(upload.file, sessionId)
          .then((result) => {
            setPendingUploads((prev) => {
              const updated = prev.map((u) =>
                u.id === upload.id ? { ...u, status: 'done' as const, result } : u
              )
              // Notify parent of all completed uploads
              const completed = updated
                .filter((u) => u.status === 'done' && u.result)
                .map((u) => u.result!)
              onFilesChange?.(completed)
              return updated
            })
          })
          .catch((err) => {
            const errorMsg = err?.response?.status === 503
              ? 'File uploads not available — contact your administrator'
              : err?.message || 'Upload failed'
            setPendingUploads((prev) =>
              prev.map((u) =>
                u.id === upload.id
                  ? { ...u, status: 'error' as const, error: errorMsg }
                  : u
              )
            )
          })
      })
    },
    [sessionId, onFilesChange]
  )

  const handlePaste = useCallback(
    (e: React.ClipboardEvent<HTMLTextAreaElement>) => {
      if (disabled) return
      const items = e.clipboardData?.items
      if (!items) return

      const imageFiles: File[] = []
      for (let i = 0; i < items.length; i++) {
        const item = items[i]
        if (item.type.startsWith('image/')) {
          const file = item.getAsFile()
          if (file) imageFiles.push(file)
        }
      }

      if (imageFiles.length > 0) {
        e.preventDefault()
        processFiles(imageFiles)
      }
    },
    [disabled, processFiles]
  )

  const handleDragOver = useCallback(
    (e: React.DragEvent) => {
      if (disabled) return
      e.preventDefault()
      e.dataTransfer.dropEffect = 'copy'
    },
    [disabled]
  )

  const handleDragEnter = useCallback(
    (e: React.DragEvent) => {
      if (disabled) return
      e.preventDefault()
      dragCounterRef.current++
      if (dragCounterRef.current === 1) {
        setIsDragOver(true)
      }
    },
    [disabled]
  )

  const handleDragLeave = useCallback(
    (e: React.DragEvent) => {
      e.preventDefault()
      dragCounterRef.current--
      if (dragCounterRef.current === 0) {
        setIsDragOver(false)
      }
    },
    []
  )

  const handleDrop = useCallback(
    (e: React.DragEvent) => {
      if (disabled) return
      e.preventDefault()
      dragCounterRef.current = 0
      setIsDragOver(false)

      const files = Array.from(e.dataTransfer.files)
      processFiles(files)
    },
    [disabled, processFiles]
  )

  const handleRemove = useCallback(
    (uploadId: string) => {
      setPendingUploads((prev) => {
        const toRemove = prev.find((u) => u.id === uploadId)
        if (toRemove) {
          URL.revokeObjectURL(toRemove.preview)
        }
        const updated = prev.filter((u) => u.id !== uploadId)
        const completed = updated
          .filter((u) => u.status === 'done' && u.result)
          .map((u) => u.result!)
        onFilesChange?.(completed)
        return updated
      })
    },
    [onFilesChange]
  )

  const retryUpload = useCallback(
    (uploadId: string) => {
      setPendingUploads((prev) =>
        prev.map((u) => (u.id === uploadId ? { ...u, status: 'uploading' as const, error: undefined } : u))
      )

      const upload = pendingUploads.find((u) => u.id === uploadId)
      if (!upload) return

      uploadsApi
        .upload(upload.file, sessionId)
        .then((result) => {
          setPendingUploads((prev) => {
            const updated = prev.map((u) =>
              u.id === uploadId ? { ...u, status: 'done' as const, result } : u
            )
            const completed = updated
              .filter((u) => u.status === 'done' && u.result)
              .map((u) => u.result!)
            onFilesChange?.(completed)
            return updated
          })
        })
        .catch((err) => {
          const errorMsg = err?.response?.status === 503
            ? 'File uploads not available — contact your administrator'
            : err?.message || 'Upload failed'
          setPendingUploads((prev) =>
            prev.map((u) =>
              u.id === uploadId
                ? { ...u, status: 'error' as const, error: errorMsg }
                : u
            )
          )
        })
    },
    [pendingUploads, sessionId, onFilesChange]
  )

  return (
    <div
      className={cn('relative', className)}
      onDragOver={handleDragOver}
      onDragEnter={handleDragEnter}
      onDragLeave={handleDragLeave}
      onDrop={handleDrop}
    >
      <textarea
        ref={textareaRef}
        value={value}
        onChange={(e) => onChange(e.target.value)}
        onPaste={handlePaste}
        onFocus={() => setIsFocused(true)}
        onBlur={() => setIsFocused(false)}
        placeholder={placeholder}
        rows={rows}
        disabled={disabled}
        className={cn(
          'w-full bg-card border border-border rounded-xl p-3 text-sm text-foreground placeholder:text-muted-foreground',
          'focus:border-[rgba(96,165,250,0.3)] focus:outline-none resize-none transition-colors',
          isDragOver && 'border-primary/50 bg-primary/5',
          disabled && 'opacity-50 cursor-not-allowed'
        )}
      />

      {/* Drag overlay hint */}
      {isDragOver && (
        <div className="absolute inset-0 flex items-center justify-center rounded-xl border-2 border-dashed border-primary/50 bg-primary/5 pointer-events-none">
          <div className="flex items-center gap-2 text-sm text-primary">
            <ImagePlus size={16} />
            Drop image to attach
          </div>
        </div>
      )}

      {/* Thumbnail strip */}
      {pendingUploads.length > 0 && (
        <div className="flex gap-2 flex-wrap mt-2">
          {pendingUploads.map((upload) => (
            <div key={upload.id} className="relative w-16 h-16 rounded-lg overflow-hidden border border-border">
              <img src={upload.preview} alt="" className="w-full h-full object-cover" />
              {upload.status === 'uploading' && (
                <div className="absolute inset-0 bg-background/50 flex items-center justify-center">
                  <Loader2 size={16} className="animate-spin text-primary" />
                </div>
              )}
              {upload.status === 'done' && (
                <button
                  onClick={() => handleRemove(upload.id)}
                  className="absolute -top-1 -right-1 w-4 h-4 rounded-full bg-background/80 border border-border flex items-center justify-center hover:bg-rose-500/20 transition-colors"
                >
                  <X size={10} className="text-muted-foreground" />
                </button>
              )}
              {upload.status === 'error' && (
                <div
                  className="absolute inset-0 bg-rose-500/20 border-2 border-rose-500 flex items-center justify-center cursor-pointer"
                  onClick={() => retryUpload(upload.id)}
                >
                  <RotateCcw size={14} className="text-rose-500" />
                </div>
              )}
            </div>
          ))}
        </div>
      )}

      {/* Paste hint */}
      {isFocused && !value && pendingUploads.length === 0 && (
        <p className="text-[0.625rem] text-muted-foreground/50 mt-1">Paste screenshots with Ctrl+V</p>
      )}
    </div>
  )
}
