import React, { useEffect, useRef, useState } from "react"
import { SVGS } from "../assets/svgs"
import { ContentCard } from "./ContentCard"
import useStore from "../utils/store"
import toast from "react-hot-toast"
import CreatorSocket from "../utils/socket"
import { DEV_MODE, RIGOBOT_HOST } from "../utils/constants"
import axios from "axios"
import { useTranslation } from "react-i18next"

// `
// app.post("/read-document", upload.single("file"), async (req, res) => {
//       console.log("READING A DOCUMENT")
//       const publicToken = req.header("x-public-token")
//       if (!publicToken) {
//         return res.status(400).json({ error: "Public token is required" })
//       }

//       try {
//         // eslint-disable-next-line
//         // @ts-ignore
//         if (!req.file) {
//           return res.status(400).json({ error: "Missing file" })
//         }

//         console.log("PUBLIC TOKEN", publicToken)

//         const resultId = `document-read-${Date.now()}-${Math.floor(
//           Math.random() * 1e6
//         )}`

//         const webhookUrl = `${deploymentURL}/notifications/${resultId}`
//         console.log("WEBHOOK URL", webhookUrl)
//         // Construir form-data para enviar al servidor proxy
//         const formData = new FormData()
//         // eslint-disable-next-line
//         // @ts-ignore
//         formData.append("file", req.file.buffer, {
//           // eslint-disable-next-line
//           // @ts-ignore
//           filename: req.file.originalname,
//           // eslint-disable-next-line
//           // @ts-ignore
//           contentType: req.file.mimetype,
//         })
//         formData.append("webhook_callback_url", webhookUrl)

//         try {
//           const response = await axios.post(
//             `${RIGOBOT_HOST}/v1/learnpack/public/tools/read-document`,
//             formData,
//             {
//               headers: {
//                 ...formData.getHeaders(),
//                 Authorization: `Token ${publicToken.trim()}`,
//               },
//             }
//           )
//         } catch (error) {
//           console.error("❌ Error in /read-document:", error)
//           return res.status(500).json({ error: (error as Error).message })
//         }

//         return res.json({ notificationId: resultId, status: "PROCESSING" })
//       } catch (error) {
//         console.error("❌ Error in /read-document:", error)
//         return res.status(500).json({ error: (error as Error).message })
//       }
//     })
// `

const socketClient = new CreatorSocket("")

const allowedTypes = [
  "application/pdf",
  "application/vnd.openxmlformats-officedocument.wordprocessingml.document",
  "text/plain",
  "text/markdown",
]

export interface ParsedFile {
  name: string
  text: string
  status: "PROCESSING" | "SUCCESS" | "ERROR"
  notificationId: string
}

interface FileUploaderProps {
  styledAs?: "button" | "card"
  onFinish?: (files: ParsedFile[]) => void
}

const UploadedFileCard = ({ idx, file }: { idx: number; file: ParsedFile }) => {
  const setUploadedFiles = useStore((state) => state.setUploadedFiles)
  const uploadedFiles = useStore((state) => state.uploadedFiles)

  const handleUpdate = (data: any) => {
    if (data.text) {
      setUploadedFiles(
        uploadedFiles.map((f, i) =>
          i === idx ? { ...f, status: "SUCCESS", text: data.text } : f
        )
      )
    } else {
      setUploadedFiles(
        uploadedFiles.map((f, i) => (i === idx ? { ...f, status: "ERROR" } : f))
      )
    }
  }

  useEffect(() => {
    if (file.status === "SUCCESS") return

    console.log("CONNECTING TO SOCKET", file.notificationId)
    socketClient.connect()
    socketClient.on(file.notificationId, handleUpdate)

    socketClient.emit("registerNotification", {
      notificationId: file.notificationId,
    })

    return () => {
      socketClient.off(file.notificationId, handleUpdate)
      socketClient.disconnect()
    }
  }, [])

  return (
    <div
      className={
        "p-3 rounded-md shadow-sm text-sm text-gray-800 text-left flex items-center gap-2" +
        (file.status === "PROCESSING"
          ? " bg-gray-100"
          : file.status === "ERROR"
          ? " bg-red-100"
          : " bg-white")
      }
      title={file.name}
    >
      {file.status === "PROCESSING" && (
        <div className="w-4 h-4 border-2 border-blue-500 border-t-transparent rounded-full animate-spin" />
      )}
      {file.status === "ERROR" && (
        <span className="text-red-500 font-bold">Error!</span>
      )}

      <strong className="truncate">{file.name.slice(0, 20)}...</strong>

      <button
        className={
          "ml-auto cursor-pointer transition-colors " +
          (file.status === "PROCESSING"
            ? "text-gray-400 cursor-not-allowed"
            : "text-gray-600 hover:text-red-500")
        }
        onClick={
          () => setUploadedFiles(uploadedFiles.filter((_, i) => i !== idx))
          // Set the file as error
          // setUploadedFiles(
          //   uploadedFiles.map((f, i) =>
          //     i === idx ? { ...f, status: "ERROR" } : f
          //   )
          // )
        }
      >
        {SVGS.trash}
      </button>
    </div>
  )
}

const FileUploader: React.FC<FileUploaderProps> = ({
  styledAs = "button",
  onFinish,
}) => {
  // const rigoToken = useStore((state) => state.auth.rigoToken)
  const { t } = useTranslation()
  const publicToken = useStore((state) => state.auth.publicToken)
  const inputRef = useRef<HTMLInputElement>(null)
  const uploadedFiles = useStore((state) => state.uploadedFiles)
  const setUploadedFiles = useStore((state) => state.setUploadedFiles)
  const [isDragging, setIsDragging] = useState(false)
  const [isLoading, setIsLoading] = useState(false)
  const [limitExceededBehavior, setLimitExceededBehavior] = useState<
    "firstImages" | "cancel"
  >("firstImages")

  const extractTextFromFile = async (file: File): Promise<ParsedFile> => {
    const { type, name } = file

    if (type === "text/plain" || type === "text/markdown") {
      const text = await file.text()
      return { name, text, status: "SUCCESS", notificationId: "" }
    }

    const formData = new FormData()
    formData.append("file", file)

    const resultId = `document-read-${Date.now()}-${Math.floor(
      Math.random() * 1e6
    )}`

    const webhookUrl = `${
      DEV_MODE
        ? "https://9cw5zmww-3000.use2.devtunnels.ms"
        : window.location.origin
    }/notifications/${resultId}`
    formData.append("webhook_callback_url", webhookUrl)
    formData.append("limit_exceeded_behavior", limitExceededBehavior)

    const loadingToast = toast.loading(`Processing ${file.name}...`)
    try {
      const res = await axios.post(
        `${RIGOBOT_HOST}/v1/learnpack/public/tools/read-document`,
        formData,
        {
          headers: {
            Authorization: `Token ${publicToken.trim()}`,
          },
        }
      )

      if (res.status >= 300) throw new Error(`Failed to read ${file.name}`)
      const data = res.data
      toast.success(`Processing ${file.name}`, { id: loadingToast })
      return {
        name,
        text: "",
        status: data.status,
        notificationId: resultId,
      }
    } catch (err: any) {
      console.log(err.response.data, "ERROR IN FILE UPLOADER")
      if (err.response.data.error_code === "too_many_images") {
        toast.error(`❌ ${t("uploader.files.maxImagesPerPDFError")}`, {
          id: loadingToast,
        })
      } else {
        toast.error(t("uploader.files.errorProcessingPDF"), {
          id: loadingToast,
        })
      }

      return { name, text: "", status: "ERROR", notificationId: "" }
    }
  }

  const parseFiles = async (files: FileList | File[]) => {
    const validFiles = Array.from(files).filter((file) =>
      allowedTypes.includes(file.type)
    )
    if (validFiles.length === 0) {
      toast.error("No valid files selected")
      return
    }

    setIsLoading(true)
    const parsed = await Promise.all(validFiles.map(extractTextFromFile))
    const newFiles = [...uploadedFiles, ...parsed]

    setUploadedFiles(newFiles.filter((file) => file.status !== "ERROR"))
    setIsLoading(false)
  }

  const handleInput = async (e: React.ChangeEvent<HTMLInputElement>) => {
    if (!e.target.files) return
    await parseFiles(e.target.files)
  }

  const handleDrop = (e: React.DragEvent<HTMLDivElement>) => {
    e.preventDefault()
    setIsDragging(false)
    if (e.dataTransfer.files.length > 0) {
      parseFiles(e.dataTransfer.files)
    }
  }

  return (
    <div className="flex flex-col gap-2 w-full">
      {uploadedFiles.length > 0 && styledAs === "card" && (
        <div className="w-full flex flex-row gap-2 flex-wrap justify-center items-center">
          {uploadedFiles.map((file, idx) => (
            <UploadedFileCard key={idx} idx={idx} file={file} />
          ))}
        </div>
      )}

      {styledAs === "button" && (
        <div className="flex items-center justify-end gap-2 w-100">
          <button
            type="button"
            className="cursor-pointer blue-on-hover flex items-center justify-center w-6 h-6"
            onClick={() => inputRef.current?.click()}
          >
            {isLoading ? (
              <div className="loader w-4 h-4 border-2 border-blue-500 border-t-transparent rounded-full animate-spin" />
            ) : (
              SVGS.clip
            )}
          </button>
        </div>
      )}

      {styledAs === "card" && (
        <>
          <ContentCard
            description={
              isDragging
                ? t("uploader.files.drop")
                : isLoading
                ? t("uploader.files.processing")
                : t("uploader.files.descriptionLong")
            }
            icon={isDragging ? SVGS.clip : SVGS.pdf}
            onClick={() => inputRef.current?.click()}
            onDragOver={(e) => {
              e.preventDefault()
              setIsDragging(true)
            }}
            onDragLeave={() => setIsDragging(false)}
            onDrop={handleDrop}
            className={isDragging ? "border-blue-600 bg-blue-50" : ""}
          />
          <p className="text-xs text-gray-500">
            {t("uploader.files.maxImagesPerPDFWarning")}

            <select
              className="bg-white text-black ml-2 p-1 rounded-md"
              value={limitExceededBehavior}
              onChange={(e) =>
                setLimitExceededBehavior(
                  e.target.value as "firstImages" | "cancel"
                )
              }
            >
              <option value="firstImages">
                {t("uploader.files.useOnlyFirstImages")}
              </option>
              <option value="cancel">
                {t("uploader.files.cancelAndUploadAnother")}
              </option>
            </select>
          </p>
          <button
            disabled={uploadedFiles.some((file) => file.status !== "SUCCESS")}
            className="bg-blue-500 text-white px-4 py-2 rounded-md cursor-pointer disabled:opacity-50"
            onClick={() => {
              onFinish?.(uploadedFiles)
            }}
          >
            {t("uploader.files.finish")}
          </button>
        </>
      )}

      <input
        ref={inputRef}
        type="file"
        multiple
        accept=".pdf,.docx,.txt,.md"
        onChange={handleInput}
        style={{ display: "none" }}
      />
    </div>
  )
}

export default FileUploader
