import { Slot } from "@radix-ui/react-slot";
import type { VariantProps } from "class-variance-authority";
import { cva } from "class-variance-authority";
import { type HTMLMotionProps, motion } from "motion/react";
import { forwardRef, type HTMLAttributes, type ReactNode } from "react";
import { cn } from "@/lib/utils";
import { CardDepthProvider, useCardDepth } from "./card-context";

const cardVariants = cva(
	`flex flex-col gap-2 ring-2 rounded-card
    ring-accent  transition-colors grow justify-start
    `,
	{
		variants: {
			padding: {
				true: "p-card",
				false: "",
			},
			interactive: {
				false: "",
				true: "hover:bg-accent/30 cursor-pointer",
			},
		},
		defaultVariants: {
			interactive: false,
			padding: true,
		},
	},
);

const BASE_RADIUS = 0.625 * 3;
const PADDING = 1.25;
const MIN_RADIUS = 0;

type CommonCardProps = {
	asChild?: boolean;
	className?: string;
	children: ReactNode;
	style?: HTMLAttributes<unknown>["style"];
} & VariantProps<typeof cardVariants>;

const Card = forwardRef<HTMLDivElement, CommonCardProps>(
	({ asChild, className, interactive, padding, style, ...props }, ref) => {
		const depth = useCardDepth();

		const radius = Math.max(BASE_RADIUS - depth * PADDING, MIN_RADIUS); // 4px floor

		const Comp = asChild ? Slot : "div";

		return (
			<CardDepthProvider>
				<Comp
					ref={ref}
					style={{ borderRadius: `${radius}rem`, ...style }}
					className={cn(cardVariants({ interactive, className, padding }))}
					{...props}
				/>
			</CardDepthProvider>
		);
	},
);

Card.displayName = "Card";

const MCard = motion.create(Card);

export const AnimatedCard: React.FC<
	CommonCardProps & HTMLMotionProps<"div">
> = (props) => {
	return (
		<MCard
			variants={{ enter: { scale: 1 }, from: { scale: 0 } }}
			transition={{
				type: "spring",
				stiffness: 200,
				damping: 15,
				mass: 2,
			}}
			{...props}
		/>
	);
};

export default Card;

export { cardVariants };
