/**
 * Icon — 矢量图标（非人像）
 *
 * **何时用**：按钮/输入前后缀、导航项、状态提示、空状态插画中的符号；默认继承父级文字色（`currentColor`）。
 * **不用**：账号/用户/机器人「脸」→ `Avatar`；需要整段可点击文案 → `Button`；切换同页多块主内容 → `Tabs`。
 *
 * @prop {string} [name='check-stroked'] — 图标名称（kebab-case，见图标库）
 * @prop {'xs'|'sm'|'md'|'lg'|'xl'|number} [size='sm'] — 尺寸档位：与 **Input/Select md（36px）** 搭配的前缀、行内符号默认 **sm（16px）**；独立展示用 md/lg/xl；也可传数字像素（少用）
 * @prop {string} [color='currentColor'] — 仅在需脱离父级文字色时覆盖
 */

import { useId } from 'react';
import { ICON_MAP } from './icons/icon-data';

/* ── 尺寸映射 ── */
const SIZE_MAP = {
  xs: 12,
  sm: 16,
  md: 20,
  lg: 24,
  xl: 32,
};

function normalizeIconEntry(entry) {
  if (Array.isArray(entry)) {
    return {
      viewBox: '0 0 24 24',
      defs: [],
      shapes: entry,
      contentTransform: '',
    };
  }

  return {
    viewBox: entry?.viewBox || '0 0 24 24',
    defs: entry?.defs || [],
    shapes: entry?.shapes || [],
    contentTransform: entry?.contentTransform || '',
  };
}

function remapPaintRef(value, idMap) {
  if (!value || !idMap) return value;
  return value.replace(/url\(#([^)]+)\)/g, (_, id) => `url(#${idMap[id] || id})`);
}

export default function Icon({
  name,
  size = 'sm',
  color = 'currentColor',
  className,
  style,
  ...rest
}) {
  const entry = ICON_MAP[name];
  if (!entry) return null;

  const px = SIZE_MAP[size] ?? (typeof size === 'number' ? size : 24);
  const iconId = useId().replace(/:/g, '');
  const { viewBox, defs, shapes, contentTransform } = normalizeIconEntry(entry);
  const defIdMap = Object.fromEntries(defs.map((def) => [def.id, `${iconId}-${def.id}`]));
  const imageClipDefs = shapes
    .map((shape, index) => ({ shape, index }))
    .filter(({ shape }) => shape.type === 'image' && shape.clipRadius !== undefined);
  const isAnimated = typeof name === 'string' && name.endsWith('-animated');

  return (
    <svg
      xmlns="http://www.w3.org/2000/svg"
      width={px}
      height={px}
      viewBox={viewBox}
      preserveAspectRatio="xMidYMid meet"
      fill="none"
      className={[`tfds-icon`, isAnimated ? 'tfds-icon-spin' : '', className].filter(Boolean).join(' ')}
      style={{ flexShrink: 0, overflow: 'visible', ...style }}
      {...rest}
     data-tfds-component="Icon">
      {defs.length || imageClipDefs.length ? (
        <defs>
          {defs.map((def) => {
            if (def.type === 'linearGradient') {
              return (
                <linearGradient
                  key={def.id}
                  id={defIdMap[def.id]}
                  x1={def.x1}
                  y1={def.y1}
                  x2={def.x2}
                  y2={def.y2}
                  gradientUnits={def.gradientUnits}
                >
                  {def.stops.map((stop, index) => (
                    <stop
                      key={index}
                      offset={stop.offset}
                      stopColor={stop.stopColor}
                      stopOpacity={stop.stopOpacity}
                    />
                  ))}
                </linearGradient>
              );
            }

            if (def.type === 'radialGradient') {
              return (
                <radialGradient
                  key={def.id}
                  id={defIdMap[def.id]}
                  cx={def.cx}
                  cy={def.cy}
                  r={def.r}
                  gradientUnits={def.gradientUnits}
                  gradientTransform={def.gradientTransform}
                >
                  {def.stops.map((stop, index) => (
                    <stop
                      key={index}
                      offset={stop.offset}
                      stopColor={stop.stopColor}
                      stopOpacity={stop.stopOpacity}
                    />
                  ))}
                </radialGradient>
              );
            }

            return null;
          })}
          {imageClipDefs.map(({ shape, index }) => (
            <clipPath key={`clip-${index}`} id={`${iconId}-image-clip-${index}`}>
              <rect
                x={shape.x || 0}
                y={shape.y || 0}
                width={shape.width}
                height={shape.height}
                rx={shape.clipRadius}
                ry={shape.clipRadius}
              />
            </clipPath>
          ))}
        </defs>
      ) : null}

      <g transform={contentTransform || undefined}>
        {shapes.map((shape, index) => {
          const fill = remapPaintRef(shape.fill, defIdMap) || color;
          const stroke = remapPaintRef(shape.strokeColor, defIdMap) || color;
          const transform = shape.transform || undefined;

          if (shape.type === 'ellipse') {
            return (
              <ellipse
                key={index}
                cx={shape.cx}
                cy={shape.cy}
                rx={shape.rx}
                ry={shape.ry}
                fill={fill}
                fillOpacity={shape.fillOpacity}
                transform={transform}
              />
            );
          }

          if (shape.type === 'rect') {
            return (
              <rect
                key={index}
                x={shape.x}
                y={shape.y}
                width={shape.width}
                height={shape.height}
                rx={shape.rx}
                ry={shape.ry}
                fill={shape.fill === 'none' ? 'none' : fill}
                fillOpacity={shape.fillOpacity}
                stroke={shape.stroke ? stroke : undefined}
                strokeWidth={shape.stroke ? (shape.strokeWidth || '2') : undefined}
                strokeOpacity={shape.strokeOpacity}
                strokeDasharray={shape.strokeDasharray}
                strokeDashoffset={shape.strokeDashoffset}
                transform={transform}
              />
            );
          }

          if (shape.type === 'image') {
            return (
              <image
                key={index}
                href={shape.href}
                x={shape.x || 0}
                y={shape.y || 0}
                width={shape.width}
                height={shape.height}
                preserveAspectRatio={shape.preserveAspectRatio || 'xMidYMid meet'}
                clipPath={shape.clipRadius !== undefined ? `url(#${iconId}-image-clip-${index})` : undefined}
                opacity={shape.opacity}
                transform={transform}
              />
            );
          }

          if (shape.stroke) {
            return (
              <path
                key={index}
                d={shape.d}
                fill="none"
                stroke={stroke}
                strokeWidth={shape.strokeWidth || '2'}
                strokeLinecap={shape.strokeLinecap || 'round'}
                strokeLinejoin={shape.strokeLinejoin || 'round'}
                strokeOpacity={shape.strokeOpacity}
                strokeDasharray={shape.strokeDasharray}
                strokeDashoffset={shape.strokeDashoffset}
                transform={transform}
              />
            );
          }

          return (
            <path
              key={index}
              d={shape.d}
              fill={fill}
              fillOpacity={shape.fillOpacity}
              fillRule={shape.fillRule || undefined}
              clipRule={shape.clipRule || undefined}
              transform={transform}
            />
          );
        })}
      </g>
    </svg>
  );
}
