// components/web/file-uploader/BookFileUploader.tsx
"use client"

import { Card, CardContent } from "@/components/ui/card"
import { Button } from "@/components/ui/button"
import { cn } from "@/lib/utils"
import { useCallback, useState } from "react"
import { useDropzone, FileRejection } from "react-dropzone"
import { FileText, Loader2, Trash, UploadCloud } from "lucide-react"
import { toast } from "sonner"
import { uploadToS3 } from "@/lib/upload"
import { FileType } from "@/lib/schemas/books"

interface BookFileUploaderProps {
  onUploadComplete?: (key: string, fileType: FileType) => void
  onDelete?: () => void
}

interface FileState {
  file: File | null
  progress: number
  error: boolean
  isUploading: boolean
  isDeleting: boolean
  key?: string
}

function deriveFileType(file: File): FileType {
  if (file.name.endsWith(".epub")) return "EPUB"
  return "PDF"
}

export default function BookFileUploader({ onUploadComplete, onDelete }: BookFileUploaderProps) {
  const [state, setState] = useState<FileState>({
    file: null,
    progress: 0,
    error: false,
    isUploading: false,
    isDeleting: false,
  })

  async function handleUpload(file: File) {
    setState(prev => ({ ...prev, isUploading: true, progress: 0, error: false }))
    try {
      const key = await uploadToS3(file, false, (percent) => {
        setState(prev => ({ ...prev, progress: percent }))
      }, "books/files");
      const fileType = deriveFileType(file)
      setState(prev => ({ ...prev, isUploading: false, key, file }))
      onUploadComplete?.(key, fileType)
      toast.success("File uploaded successfully")
    } catch {
      setState(prev => ({ ...prev, isUploading: false, error: true }))
      toast.error("Failed to upload file")
    }
  }

  async function handleDelete() {
    if (!state.key) return
    setState(prev => ({ ...prev, isDeleting: true }))
    try {
      await fetch("/api/s3/delete", {
        method: "DELETE",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify({ key: state.key }),
      })
      setState({ file: null, progress: 0, error: false, isUploading: false, isDeleting: false })
      onDelete?.()
      toast.success("File removed")
    } catch {
      setState(prev => ({ ...prev, isDeleting: false }))
      toast.error("Failed to delete file")
    }
  }

  const onDrop = useCallback((accepted: File[]) => {
    if (accepted.length > 0) handleUpload(accepted[0])
  }, [])

  function onDropRejected(rejections: FileRejection[]) {
    const tooLarge = rejections.find(r => r.errors[0].code === "file-too-large")
    if (tooLarge) toast.error("File too large. Maximum size is 50MB")
    else toast.error("Only PDF and EPUB files are accepted")
  }

  const { getRootProps, getInputProps, isDragActive } = useDropzone({
    onDrop,
    onDropRejected,
    accept: {
      "application/pdf": [".pdf"],
      "application/epub+zip": [".epub"],
    },
    maxFiles: 1,
    maxSize: 1024 * 1024 * 50, // 50MB
    disabled: state.isUploading || !!state.file,
  })

  // ── Render states ──────────────────────────────────────

  if (state.isUploading) {
    return (
      <Card className="border-2 border-dashed border-primary w-full h-40">
        <CardContent className="flex flex-col items-center justify-center h-full gap-2">
          <Loader2 className="size-6 animate-spin text-primary" />
          <p className="text-sm font-medium">Uploading...</p>
          <p className="text-xs text-muted-foreground">{state.file?.name}</p>
        </CardContent>
      </Card>
    )
  }

  if (state.file && state.key) {
    return (
      <Card className="border-2 border-border w-full h-40">
        <CardContent className="flex items-center justify-between h-full px-6">
          <div className="flex items-center gap-3">
            <div className="flex items-center justify-center size-10 rounded-lg bg-primary/10">
              <FileText className="size-5 text-primary" />
            </div>
            <div>
              <p className="text-sm font-medium truncate max-w-xs">{state.file.name}</p>
              <p className="text-xs text-muted-foreground">
                {deriveFileType(state.file)} · {(state.file.size / 1024 / 1024).toFixed(2)}MB
              </p>
            </div>
          </div>
          <Button
            type="button"
            variant="destructive"
            size="icon"
            onClick={handleDelete}
            disabled={state.isDeleting}
          >
            {state.isDeleting
              ? <Loader2 className="size-4 animate-spin" />
              : <Trash className="size-4" />
            }
          </Button>
        </CardContent>
      </Card>
    )
  }

  if (state.error) {
    return (
      <Card className="border-2 border-dashed border-destructive w-full h-40">
        <CardContent className="flex flex-col items-center justify-center h-full gap-2">
          <p className="text-sm font-semibold">Upload Failed</p>
          <p className="text-xs text-muted-foreground">Something went wrong, try again</p>
        </CardContent>
      </Card>
    )
  }

  if (state.isUploading) {
    return (
        <Card className="border-2 border-dashed border-primary w-full h-40">
            <CardContent className="flex flex-col items-center justify-center h-full gap-2">
                <Loader2 className="size-6 animate-spin text-primary" />
                <p className="text-sm font-medium">Uploading... {state.progress}%</p>
                <p className="text-xs text-muted-foreground">{state.file?.name}</p>
            </CardContent>
        </Card>
    )
  }

  return (
    <Card
      {...getRootProps()}
      className={cn(
        "relative border-2 border-dashed transition-colors duration-200 w-full h-40 cursor-pointer",
        isDragActive ? "border-primary bg-primary/10" : "border-border hover:border-primary"
      )}
    >
      <CardContent className="flex flex-col items-center justify-center h-full gap-2">
        <input {...getInputProps()} />
        <UploadCloud className={cn("size-8 text-muted-foreground", isDragActive && "text-primary")} />
        <p className="text-sm font-semibold">
          Drop your file here or <span className="text-primary">click to upload</span>
        </p>
        <p className="text-xs text-muted-foreground">PDF or EPUB · Max 50MB</p>
      </CardContent>
    </Card>
  )
}