"use client";

import {
  cloneElement,
  isValidElement,
  type ReactElement,
  type ReactNode,
} from "react";
import { usePermissions } from "@/hooks/use-permissions";

type CanProps = {
  module?: string;
  ability?: string;
  permission?: string;
  anyOf?: string[];
  allOf?: string[];
  mode?: "hide" | "disable";
  fallback?: ReactNode;
  children: ReactNode;
};

export function Can({
  module,
  ability = "view",
  permission,
  anyOf,
  allOf,
  mode = "hide",
  fallback = null,
  children,
}: CanProps) {
  const { ready, canKey, canAny, canAll } = usePermissions();

  if (!ready) {
    return <>{fallback}</>;
  }

  let allowed: boolean;
  if (allOf && allOf.length > 0) {
    allowed = canAll(allOf);
  } else if (anyOf && anyOf.length > 0) {
    allowed = canAny(anyOf);
  } else if (permission) {
    allowed = canKey(permission);
  } else if (module) {
    allowed = canKey(`${module}.${ability}`);
  } else {
    allowed = true;
  }

  if (allowed) {
    return <>{children}</>;
  }

  if (mode === "hide") {
    return <>{fallback}</>;
  }

  // disable mode
  if (isValidElement(children)) {
    const child = children as ReactElement<Record<string, unknown>>;
    return cloneElement(child, {
      ...child.props,
      disabled: true,
      "aria-disabled": true,
      className: [child.props.className, "opacity-60 pointer-events-none"]
        .filter(Boolean)
        .join(" "),
    });
  }

  return <span className="opacity-60 pointer-events-none">{children}</span>;
}
