import React, { ComponentPropsWithoutRef, ElementRef, forwardRef } from "react"
import { tv, VariantProps } from "tailwind-variants"
import { classNames } from "../../utils/classNames"

const gradientMaskVariants = tv({
  base: "will-change-[mask-size,mask-position] [mask-position:0px] [mask-size:100%]",
  variants: {
    variant: {
      container: classNames(
        "[mask-image:linear-gradient(to_right,transparent,black_theme(spacing.4),black_calc(100%_-_theme(spacing.4)),transparent)]",
        "lg:[mask-image:linear-gradient(to_right,transparent,black_theme(spacing.4),black_calc(100%_-_theme(spacing.6)),transparent)]",
      ),
    },
    side: {
      both: "",
      left: "",
      right: "",
      none: "",
    },
  },
  defaultVariants: {
    variant: "container",
  },
  compoundVariants: [
    {
      variant: "container",
      side: ["left", "right"],
      className: classNames(
        "[mask-size:calc(100%+theme(spacing.4))]",
        "lg:[mask-size:calc(100%+theme(spacing.6))]",
      ),
    },
    {
      variant: "container",
      side: ["none", "right"],
      className: classNames(
        "[mask-position:calc(theme(spacing.4)*-1)]",
        "lg:[mask-position:calc(theme(spacing.6)*-1)]",
      ),
    },
    {
      variant: "container",
      side: "none",
      className: classNames(
        // Size
        "[mask-size:calc(100%+(theme(spacing.4)*2))]",
        "lg:[mask-size:calc(100%+(theme(spacing.6)*2))]",
      ),
    },
  ],
})

export type GradientMaskProps = {
  children: React.ReactNode
  className?: string
} & ComponentPropsWithoutRef<"div"> &
  VariantProps<typeof gradientMaskVariants>

export const GradientMask = forwardRef<ElementRef<"div">, GradientMaskProps>(
  function GradientMask(
    { children, className, variant = "container", side = "both", ...rest },
    ref,
  ) {
    return (
      <div
        className={classNames(
          gradientMaskVariants({ variant, side }),
          className,
        )}
        {...rest}
        ref={ref}
      >
        {children}
      </div>
    )
  },
)
