import { MATCH3D_VISUAL_SEEDS } from '../../services/match3d-runtime';

type Match3DVisualSeed = (typeof MATCH3D_VISUAL_SEEDS)[number];

export type Match3DBlockShape =
  | 'brick'
  | 'tile'
  | 'slope'
  | 'cylinder'
  | 'ring'
  | 'arch'
  | 'cone';

export type Match3DGeometryShape = Match3DBlockShape;

export type Match3DGeometryAsset = {
  shape: Match3DBlockShape;
  fill: string;
  stroke: string;
  studsX: number;
  studsY: number;
  heightScale: number;
  transparent?: boolean;
};

const MATCH3D_GEOMETRY_ASSETS: Record<string, Match3DGeometryAsset> = {
  'block-red-2x4': blockAsset('brick', '#e31818', '#8f1111', 4, 2, 0.72),
  'block-blue-1x2': blockAsset('brick', '#1478d4', '#0b4f91', 2, 1, 0.82),
  'block-yellow-2x2': blockAsset('brick', '#f7c51d', '#a66f00', 2, 2, 0.76),
  'block-green-1x4': blockAsset('brick', '#079447', '#055c2f', 4, 1, 0.72),
  'block-orange-1x6': blockAsset('brick', '#ff7a12', '#b84708', 6, 1, 0.64),
  'block-white-1x1': blockAsset('brick', '#f3f2ec', '#b7b8b2', 1, 1, 0.86),
  'block-black-1x8': blockAsset('brick', '#101214', '#030405', 8, 1, 0.54),
  'block-tan-2x3': blockAsset('brick', '#d8bd72', '#9b7a35', 3, 2, 0.68),
  'block-lime-1x2': blockAsset('brick', '#a5df18', '#6d990b', 2, 1, 0.58),
  'block-darkred-2x2': blockAsset('brick', '#b51217', '#76090d', 2, 2, 0.7),
  'block-blue-1x4': blockAsset('brick', '#1688df', '#0b5c9e', 4, 1, 0.58),
  'block-pink-2x4': blockAsset('brick', '#f66bb5', '#ba2e7e', 4, 2, 0.56),
  'block-gray-1x6': blockAsset('brick', '#4c5456', '#232829', 6, 1, 0.5),
  'block-lavender-tile-2x2': blockAsset('tile', '#c99fe6', '#8b63ad', 2, 2, 0.28),
  'block-teal-tile-1x3': blockAsset('tile', '#11adb0', '#087377', 3, 1, 0.26),
  'block-mint-tile-1x4': blockAsset('tile', '#a7c6ac', '#6e9275', 4, 1, 0.24),
  'block-magenta-tile-2x2': blockAsset('tile', '#cf0f68', '#8e0644', 2, 2, 0.28),
  'block-orange-tile-2x2-stud': blockAsset('tile', '#ff970f', '#b65b05', 2, 2, 0.3),
  'block-purple-slope-1x2': blockAsset('slope', '#5e42b6', '#342070', 2, 1, 0.82),
  'block-brown-slope-1x2': blockAsset('slope', '#8b421f', '#552414', 2, 1, 0.94),
  'block-sky-slope-2x2': blockAsset('slope', '#4db3f2', '#1f78b7', 2, 2, 0.9),
  'block-green-cylinder': blockAsset('cylinder', '#159554', '#076236', 1, 1, 1.08),
  'block-clear-ring': {
    ...blockAsset('ring', '#d9e1df', '#aebbbb', 2, 2, 0.38),
    transparent: true,
  },
  'block-mint-arch': blockAsset('arch', '#c4ded2', '#83a996', 4, 1, 1.0),
  'block-gold-cone': blockAsset('cone', '#d39a10', '#8c6105', 1, 1, 1.18),
};

const MATCH3D_UNKNOWN_GEOMETRY_ASSETS: Match3DGeometryAsset[] = [
  blockAsset('brick', '#e11d48', '#9f1239', 2, 2, 0.68),
  blockAsset('tile', '#f59e0b', '#92400e', 3, 1, 0.28),
  blockAsset('slope', '#8b5cf6', '#5b21b6', 2, 1, 0.86),
  blockAsset('cylinder', '#10b981', '#065f46', 1, 1, 1.0),
];

const MATCH3D_UNKNOWN_VISUAL_SEEDS: Match3DVisualSeed[] = [
  {
    itemTypeId: 'unknown-rose',
    visualKey: 'unknown-rose',
    colorClassName: 'from-rose-400 to-red-600',
    label: '一',
  },
  {
    itemTypeId: 'unknown-amber',
    visualKey: 'unknown-amber',
    colorClassName: 'from-yellow-300 to-amber-500',
    label: '二',
  },
  {
    itemTypeId: 'unknown-violet',
    visualKey: 'unknown-violet',
    colorClassName: 'from-violet-400 to-purple-700',
    label: '三',
  },
  {
    itemTypeId: 'unknown-emerald',
    visualKey: 'unknown-emerald',
    colorClassName: 'from-emerald-300 to-green-600',
    label: '四',
  },
];

function blockAsset(
  shape: Match3DBlockShape,
  fill: string,
  stroke: string,
  studsX: number,
  studsY: number,
  heightScale: number,
): Match3DGeometryAsset {
  return {
    shape,
    fill,
    stroke,
    studsX,
    studsY,
    heightScale,
  };
}

export function hashVisualKey(visualKey: string) {
  let hash = 0;
  for (const char of visualKey) {
    hash = (hash * 31 + char.charCodeAt(0)) >>> 0;
  }
  return hash;
}

export function resolveVisualSeed(visualKey: string) {
  const knownSeed = MATCH3D_VISUAL_SEEDS.find(
    (seed) => seed.visualKey === visualKey,
  );
  if (knownSeed) {
    return knownSeed;
  }
  return MATCH3D_UNKNOWN_VISUAL_SEEDS[
    hashVisualKey(visualKey) % MATCH3D_UNKNOWN_VISUAL_SEEDS.length
  ]!;
}

export function resolveGeometryAsset(visualKey: string): Match3DGeometryAsset {
  return (
    MATCH3D_GEOMETRY_ASSETS[visualKey] ??
    MATCH3D_UNKNOWN_GEOMETRY_ASSETS[
      hashVisualKey(visualKey) % MATCH3D_UNKNOWN_GEOMETRY_ASSETS.length
    ]!
  );
}

function renderBlockIcon(asset: Match3DGeometryAsset) {
  const shapeProps = {
    fill: asset.fill,
    stroke: asset.stroke,
    strokeWidth: 5,
    strokeLinejoin: 'round' as const,
    opacity: asset.transparent ? 0.72 : 1,
  };

  if (asset.shape === 'cylinder') {
    return (
      <>
        <rect x="34" y="22" width="32" height="56" rx="12" {...shapeProps} />
        <ellipse cx="50" cy="24" rx="16" ry="8" fill={asset.fill} stroke={asset.stroke} strokeWidth={5} />
      </>
    );
  }

  if (asset.shape === 'ring') {
    return (
      <>
        <ellipse cx="50" cy="50" rx="34" ry="24" {...shapeProps} />
        <ellipse cx="50" cy="50" rx="17" ry="11" fill="rgba(255,255,255,0.88)" stroke={asset.stroke} strokeWidth={5} />
      </>
    );
  }

  if (asset.shape === 'arch') {
    return (
      <path
        d="M14 78 V28 H86 V78 H66 V46 C66 34 58 27 50 27 C42 27 34 34 34 46 V78Z"
        {...shapeProps}
      />
    );
  }

  if (asset.shape === 'cone') {
    return (
      <path d="M50 12 C66 28 78 62 78 82 H22 C22 62 34 28 50 12Z" {...shapeProps} />
    );
  }

  if (asset.shape === 'slope') {
    return <path d="M16 76 L84 76 L84 30 L16 60Z" {...shapeProps} />;
  }

  const width = Math.min(76, 16 + asset.studsX * 14);
  const height = Math.min(54, 18 + asset.studsY * 13);
  const x = 50 - width / 2;
  const y = 54 - height / 2;
  const studRadius = asset.shape === 'tile' ? 0 : 5;
  return (
    <>
      <rect x={x} y={y} width={width} height={height} rx="7" {...shapeProps} />
      {Array.from({ length: asset.studsX * asset.studsY }, (_, index) => {
        if (studRadius <= 0) {
          return null;
        }
        const column = index % asset.studsX;
        const row = Math.floor(index / asset.studsX);
        return (
          <circle
            key={index}
            cx={x + ((column + 0.5) * width) / asset.studsX}
            cy={y + ((row + 0.5) * height) / asset.studsY}
            r={studRadius}
            fill={asset.fill}
            stroke={asset.stroke}
            strokeWidth={3}
          />
        );
      })}
    </>
  );
}

export function Match3DVisualIcon({
  visualKey,
  className = '',
}: {
  visualKey: string;
  className?: string;
}) {
  const asset = resolveGeometryAsset(visualKey);

  return (
    <svg
      className={`pointer-events-none h-full w-full drop-shadow-[0_5px_7px_rgba(15,23,42,0.36)] ${className}`}
      viewBox="0 0 100 100"
      aria-hidden
      focusable={false}
      data-testid={`match3d-visual-${visualKey}`}
      data-shape={asset.shape}
    >
      {renderBlockIcon(asset)}
    </svg>
  );
}
