'use client';

import { memo, type CSSProperties, type ReactNode } from 'react';
import type { FdiToothId } from '@/types/treatment';
import type { ToothShapeKind } from '@/components/treatment/fdiToothMeta';
import { getToothPathModel, type ToothPathModel } from '@/components/treatment/toothPathModel';
import {
  getRealisticToothAsset,
  type RealisticToothAsset,
} from '@/components/treatment/realisticToothAssets';

interface ToothGlyphProps {
  fdi: FdiToothId;
  kind: ToothShapeKind;
  gradientId: string;
  selected: boolean;
  upper?: boolean;
  mirrored?: boolean;
  upsideDown?: boolean;
  className?: string;
  style?: CSSProperties;
  /** When set, selected tooth glow + fill use this color instead of primary. */
  accentColor?: string;
  /** Independent crown tint (stacked implant + restoration). */
  crownAccent?: string;
  /** Independent root tint. */
  rootAccent?: string;
}

function hexToRgb(hex: string): { r: number; g: number; b: number } | null {
  const normalized = hex.replace('#', '');
  if (normalized.length !== 6) return null;
  const r = parseInt(normalized.slice(0, 2), 16);
  const g = parseInt(normalized.slice(2, 4), 16);
  const b = parseInt(normalized.slice(4, 6), 16);
  if ([r, g, b].some((n) => Number.isNaN(n))) return null;
  return { r, g, b };
}

function rgbaFromHex(hex: string, alpha: number): string {
  const rgb = hexToRgb(hex);
  if (!rgb) return `rgba(9, 169, 188, ${alpha})`;
  return `rgba(${rgb.r}, ${rgb.g}, ${rgb.b}, ${alpha})`;
}

function mixHex(hex: string, toward: string, amount: number): string {
  const a = hexToRgb(hex);
  const b = hexToRgb(toward);
  if (!a || !b) return hex;
  const t = Math.min(1, Math.max(0, amount));
  const r = Math.round(a.r + (b.r - a.r) * t);
  const g = Math.round(a.g + (b.g - a.g) * t);
  const bl = Math.round(a.b + (b.b - a.b) * t);
  return `#${[r, g, bl].map((n) => n.toString(16).padStart(2, '0')).join('')}`;
}

function filledSilhouette(
  model: Pick<ToothPathModel, 'crown' | 'roots'>,
  crownFill: string,
  rootFill: string,
  stroke: string,
  strokeW: number,
  rootsFirst = false,
): ReactNode {
  const crown = (
    <path d={model.crown} fill={crownFill} stroke={stroke} strokeWidth={strokeW} strokeLinejoin="round" />
  );
  const roots = model.roots.map((d, i) => (
    <path key={i} d={d} fill={rootFill} stroke={stroke} strokeWidth={strokeW} strokeLinejoin="round" />
  ));
  return rootsFirst ? (
    <>
      {roots}
      {crown}
    </>
  ) : (
    <>
      {crown}
      {roots}
    </>
  );
}

function detailOnly(model: ToothPathModel, stroke: string, strokeW: number): ReactNode {
  if (!model.detailStroke) return null;
  const { d, widthScale } = model.detailStroke;
  return <path d={d} fill="none" stroke={stroke} strokeWidth={strokeW * widthScale} strokeLinecap="round" />;
}

function renderClinicalFill(
  model: ToothPathModel,
  selected: boolean,
  gradientId: string,
  accentColor?: string,
): ReactNode {
  const stroke = selected ? (accentColor ?? 'var(--color-primary)') : '#1e293b';
  const strokeW = selected ? 2.4 : 1.35;
  const fill = `url(#${gradientId})`;
  return (
    <>
      {filledSilhouette(model, fill, fill, stroke, strokeW)}
      {detailOnly(model, stroke, strokeW)}
    </>
  );
}

function renderRealisticFill(
  asset: RealisticToothAsset,
  selected: boolean,
  crownGradId: string,
  rootGradId: string,
  accentColor?: string,
): ReactNode {
  const stroke = selected
    ? (accentColor ?? 'var(--color-primary)')
    : 'var(--tooth-stroke)';
  const strokeW = selected ? 1.05 : 0.55;
  return filledSilhouette(
    asset,
    `url(#${crownGradId})`,
    `url(#${rootGradId})`,
    stroke,
    strokeW,
    true,
  );
}

/** FDI chart tooth: clinical gradient + roots only. */
export const ToothGlyph = memo(function ToothGlyph({
  fdi,
  kind,
  gradientId,
  selected,
  upper,
  mirrored,
  upsideDown,
  className = 'w-8 h-[4.85rem]',
  accentColor,
  crownAccent,
  rootAccent,
  style,
}: ToothGlyphProps) {
  const realistic = getRealisticToothAsset(fdi);
  const regionSelected = Boolean(crownAccent || rootAccent);
  const isOn = selected || regionSelected;
  const glow = crownAccent ?? rootAccent ?? accentColor;
  const filter = isOn
    ? glow
      ? `drop-shadow(0 0 6px ${rgbaFromHex(glow, 0.75)})`
      : 'drop-shadow(0 0 6px rgba(9, 169, 188, 0.65))'
    : 'drop-shadow(0 1px 1.5px rgba(15, 23, 42, 0.18))';
  const svgStyle: CSSProperties = { filter, ...style };

  if (realistic) {
    const crownGradId = `${gradientId}-crown`;
    const rootGradId = `${gradientId}-root`;
    const preserveAspectRatio = upper ? 'xMidYMax meet' : 'xMidYMin meet';
    const selectedDefault = selected && !crownAccent && !rootAccent;
    const crownColor = crownAccent ?? (selectedDefault ? accentColor : undefined);
    const rootColor = rootAccent ?? (selectedDefault ? accentColor : undefined);

    const crownStops = crownColor
      ? { hi: '#ffffff', mid: crownColor, shade: mixHex(crownColor, '#0f172a', 0.22) }
      : selectedDefault
        ? { hi: '#ffffff', mid: '#5eead4', shade: '#0e7490' }
        : {
            hi: 'var(--tooth-crown-hi)',
            mid: 'var(--tooth-crown-mid)',
            shade: 'var(--tooth-crown-shade)',
          };

    const rootStops = rootColor
      ? {
          hi: mixHex(rootColor, '#ffffff', 0.2),
          mid: mixHex(rootColor, '#0f172a', 0.12),
          shade: mixHex(rootColor, '#0f172a', 0.32),
        }
      : selectedDefault
        ? { hi: '#99f6e4', mid: '#14b8a6', shade: '#0f766e' }
        : {
            hi: 'var(--tooth-root-hi)',
            mid: 'var(--tooth-root-mid)',
            shade: 'var(--tooth-root-shade)',
          };

    return (
      <svg
        viewBox={realistic.viewBox}
        preserveAspectRatio={preserveAspectRatio}
        className={`${className} shrink-0 pointer-events-none`}
        style={svgStyle}
        aria-hidden
      >
        <defs>
          <radialGradient id={crownGradId} cx="40%" cy="35%" r="70%">
            <stop offset="0%" stopColor={crownStops.hi} />
            <stop offset="55%" stopColor={crownStops.mid} />
            <stop offset="100%" stopColor={crownStops.shade} />
          </radialGradient>
          <linearGradient id={rootGradId} x1="30%" y1="0%" x2="70%" y2="100%">
            <stop offset="0%" stopColor={rootStops.hi} />
            <stop offset="55%" stopColor={rootStops.mid} />
            <stop offset="100%" stopColor={rootStops.shade} />
          </linearGradient>
        </defs>
        <g transform={realistic.groupTransform}>
          {renderRealisticFill(realistic, isOn, crownGradId, rootGradId, glow)}
        </g>
      </svg>
    );
  }

  const model: ToothPathModel | null = getToothPathModel(fdi, kind, upper);

  if (!model) {
    return (
      <svg viewBox="0 0 36 78" className={`${className} shrink-0 pointer-events-none`} style={style} aria-hidden>
        <text x="4" y="40" fontSize="8" fill="currentColor" opacity="0.35">
          ?
        </text>
      </svg>
    );
  }

  const body = renderClinicalFill(model, isOn, gradientId, glow);

  const selectedStops = glow
    ? {
        inner: '#ffffff',
        mid: glow,
        outer: glow,
      }
    : {
        inner: '#cffafe',
        mid: '#5eead4',
        outer: '#0e7490',
      };

  return (
    <svg
      viewBox="0 0 36 78"
      className={`${className} shrink-0 pointer-events-none`}
      style={svgStyle}
      aria-hidden
    >
      <defs>
        <radialGradient id={gradientId} cx="45%" cy="35%" r="65%">
          <stop offset="0%" stopColor={isOn ? selectedStops.inner : '#ffffff'} />
          <stop offset="55%" stopColor={isOn ? selectedStops.mid : '#e0f2fe'} />
          <stop offset="100%" stopColor={isOn ? selectedStops.outer : '#93c5fd'} />
        </radialGradient>
      </defs>
      <g
        transform={[
          mirrored ? 'translate(36 0) scale(-1 1)' : '',
          upsideDown ? 'translate(0 78) scale(1 -1)' : '',
        ]
          .filter(Boolean)
          .join(' ') || undefined}
      >
        {body}
      </g>
    </svg>
  );
});
