import React, { useState } from 'react';
import cx from 'classnames';
import { HiddenCount } from '../hiddenCount';
import { SuiteBadge, renderBadgeIcon } from '../suiteBadge';
import { getBadgeIconType } from '../tag/tag';
import type { ComponentBaseProps } from '../../types';
import type { TagProps } from '../tag/tag';

const CLASS_NAME = 'TagCloud';

export type TagCloudItem = TagProps & {
    /**
     * Tag label.
     * @deprecated Use `text`
     */
    label?: string;
    /**
     * Icon or graphical element shown to the left of the label.
     * @deprecated Use `iconName`, `flag`, or `brand`.
     */
    icon?: React.ReactNode;
    /**
     * Optional unique key for making react happy when rendering the item in the cloud.
     * Defaults to the label prop.
     */
    key?: string;
};

export interface TagCloudProps<T extends TagCloudItem = TagCloudItem> extends ComponentBaseProps {
    style?: React.CSSProperties;
    disableRemove?: boolean;
    items: T[];
    onRemove?: (tag: T) => void;
    itemWidth?: number | string;
    itemMaxWidth?: number | string;
    maxVisibleCount?: number;
}

/**
 * TagCloud is an expandable container of Tag components.
 *
 * @type molecule
 * @status live
 * @tags utilities
 */
export function TagCloud<T extends TagCloudItem>({
    className,
    style,
    testId = CLASS_NAME,
    disableRemove,
    items = [],
    onRemove,
    maxVisibleCount = 5,
    itemWidth,
    itemMaxWidth,
}: TagCloudProps<T>) {
    const [open, setOpen] = useState(false);

    const visibleTags = open ? items : items.slice(0, maxVisibleCount);
    const hiddenCount = items.length - visibleTags.length;
    const showExpander = items.length > maxVisibleCount;

    const renderIcon = (item: T) => {
        if (item.icon) return item.icon;
        if (item.flag) return renderBadgeIcon('flag', item.flag);
        if (!item.iconName) return;

        const iconType = getBadgeIconType(item.variant ?? 'flag');
        return renderBadgeIcon(iconType, item.iconName);
    };

    return (
        <div className={cx(CLASS_NAME, className)} style={style} data-testid={testId}>
            {visibleTags.map((option) => (
                <SuiteBadge
                    disabled={onRemove && disableRemove}
                    type="tag"
                    width={itemWidth}
                    maxWidth={itemMaxWidth}
                    className={`${CLASS_NAME}-tag`}
                    key={option.key ?? option.label ?? option.text}
                    text={option.label ?? option.text}
                    icon={renderIcon(option)}
                    brand={option.brand}
                    onClose={
                        onRemove
                            ? (e) => {
                                  e.stopPropagation();
                                  onRemove(option);
                              }
                            : undefined
                    }
                    indicator={option.indicator}
                />
            ))}

            {items.length > maxVisibleCount && (
                <HiddenCount
                    doubleChevron
                    expanded={open}
                    hiddenCount={hiddenCount}
                    showExpander={showExpander}
                    onClick={() => setOpen(!open)}
                />
            )}
        </div>
    );
}
