import * as tailwindColors from 'tailwindcss/colors';
import type { CSSProperties, ElementType, ReactNode } from 'react';

type ChipVariant = 'solid' | 'outlined';

type ChipProps<T extends ElementType> = {
    variant?: ChipVariant;
    // Tailwind color token, e.g. "cyan-700", "indigo-500", "rose-600".
    tone?: string;
    as?: T;
    className?: string;
    children: ReactNode;
};

const variantClassMap: Record<ChipVariant, string> = {
    solid: 'chip-solid',
    outlined: 'chip-outlined',
};

type TailwindPalette = Record<string, string>;

function resolveTailwindToneColor(tone: string | undefined): string | null {
    const normalizedTone = tone?.trim().toLowerCase();
    if (normalizedTone == null || normalizedTone === '') {
        return null;
    }

    const colorSource = tailwindColors as unknown as Record<string, unknown>;
    const lastDashIndex = normalizedTone.lastIndexOf('-');

    if (lastDashIndex === -1) {
        const direct = colorSource[normalizedTone];
        return typeof direct === 'string' ? direct : null;
    }

    const colorName = normalizedTone.slice(0, lastDashIndex);
    const shade = normalizedTone.slice(lastDashIndex + 1);
    const palette = colorSource[colorName];

    if (palette == null || typeof palette !== 'object') {
        return null;
    }

    const shadeColor = (palette as TailwindPalette)[shade];
    return typeof shadeColor === 'string' ? shadeColor : null;
}

export function Chip<T extends ElementType = 'span'>({
    variant = 'solid',
    tone,
    as,
    className = '',
    children,
}: Readonly<ChipProps<T>>) {
    const Component = as ?? ('span' as ElementType);
    const toneColor = resolveTailwindToneColor(tone);
    const toneStyle: CSSProperties | undefined =
        toneColor == null
            ? undefined
            : variant === 'solid'
              ? { borderColor: toneColor, backgroundColor: toneColor, color: '#ffffff' }
              : { borderColor: toneColor, color: toneColor };
    const classes = `chip-root ${variantClassMap[variant]} ${className}`.trim();

    return (
        <Component className={classes} style={toneStyle}>
            {children}
        </Component>
    );
}
