import { gothampro, fluxgore } from "@/utils/fonts";
import React, { useState, useRef, DragEvent, ChangeEvent } from "react";

interface FileUploadProps {
  label?: string;
  onFileSelect?: (files: File[]) => void;
  acceptedTypes?: string[];
  maxFileSize?: number; // in MB
  maxFiles?: number; // maximum number of files
  multiple?: boolean;
  disabled?: boolean;
  placeholder?: string;
  id?: string;
  name?: string;
  required?: boolean;
}

function Fileupload({
  label,
  onFileSelect,
  acceptedTypes = ["image/*", "application/pdf", ".doc", ".docx"],
  maxFileSize = 10,
  maxFiles = 5,
  multiple = false,
  disabled = false,
  placeholder = "Файл в формате jpg или png до N мб",
  id,
  name,
  required = false,
}: FileUploadProps) {
  const [dragActive, setDragActive] = useState(false);
  const [selectedFiles, setSelectedFiles] = useState<File[]>([]);
  const [errors, setErrors] = useState<string[]>([]);
  const fileInputRef = useRef<HTMLInputElement>(null);

  const validateFiles = (
    files: File[]
  ): { valid: File[]; errors: string[] } => {
    const validFiles: File[] = [];
    const fileErrors: string[] = [];

    files.forEach((file) => {
      // Check file size
      if (file.size > maxFileSize * 1024 * 1024) {
        fileErrors.push(`${file.name} is too large (max ${maxFileSize}MB)`);
        return;
      }

      // Check file type
      const isValidType = acceptedTypes.some((type) => {
        if (type.includes("*")) {
          return file.type.startsWith(type.split("*")[0]);
        }
        return file.type === type || file.name.toLowerCase().endsWith(type);
      });

      if (!isValidType) {
        fileErrors.push(`${file.name} is not a supported file type`);
        return;
      }

      validFiles.push(file);
    });

    return { valid: validFiles, errors: fileErrors };
  };

  const handleFiles = (files: FileList | null) => {
    if (!files) return;

    const fileArray = Array.from(files);
    const { valid, errors: validationErrors } = validateFiles(fileArray);
    const allErrors = [...validationErrors];

    if (valid.length > 0) {
      let newFiles: File[];

      if (multiple) {
        // Check if adding new files would exceed maxFiles limit
        const totalFiles = selectedFiles.length + valid.length;
        if (totalFiles > maxFiles) {
          const allowedCount = maxFiles - selectedFiles.length;
          if (allowedCount <= 0) {
            allErrors.push(
              `Maximum ${maxFiles} files allowed. Remove some files first.`
            );
            setErrors(allErrors);
            return;
          } else {
            allErrors.push(
              `Only ${allowedCount} more files can be added (max ${maxFiles} total).`
            );
            newFiles = [...selectedFiles, ...valid.slice(0, allowedCount)];
          }
        } else {
          newFiles = [...selectedFiles, ...valid];
        }
      } else {
        newFiles = valid;
      }

      setSelectedFiles(newFiles);
      onFileSelect?.(newFiles);
    }

    setErrors(allErrors);
  };

  const handleDrag = (e: DragEvent<HTMLDivElement>) => {
    e.preventDefault();
    e.stopPropagation();
    if (e.type === "dragenter" || e.type === "dragover") {
      setDragActive(true);
    } else if (e.type === "dragleave") {
      setDragActive(false);
    }
  };

  const handleDrop = (e: DragEvent<HTMLDivElement>) => {
    e.preventDefault();
    e.stopPropagation();
    setDragActive(false);

    if (disabled) return;

    if (e.dataTransfer.files) {
      handleFiles(e.dataTransfer.files);
    }
  };

  const handleInputChange = (e: ChangeEvent<HTMLInputElement>) => {
    handleFiles(e.target.files);
  };

  const removeFile = (index: number) => {
    const updatedFiles = selectedFiles.filter((_, i) => i !== index);
    setSelectedFiles(updatedFiles);
    onFileSelect?.(updatedFiles);
  };

  const openFileDialog = () => {
    if (!disabled && fileInputRef.current) {
      fileInputRef.current.click();
    }
  };

  // Check if upload button should be disabled
  const isUploadDisabled =
    disabled || (multiple && selectedFiles.length >= maxFiles);

  return (
    <div className="w-full">
      {label && (
        <label
          htmlFor={id || name}
          className={`${gothampro.className} text-base font-bold text-black`}
        >
          {label}
          {required && <span className="text-red-500 ml-1">*</span>}
        </label>
      )}

      {/* Upload Area */}
      <div
        className={`
          flex items-center overflow-hidden transition-colors
          ${dragActive ? "border-[#1068B0] bg-[#1068B0]/10" : "border-gray-300"}
          ${
            isUploadDisabled
              ? "opacity-50 cursor-not-allowed"
              : "hover:border-[#1068B0]"
          }
        `}
        onDragEnter={handleDrag}
        onDragLeave={handleDrag}
        onDragOver={handleDrag}
        onDrop={handleDrop}
      >
        <input
          ref={fileInputRef}
          type="file"
          className="hidden"
          multiple={multiple}
          accept={acceptedTypes.join(",")}
          onChange={handleInputChange}
          disabled={isUploadDisabled}
          id={id}
          name={name}
        />

        {/* Upload Button */}
        <button
          type="button"
          onClick={openFileDialog}
          disabled={isUploadDisabled}
          className={`${fluxgore.className} bg-[#1068B0] hover:bg-[#0d5a96] text-white px-9 py-4 text-base font-medium uppercase tracking-wide disabled:opacity-50`}
        >
          ПРИКРЕПИТЬ
        </button>

        {/* File Display Area */}
        <div className="flex-1 px-3 py-2 min-h-[40px] flex items-center">
          {selectedFiles.length > 0 ? (
            <div className="flex items-center justify-between">
              <span className="text-sm text-gray-900 truncate">
                {selectedFiles[0].name}
                {multiple && selectedFiles.length > 1 && (
                  <span className="text-gray-500 ml-1">
                    and {selectedFiles.length - 1} more
                  </span>
                )}
              </span>
              <button
                type="button"
                onClick={(e) => {
                  e.stopPropagation();
                  removeFile(0);
                }}
                className="ml-2 p-1 text-gray-400 hover:text-gray-600"
              >
                <svg
                  className="w-4 h-4"
                  fill="none"
                  stroke="currentColor"
                  viewBox="0 0 24 24"
                >
                  <path
                    strokeLinecap="round"
                    strokeLinejoin="round"
                    strokeWidth={2}
                    d="M19 7l-.867 12.142A2 2 0 0116.138 21H7.862a2 2 0 01-1.995-1.858L5 7m5 4v6m4-6v6m1-10V4a1 1 0 00-1-1h-4a1 1 0 00-1 1v3M4 7h16"
                  />
                </svg>
              </button>
            </div>
          ) : (
            <span className={`${gothampro.className} text-sm text-gray-500`}>
              {placeholder.replace("N", maxFileSize.toString())}
            </span>
          )}
        </div>
      </div>

      {/* File count indicator for multiple files */}
      {multiple && selectedFiles.length > 0 && (
        <div className="mt-1 text-xs text-gray-500">
          {selectedFiles.length} of {maxFiles} files selected
        </div>
      )}

      {/* Error Messages */}
      {errors.length > 0 && (
        <div className="mt-2 text-sm text-red-600">
          {errors.map((error, index) => (
            <div key={index}>{error}</div>
          ))}
        </div>
      )}

      {/* Additional Files (if multiple) */}
      {multiple && selectedFiles.length > 1 && (
        <div className="mt-2 space-y-1">
          {selectedFiles.slice(1).map((file, index) => (
            <div
              key={index + 1}
              className="flex items-center justify-between p-2 bg-gray-50 rounded text-sm"
            >
              <span className="truncate">{file.name}</span>
              <button
                type="button"
                onClick={() => removeFile(index + 1)}
                className="ml-2 p-1 text-gray-400 hover:text-gray-600"
              >
                <svg
                  className="w-4 h-4"
                  fill="none"
                  stroke="currentColor"
                  viewBox="0 0 24 24"
                >
                  <path
                    strokeLinecap="round"
                    strokeLinejoin="round"
                    strokeWidth={2}
                    d="M19 7l-.867 12.142A2 2 0 0116.138 21H7.862a2 2 0 01-1.995-1.858L5 7m5 4v6m4-6v6m1-10V4a1 1 0 00-1-1h-4a1 1 0 00-1 1v3M4 7h16"
                  />
                </svg>
              </button>
            </div>
          ))}
        </div>
      )}
    </div>
  );
}

export default Fileupload;
