"use client";

import { useTranslations } from "next-intl";
import { useState, useRef, useEffect } from "react";
import { FiPlusCircle, FiX } from "react-icons/fi";
import { MdOutlineFileUpload } from "react-icons/md";

interface FileItem {
  file: File | null;
  url: string;
  serverData?: any;
}

interface Props {
  multiple?: boolean;
  fileType?: "image" | "video";
  onChange: (value: File[] | File | null) => void;
  value?: File[] | File | null;
}

export default function ImageUploader({
  multiple = false,
  onChange,
  fileType = "image",
  value,
}: Props) {
  const [files, setFiles] = useState<FileItem[]>([]);
  const [error, setError] = useState<string>("");
  const fileInputRef = useRef<HTMLInputElement>(null);
  const errorTimeoutRef = useRef<NodeJS.Timeout | null>(null);
  const t=useTranslations();
  const acceptedMimeType: Record<string, string> = {
    image: "image/*",
    video: "video/*",
  };

  const fileTypeExtensions: Record<string, string[]> = {
    image: [".jpg", ".jpeg", ".png", ".gif", ".bmp", ".webp", ".svg"],
    video: [".mp4", ".mov", ".avi", ".wmv", ".flv", ".mkv", ".webm"],
  };

  const matchesFileType = (file: File) => {
    return file.type.startsWith(`${fileType}/`);
  };

  const getFileExtension = (filename: string): string => {
    return filename.slice(((filename.lastIndexOf(".") - 1) >>> 0) + 2).toLowerCase();
  };

  const isValidFileExtension = (filename: string): boolean => {
    const extension = getFileExtension(filename);
    return fileTypeExtensions[fileType].includes(`.${extension}`);
  };

  // Clear timeout on component unmount
  useEffect(() => {
    return () => {
      if (errorTimeoutRef.current) {
        clearTimeout(errorTimeoutRef.current);
      }
    };
  }, []);

  const setAutoDismissError = (message: string) => {
    // Clear any existing timeout
    if (errorTimeoutRef.current) {
      clearTimeout(errorTimeoutRef.current);
    }

    // Set new error message
    setError(message);

    // Set timeout to clear error after 3 seconds
    errorTimeoutRef.current = setTimeout(() => {
      setError("");
      errorTimeoutRef.current = null;
    }, 3000);
  };

  useEffect(() => {
    if (value) {
      const files = Array.isArray(value) ? value : [value];
      const imageFiles = files
        .map((item: any) => {
          if (item instanceof File) {
            return {
              file: item,
              url: URL.createObjectURL(item),
            };
          }

          if (typeof item === "object") {
            return {
              file: null,
              url: item?.location?.startsWith("http")
                ? item.location
                : `${process.env.NEXT_PUBLIC_API}${item?.location}`,
              serverData: item,
            };
          }

          return null;
        })
        .filter((f): f is FileItem => f !== null);
      setFiles(imageFiles);
    } else {
      setFiles([]);
    }
  }, [value]);

  const handleDrop = (e: React.DragEvent<HTMLDivElement>) => {
    e.preventDefault();
    setError("");
    const files = Array.from(e.dataTransfer.files);
    handleFiles(files);
  };

  const handleBrowse = (e: React.ChangeEvent<HTMLInputElement>) => {
    if (!e.target.files) return;
    setError("");
    const files = Array.from(e.target.files);
    handleFiles(files);

    // Reset the input value to allow selecting the same file again
    if (fileInputRef.current) {
      fileInputRef.current.value = "";
    }
  };

  const handleFiles = (incomingFiles: File[]) => {
    // Validate file types
    const invalidFiles = incomingFiles.filter(file => !matchesFileType(file));

    if (invalidFiles.length > 0) {
      const invalidFileNames = invalidFiles.map(f => f.name).join(", ");
      setAutoDismissError(`Invalid file type. Please select ${fileType} files only. Invalid files: ${invalidFileNames}`);
      return;
    }

    // Validate file extensions as an additional safety measure
    const filesWithInvalidExtensions = incomingFiles.filter(file => !isValidFileExtension(file.name));

    if (filesWithInvalidExtensions.length > 0) {
      const invalidFileNames = filesWithInvalidExtensions.map(f => f.name).join(", ");
      setAutoDismissError(`Invalid file extension. Allowed extensions for ${fileType}: ${fileTypeExtensions[fileType].join(", ")}. Invalid files: ${invalidFileNames}`);
      return;
    }

    let validFiles = incomingFiles.filter(matchesFileType);

    if (fileType === "video") {
      const currentVideoCount = files.filter((f) => {
        if (f.file) {
          return f.file.type.startsWith("video/");
        }

        return /\.(mp4|mov|avi|wmv|flv|mkv)$/i.test(f.url);
      }).length;

      const count = 3 - currentVideoCount;
      validFiles = validFiles.slice(0, count);
    }

    const newItems = validFiles.map((file) => ({
      file,
      url: URL.createObjectURL(file),
    }));

    const updatedList: any = multiple ? [...files, ...newItems] : [newItems[0]];

    setFiles(updatedList);

    const selectedFiles = multiple
      ? updatedList.map((f: any) => f.file || f.serverData)
      : updatedList[0]?.file || updatedList[0]?.serverData || null;

    onChange(selectedFiles);
  };

  const handleRemove = (index: number) => {
    const updated = files.filter((_, i) => i !== index);
    setFiles(updated);

    if (multiple) {
      const updatedFiles = updated.map((f) => f.file || f.serverData);
      onChange(updatedFiles);
    } else {
      const firstItem = updated[0];
      onChange(firstItem ? firstItem.file || firstItem.serverData : null);
    }
  };

  const renderPreview = (item: FileItem, index: number) => {
    if (fileType === "video" || item.file?.type.startsWith("video")) {
      return (
        <video
          src={item?.url}
          controls
          className="w-full h-full object-cover rounded-md border p-2 border-neutrals300 dark:border-darkborder"
        />
      );
    }

    return (
      <img
        src={item?.url}
        alt={`upload-${index}`}
        className="w-full h-full object-cover rounded-md border p-2 border-neutrals300 dark:border-darkborder"
      />
    );
  };

  return (
    <div className="relative">
      <label className="block text-sm font-medium text-neutrals800 mb-1 dark:text-neutrals400">
        {/* Upload File <span className="text-red">*</span> */}
      </label>

      <div
        onClick={() => fileInputRef.current?.click()}
        onDrop={handleDrop}
        onDragOver={(e) => e.preventDefault()}
        className="flex flex-col items-center justify-center border-2 border-dashed border-neutrals100 rounded-xl py-10 px-5 text-center cursor-pointer dark:hover:border-primary600 dark:border-darkborder"
      >
        <MdOutlineFileUpload size={28} className="text-neutrals400 mb-2" />
        <p className="text-sm text-neutrals500 dark:text-neutrals400">
          {t("drag_and_drop")}
        </p>
        <p className="text-sm text-neutrals500 my-4 dark:text-neutrals400">
          {t("or")}
        </p>
        <label className="cursor-pointer flex items-center gap-1 text-primary500 font-medium text-sm dark:text-primary400">
          <FiPlusCircle /> {t("browse")}
        </label>
        <input
          type="file"
          ref={fileInputRef}
          className="hidden"
          accept={acceptedMimeType[fileType]}
          multiple={multiple}
          onChange={handleBrowse}
        />
      </div>

      {error && (
        <div className="mt-2 p-2 bg-red-50 border border-red-200 rounded-md">
          <p className="text-sm text-red-600">{error}</p>
        </div>
      )}

      {files.length > 0 && (
        <div className="flex flex-wrap gap-4 mt-4">
          {files.map((item, index) => (
            <div key={index} className="relative w-24 h-24">
              {renderPreview(item, index)}
              <button
                type="button"
                onClick={() => handleRemove(index)}
                className="absolute top-1 right-1 bg-kzblack100 p-1 text-xs text-primary500 hover:bg-primary500 hover:text-white dark:bg-primary400 dark:hover:opacity-100 dark:opacity-80 dark:hover:bg-primary600 dark:text-white"
              >
                <FiX size={14} />
              </button>
            </div>
          ))}
        </div>
      )}
    </div>
  );
}