import React, { useRef, useState, useEffect, ChangeEvent } from "react";
import {
  ArrowDownTrayIcon,
  ArrowUpTrayIcon,
  CheckCircleIcon,
} from "@heroicons/react/24/outline";
import api from "../../utils/axios";
import { useBackdropStore } from "../../context/zustand-store/appStore";
import { useToast } from "../../hooks/useToast";
import { useUserProfileStore } from "../../context/zustand-store/userStore";
import { RolesContextMenu } from "../Button/RolesContextMenu";

interface DocumentOperationProps {
  downloadLink: string;
  uploadLink: string;
  validFiles?: string[];
  payloadKey: string;
  onUploadSuccess?: () => void;
  page?: string;
  access?: string;
  limitSize?: number;
}

const buildAcceptString = (extensions: string[]): string => {
  const mimeTypes: string[] = [];

  extensions.forEach((ext) => {
    const lower = ext.toLowerCase().replace(".", "");

    if (lower === "img" || lower === "image") {
      mimeTypes.push("image/*");
    } else {
      mimeTypes.push(`.${lower}`);
    }
  });

  return mimeTypes.join(",");
};

export const DocumentOperation = ({
  downloadLink,
  uploadLink,
  validFiles = [],
  payloadKey,
  onUploadSuccess,
  page = "",
  access = "",
  limitSize,
}: DocumentOperationProps) => {
  const { openBackdrop, closeBackdrop } = useBackdropStore();
  const showToast = useToast();
  const fileInputRef = useRef<HTMLInputElement>(null);
  const [uploadedFileName, setUploadedFileName] = useState<string>("");
  const { profile } = useUserProfileStore();
  const [contextMenu, setContextMenu] = useState<{
    x: number;
    y: number;
  } | null>(null);

  const isAdmin = profile?.role?.type?.key === "ADM";

  const ableToSee = () => {
    if (!access || !page) {
      return true;
    }
    const found = profile?.permissions?.find(
      (item: any) => item.page_name === page,
    );
    if (found && found.page_access.includes(access)) {
      return true;
    }
    return false;
  };

  const handleContextMenu = (e: React.MouseEvent<HTMLDivElement>) => {
    if (isAdmin && page && access) {
      e.preventDefault();
      e.stopPropagation();
      setContextMenu({
        x: e.clientX,
        y: e.clientY,
      });
    }
  };

  useEffect(() => {
    const handleClick = () => {
      if (contextMenu) {
        setContextMenu(null);
      }
    };

    if (contextMenu) {
      document.addEventListener("click", handleClick);
    }

    return () => {
      document.removeEventListener("click", handleClick);
    };
  }, [contextMenu]);

  const handleDownload = async () => {
    if (!downloadLink) return;

    openBackdrop();
    try {
      const response = await api.get(downloadLink, {
        responseType: "blob",
      });

      const contentDisposition = response.headers["content-disposition"];
      let fileName = "document";

      if (contentDisposition) {
        const match = contentDisposition.match(
          /filename\*?=(?:UTF-8''|"?)([^";]+)/i,
        );
        if (match?.[1]) {
          fileName = decodeURIComponent(match[1].replace(/"/g, ""));
        }
      } else {
        const urlParts = downloadLink.split("/").filter(Boolean);
        const lastPart = urlParts[urlParts.length - 1];
        if (lastPart && lastPart.includes(".")) {
          fileName = lastPart;
        }
      }

      const url = window.URL.createObjectURL(new Blob([response.data]));
      const link = document.createElement("a");
      link.href = url;
      link.setAttribute("download", fileName);
      document.body.appendChild(link);
      link.click();
      document.body.removeChild(link);
      window.URL.revokeObjectURL(url);

      showToast("فایل با موفقیت دانلود شد", "success");
    } catch {
      showToast("خطا در دانلود فایل", "error");
    } finally {
      closeBackdrop();
    }
  };

  const handleUploadClick = () => {
    fileInputRef.current?.click();
  };

  const handleFileChange = async (e: ChangeEvent<HTMLInputElement>) => {
    const file = e.target.files?.[0];
    if (!file) return;

    if (fileInputRef.current) {
      fileInputRef.current.value = "";
    }

    if (limitSize && file.size > limitSize * 1024 * 1024) {
      showToast(`حداکثر حجم فایل ${limitSize} مگابایت است`, "error");
      return;
    }

    openBackdrop();
    try {
      const formData = new FormData();
      formData.append(payloadKey, file);

      await api.post(uploadLink, formData, {
        headers: {
          "Content-Type": "multipart/form-data",
        },
      });

      setUploadedFileName(file.name);
      showToast("فایل با موفقیت آپلود شد", "success");
      onUploadSuccess?.();
    } catch {
      showToast("خطا در آپلود فایل", "error");
    } finally {
      closeBackdrop();
    }
  };

  const acceptString =
    validFiles.length > 0 ? buildAcceptString(validFiles) : undefined;

  return (
    <>
      <div
        className="inline-flex items-center"
        onContextMenu={handleContextMenu}
      >
        <input
          type="file"
          ref={fileInputRef}
          onChange={handleFileChange}
          className="hidden"
          accept={acceptString}
        />

        <button
          type="button"
          onClick={handleDownload}
          disabled={!downloadLink || !ableToSee()}
          className="flex items-center gap-1.5 px-3 py-1.5 text-sm rounded-r-lg border border-l-0 border-primary-300 dark:border-dark-400 bg-primary-50 dark:bg-dark-600 text-primary-700 dark:text-primary-200 hover:bg-primary-100 dark:hover:bg-dark-500 transition-colors duration-200 cursor-pointer disabled:opacity-50 disabled:cursor-not-allowed"
        >
          <ArrowDownTrayIcon className="w-4 h-4" />
          <span>دانلود</span>
        </button>

        <button
          type="button"
          onClick={handleUploadClick}
          disabled={!uploadLink || !ableToSee()}
          className="flex items-center gap-1.5 px-3 py-1.5 text-sm rounded-l-lg border border-primary-300 dark:border-dark-400 bg-primary-600 dark:bg-primary-700 text-white hover:bg-primary-500 dark:hover:bg-primary-800 transition-colors duration-200 cursor-pointer disabled:opacity-50 disabled:cursor-not-allowed"
        >
          {uploadedFileName ? (
            <CheckCircleIcon className="w-4 h-4 text-green-300" />
          ) : (
            <ArrowUpTrayIcon className="w-4 h-4" />
          )}
          <span>آپلود</span>
        </button>
      </div>

      {contextMenu && page && access && (
        <RolesContextMenu
          page={page}
          access={access}
          position={contextMenu}
          onClose={() => setContextMenu(null)}
        />
      )}
    </>
  );
};
