"use client"

import * as React from "react"

import { useRouter } from "next/navigation"
import { CheckCircle2, FileText, UploadCloud, X } from "lucide-react"
import { toast } from "sonner"

import { FormSaveBar } from "@/app/dashboard/_components/form"
import { Badge } from "@/components/ui/badge"
import { Button } from "@/components/ui/button"
import {
  Card,
  CardContent,
  CardDescription,
  CardHeader,
  CardTitle,
} from "@/components/ui/card"
import { Field, FieldDescription, FieldLabel } from "@/components/ui/field"
import { uploadDeepdexFiles } from "@/components/deepdex/api/deepdex.api"
import { formatFileSize } from "@/lib/format-file-size"
import { cn } from "@/lib/utils"

const listHref = "/dashboard/deepdex/upload-queue"

export function DeepdexUploadForm({
  module = "deepdex",
  onUploaded,
}: {
  module?: "deepdex" | "structure" | "accumulator"
  onUploaded?: () => void
} = {}) {
  const router = useRouter()
  const inputRef = React.useRef<HTMLInputElement>(null)
  const [files, setFiles] = React.useState<File[]>([])
  const [isDragging, setIsDragging] = React.useState(false)
  const [isSubmitting, setIsSubmitting] = React.useState(false)

  const fileNames = files.map((file) => file.name)
  const totalSize = files.reduce((sum, file) => sum + file.size, 0)

  const setSelectedFiles = (selectedFiles: FileList | File[]) => {
    if (inputRef.current) {
      inputRef.current.value = ""
    }
    setFiles(Array.from(selectedFiles))
  }

  const onFileChange = (event: React.ChangeEvent<HTMLInputElement>) => {
    const selectedFiles = event.target.files
    setFiles(selectedFiles?.length ? Array.from(selectedFiles) : [])
  }

  const onDrop = (event: React.DragEvent<HTMLLabelElement>) => {
    event.preventDefault()
    setIsDragging(false)

    if (event.dataTransfer.files.length) {
      setSelectedFiles(event.dataTransfer.files)
    }
  }

  const removeFile = (index: number) => {
    if (inputRef.current) {
      inputRef.current.value = ""
    }
    setFiles((currentFiles) => {
      return currentFiles.filter((_, fileIndex) => fileIndex !== index)
    })
  }

  const clearFiles = () => {
    setFiles([])
    if (inputRef.current) {
      inputRef.current.value = ""
    }
  }

  const onSubmit = async (e: React.FormEvent) => {
    e.preventDefault()
    if (!fileNames.length) {
      toast.error("Select at least one file")
      return
    }
    setIsSubmitting(true)
    try {
      await uploadDeepdexFiles(files, module)
      toast.success(
        fileNames.length === 1
          ? "File added to queue"
          : `${fileNames.length} files added to queue`
      )
      if (onUploaded) {
        onUploaded()
      } else {
        router.push(listHref)
      }
    } catch {
      toast.error("Upload failed")
    } finally {
      setIsSubmitting(false)
    }
  }

  return (
    <form onSubmit={(e) => void onSubmit(e)} className="flex flex-col">
      <Card className="border-dashed shadow-xs">
        <CardHeader className="border-b bg-muted/20">
          <div className="flex flex-wrap items-start justify-between gap-3">
            <div className="space-y-1">
              <CardTitle>Upload documents</CardTitle>
              <CardDescription>
                Add PDFs, statements, reports, and other files to the Deepdex processing queue.
              </CardDescription>
            </div>
            {files.length ? (
              <Badge variant="secondary">
                {files.length} {files.length === 1 ? "file" : "files"} selected
              </Badge>
            ) : null}
          </div>
        </CardHeader>
        <CardContent className="space-y-5 pt-4">
          <Field className="gap-2">
            <FieldLabel htmlFor="deepdex-files" className="text-sm font-medium">
              Select files
            </FieldLabel>
            <label
              htmlFor="deepdex-files"
              onDragOver={(event) => {
                event.preventDefault()
                setIsDragging(true)
              }}
              onDragLeave={() => setIsDragging(false)}
              onDrop={onDrop}
              className={cn(
                "flex cursor-pointer flex-col items-center justify-center rounded-2xl border border-dashed bg-background px-6 py-10 text-center transition",
                "hover:border-primary/50 hover:bg-primary/5",
                isDragging && "border-primary bg-primary/10 ring-4 ring-primary/10"
              )}
            >
              <span className="mb-4 flex size-14 items-center justify-center rounded-2xl bg-primary/10 text-primary">
                <UploadCloud className="size-7" />
              </span>
              <span className="text-base font-medium">Drop files here or browse</span>
              <span className="mt-1 max-w-md text-muted-foreground text-sm">
                Choose one or more files. They will be queued for OCR/review, then published to Deepdex.
              </span>
              <span className="mt-4 inline-flex h-8 items-center rounded-lg bg-primary px-3 text-primary-foreground text-sm font-medium">
                Choose files
              </span>
              <input
                ref={inputRef}
                id="deepdex-files"
                type="file"
                multiple
                accept="*/*"
                className="sr-only"
                onChange={onFileChange}
              />
            </label>
            <FieldDescription>
              Supported by the current flow: all file types. Recommended files include PDF,
              XLSX, CSV, DOCX, and images.
            </FieldDescription>
          </Field>

          {files.length > 0 ? (
            <section className="rounded-xl border bg-muted/20">
              <div className="flex flex-wrap items-center justify-between gap-2 border-b px-4 py-3">
                <div>
                  <h2 className="text-sm font-medium">Ready to upload</h2>
                  <p className="text-muted-foreground text-xs">
                    {files.length} {files.length === 1 ? "file" : "files"} selected,
                    {" "}
                    {formatFileSize(totalSize)} total
                  </p>
                </div>
                <Button type="button" variant="ghost" size="sm" onClick={clearFiles}>
                  Clear all
                </Button>
              </div>
              <ul className="divide-y">
                {files.map((file, index) => (
                  <li
                    key={`${file.name}-${file.size}-${file.lastModified}-${index}`}
                    className="flex items-center gap-3 px-4 py-3"
                  >
                    <span className="flex size-9 shrink-0 items-center justify-center rounded-lg bg-background text-primary ring-1 ring-border">
                      <FileText className="size-4" />
                    </span>
                    <div className="min-w-0 flex-1">
                      <p className="truncate text-sm font-medium">{file.name}</p>
                      <p className="text-muted-foreground text-xs">{formatFileSize(file.size)}</p>
                    </div>
                    <Badge variant="outline" className="hidden sm:inline-flex">
                      <CheckCircle2 className="size-3" />
                      queued
                    </Badge>
                    <Button
                      type="button"
                      variant="ghost"
                      size="icon-sm"
                      aria-label={`Remove ${file.name}`}
                      onClick={() => removeFile(index)}
                    >
                      <X className="size-4" />
                    </Button>
                  </li>
                ))}
              </ul>
            </section>
          ) : null}
        </CardContent>
      </Card>

      <FormSaveBar
        saveLabel="Upload"
        isSaving={isSubmitting}
        status={
          files.length
            ? `${files.length} ${files.length === 1 ? "file" : "files"} ready (${formatFileSize(totalSize)})`
            : "No files selected"
        }
      />
    </form>
  )
}

