import { forwardRef, useMemo } from 'react'

import type { VariantProps } from '@payfit/unity-themes'
import type { ImgHTMLAttributes } from 'react'

import type { UnityIllustrationAsset } from '../../generated/illustrationAssets'

import { uyTv } from '@payfit/unity-themes'

export const illustratedPicture = uyTv({
  base: 'uy:object-contain uy:aspect-auto',
})

export const illustratedIcon = uyTv({
  base: 'uy:object-contain uy:aspect-square',
  variants: {
    size: {
      sm: 'uy:size-7',
      md: 'uy:size-9',
      lg: 'uy:size-12',
    },
  },
})

interface IllustrationPropsCore
  extends Omit<
    ImgHTMLAttributes<HTMLImageElement>,
    'src' | 'children' | 'alt'
  > {
  /**
   * The illustration asset to render. Must be imported from @payfit/unity-illustrations
   */
  src: UnityIllustrationAsset
}

interface NonDecorativeIllustrationProps extends IllustrationPropsCore {
  /** Whether this is decorative (hidden from screen readers) */
  isDecorative?: false | undefined
  /** Accessible name for the illustration - required when not decorative */
  alt: string
  /** Optional description for complex illustrations */
  description?: string
}

interface DecorativeIllustrationProps extends IllustrationPropsCore {
  /** Whether this is decorative (hidden from screen readers) */
  isDecorative: true
  /** Accessible name for the illustration - optional when decorative */
  alt?: string
}

export type IllustrationPropsBase =
  | NonDecorativeIllustrationProps
  | DecorativeIllustrationProps

export type IllustratedPictureProps = IllustrationPropsBase &
  VariantProps<typeof illustratedPicture> & {
    /**
     * The illustration variant. It can be a regular picture or an illustrated icon
     */
    variant: 'picture'
  }

export type IllustratedIconProps = IllustrationPropsBase &
  VariantProps<typeof illustratedIcon> & {
    /**
     * The illustration variant. It can be a regular picture or an illustrated icon
     */
    variant: 'icon'
    /**
     * The size of the illustration. It only applies to illustrated icons
     */
    size: VariantProps<typeof illustratedIcon>['size']
  }

export type IllustrationProps = IllustratedPictureProps | IllustratedIconProps

/**
 * Renders illustrations from the Unity design system with consistent styling and accessibility features.
 *
 * The Illustration component provides a standardized way to display SVG illustrations and images
 * , ensuring consistent sizing, responsive behavior, and accessibility compliance.
 * @param {IllustrationProps} props - Component props including variant, src, size, and standard HTML attributes
 * @see {@link IllustrationProps} for all available props
 * @example
 * ```tsx
 * import { Illustration } from '@payfit/unity-illustrations'
 * import FAQ from '@payfit/unity-illustrations/FAQ'
 *
 * function Example() {
 *   return (
 *     <Illustration
 *       variant="picture"
 *       src={FAQ}
 *       className="uy:size-[150px]"
 *       alt="FAQ illustration"
 *     />
 *   )
 * }
 * ```
 * @remarks
 * You must import illustration assets individually from `@payfit/unity-illustrations/[AssetName]` to use with this component.
 * See the [usage documentation](https://unity-illustrations.payfit.io/?path=/docs/introduction-usage--docs) for complete examples and best practices.
 */
export const Illustration = forwardRef<HTMLImageElement, IllustrationProps>(
  (
    {
      src,
      alt,
      isDecorative: decorative = false,
      variant,
      className,
      style,
      ...props
    },
    ref,
  ) => {
    const clsx =
      variant === 'picture'
        ? illustratedPicture({ className })
        : illustratedIcon({
            className,
            size: (props as IllustratedIconProps).size,
          })

    const description = decorative
      ? (props as NonDecorativeIllustrationProps).description
      : undefined

    // Apply max dimensions for animated assets and generate CSS custom properties
    const { enhancedStyle, enhancedClassName } = useMemo(() => {
      if ('category' in src && 'dimensions' in src) {
        const animationClasses =
          'uy:max-w-[var(--uy-illustration-max-width)] uy:max-h-[var(--uy-illustration-max-height)] uy:w-full uy:h-auto'
        return {
          enhancedStyle: {
            '--uy-illustration-max-width': `${src.dimensions.width}px`,
            '--uy-illustration-max-height': `${src.dimensions.height}px`,
            ...style,
          },
          enhancedClassName: `${clsx} ${animationClasses}`.trim(),
        }
      }
      return {
        enhancedStyle: style,
        enhancedClassName: clsx,
      }
    }, [src, style, clsx])

    return (
      <img
        ref={ref}
        src={src.url}
        alt={decorative ? '' : alt}
        title={decorative ? undefined : alt}
        className={enhancedClassName}
        style={enhancedStyle}
        role={decorative ? 'presentation' : 'img'}
        aria-hidden={decorative}
        aria-description={description}
        loading="lazy"
        {...props}
      />
    )
  },
)

Illustration.displayName = 'Illustration'
