'use client'

import type { CSSProperties, ReactElement, ReactNode } from 'react'
import { useEffect, useRef, useState } from 'react'
import { ny } from '@/lib/utils'

interface NeonColorsProps {
   firstColor: string
   secondColor: string
}

interface NeonGradientCardProps {
   /**
    * @default <div />
    * @type ReactElement
    * @description
    * The component to be rendered as the card
    */
   as?: ReactElement
   /**
    * @default ""
    * @type string
    * @description
    * The className of the card
    */
   className?: string

   /**
    * @default ""
    * @type ReactNode
    * @description
    * The children of the card
    */
   children?: ReactNode

   /**
    * @default 5
    * @type number
    * @description
    * The size of the border in pixels
    */
   borderSize?: number

   /**
    * @default 20
    * @type number
    * @description
    * The size of the radius in pixels
    */
   borderRadius?: number

   /**
    * @default "{ firstColor: '#ff00aa', secondColor: '#00FFF1' }"
    * @type string
    * @description
    * The colors of the neon gradient
    */
   neonColors?: NeonColorsProps

   [key: string]: any
}

const NeonGradientCard: React.FC<NeonGradientCardProps> = ({
   className,
   children,
   borderSize = 2,
   borderRadius = 20,
   neonColors = {
      firstColor: '#ff00aa',
      secondColor: '#00FFF1',
   },
   ...props
}) => {
   const containerRef = useRef<HTMLDivElement>(null)
   const [dimensions, setDimensions] = useState({ width: 0, height: 0 })

   useEffect(() => {
      const updateDimensions = () => {
         if (containerRef.current) {
            const { offsetWidth, offsetHeight } = containerRef.current
            setDimensions({ width: offsetWidth, height: offsetHeight })
         }
      }

      updateDimensions()
      window.addEventListener('resize', updateDimensions)

      return () => {
         window.removeEventListener('resize', updateDimensions)
      }
   }, [])

   useEffect(() => {
      if (containerRef.current) {
         const { offsetWidth, offsetHeight } = containerRef.current
         setDimensions({ width: offsetWidth, height: offsetHeight })
      }
   }, [children])

   return (
      <div
         ref={containerRef}
         style={
            {
               '--border-size': `${borderSize}px`,
               '--border-radius': `${borderRadius}px`,
               '--neon-first-color': neonColors.firstColor,
               '--neon-second-color': neonColors.secondColor,
               '--card-width': `${dimensions.width}px`,
               '--card-height': `${dimensions.height}px`,
               '--card-content-radius': `${borderRadius - borderSize}px`,
               '--pseudo-element-background-image': `linear-gradient(0deg, ${neonColors.firstColor}, ${neonColors.secondColor})`,
               '--pseudo-element-width': `${dimensions.width + borderSize * 2}px`,
               '--pseudo-element-height': `${dimensions.height + borderSize * 2}px`,
               '--after-blur': `${dimensions.width / 3}px`,
            } as CSSProperties
         }
         className={ny(
            'relative z-10 size-full rounded-[var(--border-radius)]',
            className,
         )}
         {...props}
      >
         <div
            className={ny(
               'relative size-full min-h-[inherit] rounded-[var(--card-content-radius)] bg-gray-100 p-6',
               'before:absolute before:-left-[var(--border-size)] before:-top-[var(--border-size)] before:-z-10 before:block',
               'before:h-[var(--pseudo-element-height)] before:w-[var(--pseudo-element-width)] before:rounded-[var(--border-radius)] before:content-[\'\']',
               'before:bg-[linear-gradient(0deg,var(--neon-first-color),var(--neon-second-color))] before:bg-[length:100%_200%]',
               'before:animate-backgroundPositionSpin',
               'after:absolute after:-left-[var(--border-size)] after:-top-[var(--border-size)] after:-z-10 after:block',
               'after:h-[var(--pseudo-element-height)] after:w-[var(--pseudo-element-width)] after:rounded-[var(--border-radius)] after:blur-[var(--after-blur)] after:content-[\'\']',
               'after:bg-[linear-gradient(0deg,var(--neon-first-color),var(--neon-second-color))] after:bg-[length:100%_200%] after:opacity-80',
               'after:animate-backgroundPositionSpin',
               'dark:bg-neutral-900',
            )}
         >
            {children}
         </div>
      </div>
   )
}

export { NeonGradientCard }
