import { useEffect, useRef, useState } from "react";
import { motion, AnimatePresence } from "framer-motion";
import { createPortal } from "react-dom";
import Typography from "../Typography/Typography";
import Checkbox from "../CheckBox/CheckBox";
import { useApiRequest } from "../../utils/useApiRequest";
import { useFetchProfile } from "../../hooks/useFetchProfile";
import { useQueryClient } from "@tanstack/react-query";
import { useToast } from "../../hooks/useToast";
import api from "../../utils/axios";
import { getFaPermissions } from "../../utils/getFaPermissions";

type RolesContextMenuProps = {
  page: string;
  access: string;
  isPage?: boolean;
  position: { x: number; y: number };
  onClose: () => void;
};

export const RolesContextMenu = ({
  page,
  access,
  isPage,
  position,
  onClose,
}: RolesContextMenuProps) => {
  const menuRef = useRef<HTMLDivElement>(null);
  const queryClient = useQueryClient();
  const { getProfile } = useFetchProfile();
  const showToast = useToast();

  const { data: rolesData, refetch: refetchRoles } = useApiRequest({
    api: "/auth/api/v1/role/",
    method: "get",
    params: { page: 1, page_size: 1000 },
    queryKey: ["roles-permissions"],
  });

  const { data: permissionsData } = useApiRequest({
    api: "/auth/api/v1/permission/",
    method: "get",
    params: { page: 1, page_size: 1000 },
    queryKey: ["all-permissions"],
  });

  const findPermissionId = (page: string, access: string): number | null => {
    if (!permissionsData?.results) return null;
    const permission = permissionsData.results.find(
      (p: any) => p.page === page && p.name === access
    );
    return permission?.id || null;
  };

  const checkRoleHasPermission = (
    role: any,
    page: string,
    access: string
  ): boolean => {
    if (!role?.permissions || !Array.isArray(role.permissions)) {
      return false;
    }
    if (!permissionsData?.results) return false;

    const permissionId = findPermissionId(page, access);
    if (!permissionId) return false;

    const rolePermissionIds = role.permissions.map((p: any) => p.id || p);
    return rolePermissionIds.includes(permissionId);
  };

  const [selectedRoleIds, setSelectedRoleIds] = useState<Set<number>>(
    new Set()
  );
  const [submitting, setSubmitting] = useState(false);

  useEffect(() => {
    if (!rolesData?.results) return;
    const next = new Set<number>();
    rolesData.results.forEach((role: any) => {
      if (checkRoleHasPermission(role, page, access)) {
        next.add(role.id);
      }
    });
    setSelectedRoleIds(next);
  }, [rolesData?.results, permissionsData?.results, page, access]);

  const handleToggleLocal = (roleId: number) => {
    setSelectedRoleIds((prev) => {
      const next = new Set(prev);
      if (next.has(roleId)) {
        next.delete(roleId);
      } else {
        next.add(roleId);
      }
      return next;
    });
  };

  const handleSubmit = async () => {
    try {
      const permissionId = findPermissionId(page, access);
      if (!permissionId) {
        showToast("دسترسی یافت نشد", "error");
        return;
      }
      if (!rolesData?.results) return;
      setSubmitting(true);
      const updates = rolesData.results.flatMap((role: any) => {
        const currentPermissionIds = (role.permissions || []).map(
          (p: any) => p.id || p
        );
        const currentlyHas = currentPermissionIds.includes(permissionId);
        const shouldHave = selectedRoleIds.has(role.id);
        if (currentlyHas === shouldHave) return [];
        const updatedPermissionIds = shouldHave
          ? currentPermissionIds.includes(permissionId)
            ? currentPermissionIds
            : [...currentPermissionIds, permissionId]
          : currentPermissionIds.filter((id: number) => id !== permissionId);
        return [
          api.put(`/auth/api/v1/role/${role.id}/`, {
            role_name: role.role_name,
            description: role.description,
            type: role.type?.id,
            permissions: updatedPermissionIds,
            ...(role.parent_role?.id
              ? { parent_role: role.parent_role.id }
              : {}),
          }),
        ];
      });
      if (updates.length === 0) {
        showToast("تغییری برای ارسال وجود ندارد", "info");
        return;
      }
      await Promise.all(updates);
      showToast("به‌روزرسانی نقش‌ها با موفقیت انجام شد", "success");
      queryClient.invalidateQueries({ queryKey: ["roles"] });
      queryClient.invalidateQueries({ queryKey: ["roles-permissions"] });
      refetchRoles();
      getProfile();
      onClose();
    } catch (error: any) {
      showToast(
        error?.response?.data?.message || "خطا در به‌روزرسانی نقش‌ها",
        "error"
      );
    } finally {
      setSubmitting(false);
    }
  };

  useEffect(() => {
    const handleClickOutside = (e: MouseEvent) => {
      if (menuRef.current && !menuRef.current.contains(e.target as Node)) {
        onClose();
      }
    };

    const handleEscape = (e: KeyboardEvent) => {
      if (e.key === "Escape") {
        onClose();
      }
    };

    document.addEventListener("mousedown", handleClickOutside);
    document.addEventListener("keydown", handleEscape);

    return () => {
      document.removeEventListener("mousedown", handleClickOutside);
      document.removeEventListener("keydown", handleEscape);
    };
  }, [onClose]);

  useEffect(() => {
    const menu = menuRef.current;
    if (!menu) return;

    setTimeout(() => {
      const rect = menu.getBoundingClientRect();
      const viewportWidth = window.innerWidth;
      const viewportHeight = window.innerHeight;
      let adjustedX = position.x;
      let adjustedY = position.y;

      if (adjustedX + rect.width > viewportWidth) {
        adjustedX = viewportWidth - rect.width - 10;
      }
      if (adjustedY + rect.height > viewportHeight) {
        adjustedY = viewportHeight - rect.height - 10;
      }

      if (adjustedX < 10) adjustedX = 10;
      if (adjustedY < 10) adjustedY = 10;

      menu.style.left = `${adjustedX}px`;
      menu.style.top = `${adjustedY}px`;
    }, 0);
  }, [position]);

  const rolesWithPermission =
    rolesData?.results?.filter((role: any) => selectedRoleIds.has(role.id)) ||
    [];

  return createPortal(
    <AnimatePresence>
      <motion.div
        ref={menuRef}
        initial={{ opacity: 0, scale: 0.95 }}
        animate={{ opacity: 1, scale: 1 }}
        exit={{ opacity: 0, scale: 0.95 }}
        transition={{ duration: 0.15 }}
        className="fixed z-[10000] bg-white dark:bg-dark-700 rounded-lg shadow-xl ring-1 ring-black/10 dark:ring-white/10 min-w-[300px] max-w-[400px] max-h-[500px] overflow-hidden flex flex-col"
        style={{
          left: `${position.x}px`,
          top: `${position.y}px`,
        }}
        onClick={(e) => e.stopPropagation()}
      >
        {isPage && (
          <div className="p-3 border-b border-gray-200/60 dark:border-gray-700/40">
            <Typography
              variant="subtitle2"
              className="text-gray-700 dark:text-gray-300 font-medium text-sm mb-1"
            >
              نمایش صفحه
            </Typography>
          </div>
        )}
        <div className="p-3 border-b border-gray-200/60 dark:border-gray-700/40">
          <Typography
            variant="subtitle2"
            className="text-gray-700 dark:text-gray-300 font-medium text-sm mb-1"
          >
            نام صفحه: {page} ({getFaPermissions(page)})
          </Typography>
          <Typography
            variant="caption"
            className="text-xs text-gray-500 dark:text-gray-400"
          >
            دسترسی: {access}
          </Typography>
          <Typography
            variant="caption"
            className="text-xs text-primary-600 dark:text-primary-400 mt-1 block"
          >
            {rolesWithPermission.length} / {rolesData?.results?.length || 0} نقش
          </Typography>
        </div>
        <div className="flex-1 overflow-y-auto p-2 modern-scrollbar">
          {!rolesData?.results ? (
            <div className="text-center py-4 text-gray-500 dark:text-gray-400">
              <Typography variant="caption" className="text-xs">
                در حال بارگذاری...
              </Typography>
            </div>
          ) : rolesData.results.length > 0 ? (
            <div className="space-y-1">
              {rolesData.results.map((role: any) => {
                const hasPermission = selectedRoleIds.has(role.id);
                return (
                  <div
                    key={role.id}
                    className="flex items-center gap-2 px-2 py-1.5 rounded-md bg-gray-50/50 dark:bg-dark-600/30 border border-gray-200/50 dark:border-gray-700/50 hover:bg-gray-100/60 dark:hover:bg-dark-600/50 transition-colors"
                  >
                    <Checkbox
                      checked={hasPermission}
                      disabled={submitting}
                      onChange={(e) => {
                        e.stopPropagation();
                        handleToggleLocal(role.id);
                      }}
                      size="small"
                    />
                    <Typography
                      variant="caption"
                      className="text-xs text-gray-700 dark:text-gray-300 flex-1"
                    >
                      {role.role_name}
                    </Typography>
                    {role.type?.name && (
                      <Typography
                        variant="caption"
                        className="text-xs text-gray-500 dark:text-gray-400"
                      >
                        ({role.type.name})
                      </Typography>
                    )}
                  </div>
                );
              })}
            </div>
          ) : (
            <div className="text-center py-4 text-gray-500 dark:text-gray-400">
              <Typography variant="caption" className="text-xs">
                نقشی یافت نشد
              </Typography>
            </div>
          )}
        </div>
        <div className="flex items-center justify-between gap-2 p-3 border-t border-gray-200/60 dark:border-gray-700/40">
          <button
            className="px-3 py-1.5 text-xs rounded-md bg-gray-100 dark:bg-dark-600 text-gray-700 dark:text-gray-200 hover:bg-gray-200/80 dark:hover:bg-dark-500"
            onClick={onClose}
            disabled={submitting}
          >
            انصراف
          </button>
          <button
            className="px-3 py-1.5 text-xs rounded-md bg-primary-600 text-white hover:bg-primary-700 disabled:opacity-60"
            onClick={handleSubmit}
            disabled={submitting}
          >
            {submitting ? "در حال ارسال..." : "ثبت تغییرات"}
          </button>
        </div>
      </motion.div>
    </AnimatePresence>,
    document.body
  );
};
