'use client';

import clsx from 'clsx';
import React from 'react';
import { twMerge } from 'tailwind-merge';

import { PolymorphicComponent } from '@/utils/polymorphic';

export enum TagVariant {
  Standard = 'standard',
  Inherit = 'inherit',
  Gradient = 'gradient',
  New = 'new',
  Auk = 'auk',
  Beta = 'beta',
  Pro = 'pro',
  Studio = 'studio',
}

export enum TagShape {
  Tag = 'tag',
  Badge = 'badge',
}

export type TagProps = {
  variant?: TagVariant;
  shape?: TagShape;
  className?: string;
  children?: React.ReactNode;
  style?: React.CSSProperties;
};

/**
 * Constructs a custom color variant for a `Tag`
 */
export function tagColorCssVariables(options: {
  background?: string;
  foreground?: string;
  border?: string;
}) {
  return {
    '--background-tag': options.background ?? 'transparent',
    '--foreground-tag': options.foreground ?? 'currentColor',
    '--border-tag': options.border ?? 'currentColor',
  } as React.CSSProperties;
}

/**
 * Generic text tag component that can be used for marking info on songs and
 * highlighting new features in general.
 *
 * For consistency, we generally recommend using a preset `TagVariant` to set
 * a standard color scheme, but for instances where we need a custom color,
 * pass a custom `style` using the `tagCssVariables` utility.
 */
const Tag: PolymorphicComponent<TagProps> = (props) => {
  const {
    as: Component = 'span',
    className,
    children,
    variant = TagVariant.Standard,
    shape = TagShape.Tag,
    ...restProps
  } = props;

  return (
    <Component
      className={twMerge(
        clsx(
          'relative inline-flex flex-row items-center justify-center align-text-top',
          'gap-0.5 rounded px-1 py-0',
          'font-sans text-xs font-medium text-nowrap',
          'text-foreground-primary',
          'border-(--border-tag,currentColor) bg-(--background-tag,transparent) text-(--foreground-tag,currentColor)',
          'before:pointer-events-none before:absolute before:inset-0 before:rounded-[inherit] before:border before:border-inherit',
          {
            /**
             * Variant controls the color scheme
             */
            'border-border-secondary bg-background-secondary text-foreground-primary':
              variant === TagVariant.Standard,
            'bg-transparent bg-gradient-to-r from-(--foreground-tag,var(--color-foreground-primary)) to-(--background-tag,var(--color-foreground-primary)) bg-clip-text text-transparent':
              variant === TagVariant.Gradient || variant === TagVariant.Studio,
            'before:border-0 before:bg-inherit before:bg-[image:inherit] before:mask-border':
              variant === TagVariant.Gradient || variant === TagVariant.Studio,
            'text-accent-pink-on-primary': variant === TagVariant.Auk,
            'border-transparent bg-accent-pink text-accent-pink-contrast':
              variant === TagVariant.New,
            'border-transparent bg-foreground-inactive text-foreground-primary':
              variant === TagVariant.Beta,
            'border-transparent bg-background-secondary text-foreground-primary':
              variant === TagVariant.Pro,
            '[--background-tag:var(--color-accent-pink-on-primary)] [--foreground-tag:var(--color-accent-red-on-primary)]':
              variant === TagVariant.Studio,
            /**
             * Shape controls the border radius and padding
             */
            'rounded-[0.5em]': shape === TagShape.Tag,
            'rounded-full': shape === TagShape.Badge,
          }
        ),
        className
      )}
      {...restProps}
    >
      {children}
    </Component>
  );
};

export default Tag;
