import React, {FC, PropsWithChildren} from "react";
import {colors} from "./Colors";
import {useHover} from "./hooks";
import {ColorOption, ColorOptionWithCustomTint, ColorWithCustomTint, CurrentColor, request} from "./Color";
import classNames from "classnames";
import {motion} from "motion/react";

export type CardProps = ColorOptionWithCustomTint & {
    id?: string,
    highlight?: boolean,
    blur?: boolean,
    onHoverStart?: () => void,
    onHoverEnd?: () => void,
    bottomButton?: {
        icon: React.ReactNode,
        text: string,
        onClick: () => void
    },
    afterContent?: React.ReactNode | ((isHovered: boolean) => React.ReactNode),
    beforeCardInsideContent?: React.ReactNode,
    beforeCardInsideContentHorizontal?: boolean, // default is false
    outsideContent?: React.ReactNode | ((isHovered: boolean) => React.ReactNode),
    innerRing?: boolean,
    outerRing?: boolean,
    outerRingWidth?: string,
    outerRingColor?: {
        default: ColorWithCustomTint,
        highlight?: ColorWithCustomTint,
    },
    roundness?: string,
    outerRingRoundness?: string,
    enableSelfHovering?: boolean,
    explicitWidth?: boolean,
    fullWidth?: boolean,
    scaleOnHover?: boolean,
    animateLayout?: boolean,
}

export const Card: FC<CardProps & PropsWithChildren> = ({
                                                            id,
                                                            highlight,
                                                            children,
                                                            blur,
                                                            onHoverStart,
                                                            onHoverEnd,
                                                            bottomButton,
                                                            afterContent,
                                                            outsideContent,
                                                            beforeCardInsideContent,
                                                            beforeCardInsideContentHorizontal,
                                                            color,
                                                            innerRing = true,
                                                            outerRing,
                                                            outerRingWidth,
                                                            outerRingColor,
                                                            roundness,
                                                            outerRingRoundness,
                                                            enableSelfHovering = false,
                                                          explicitWidth = false,
                                                          fullWidth = false,
                                                          scaleOnHover = true,
                                                          animateLayout = true,
                                                          }) => {
    const resizeTransition = React.useMemo(() => ({
        type: "spring" as const,
        stiffness: 500,
        damping: 38,
        mass: 0.42,
    }), [])

    const hoverRef = useHover<HTMLDivElement>({
        onMouseEnter: () => {
            if (enableSelfHovering) {
                setIsHovered(true)
            }
            onHoverStart?.()
        },
        onMouseLeave: () => {
            if (enableSelfHovering) {
                setIsHovered(false)
            }
            onHoverEnd?.()
        }
    })

    const [isHovered, setIsHovered] = React.useState(false)

    return <motion.div layout={animateLayout} transition={animateLayout ? resizeTransition : undefined} className={classNames('flex flex-col', {
                    'items-start': !fullWidth,
                })}
                style={{width: explicitWidth ? hoverRef.current?.offsetWidth : undefined}}>
        <div className={classNames({
            'flex items-center': beforeCardInsideContentHorizontal
        })}>
            {beforeCardInsideContent}
            <div id={id} ref={hoverRef} className={classNames(`relative  p-px transition-all duration-300`, {
                'scale-100 hover:scale-[1.03] active:scale-[.98]': scaleOnHover,
                'rounded-[24px]': !outerRingRoundness,
                [outerRingRoundness || 'default-outerRingRoundness']: outerRingRoundness,
                'border-[3px]': outerRing && !outerRingWidth,
                [outerRingWidth || 'default-outer-wing-width']: outerRing && outerRingWidth,
                [request(outerRingColor?.default ?? color).get('border.light.secondary')]: !highlight,
                [request(color).get('border.light.primary')]: highlight,
                'opacity-20': blur,
            })}
            >
                <div
                    className="absolute top-1/2 -left-1 --translate-x-[-50%] translate-y-[-50%] --bg-gray-300 w-full h-full ----p-3 ----pr-7 box-content"></div>
                <motion.div layout={animateLayout} transition={animateLayout ? resizeTransition : undefined} className={classNames(`relative overflow-hidden border-2 transition duration-300`, {
                    'border-none': !innerRing,
                    [request(color, 'card-border-inner').get('border.light.primary')]: !highlight,
                    [request(color).border(70)]: highlight,
                    'rounded-[20px]': !roundness,
                    [roundness ?? 'default-roundness']: roundness,
                })}>
                    {children}
                    {bottomButton && <button
                        className={`flex items-center justify-center space-x-1 w-full h-[14px] ${request(color).get('text.dark.secondary')} transition-all ${request(color).get('background.light')} group`}
                        onClick={bottomButton.onClick}>
                        {bottomButton.icon}
                        <span
                            className="hidden group-hover:flex text-smaller-2 leading-px font-medium">{bottomButton.text}</span>
                    </button>}
                </motion.div>
                {typeof afterContent === 'function' ? afterContent(isHovered) : afterContent}
            </div>
        </div>
        {typeof outsideContent === 'function' ? outsideContent(isHovered) : outsideContent}
    </motion.div>
}
