import { useId } from 'react';
import type { ChakraType } from '@/lib/aura/types';
import { WHEEL_ORDER } from '@/lib/aura/energyGraphs';
import { cn } from '@/lib/cn';

/* Symbolic aura graphs. Every one is a plain SVG so it prints and scales cleanly. */

// Trig results can differ in the last digit between server and browser; rounding keeps hydration stable.
const r2 = (n: number) => Math.round(n * 100) / 100;

export interface BarPoint {
  key: ChakraType;
  label: string;
  /** 1–10 */
  value: number;
  color: string;
}

/** Seven chakra columns drawn as 3D blocks on a 1–10 scale, root on the left. */
export function ChakraBarGraph3D({ points, className }: { points: BarPoint[]; className?: string }) {
  const W = 560;
  const H = 320;
  const left = 34;
  const bottom = 270;
  const top = 34;
  const unit = (bottom - top) / 10;
  const slot = (W - left - 20) / points.length;
  const bw = slot * 0.52;
  const dx = 12;
  const dy = 8;
  return (
    <svg viewBox={`0 0 ${W} ${H}`} className={cn('w-full', className)} role="img" aria-label={points.map((p) => `${p.label} ${p.value}`).join(', ')}>
      {/* Back wall grid */}
      {Array.from({ length: 11 }, (_, i) => {
        const y = bottom - i * unit;
        return (
          <g key={i}>
            <line x1={left + dx} x2={W - 8} y1={y - dy} y2={y - dy} stroke="#fff" strokeOpacity={i === 0 ? 0.3 : 0.08} />
            <line x1={left} x2={left + dx} y1={y} y2={y - dy} stroke="#fff" strokeOpacity="0.08" />
            {i > 0 && (
              <text x={left - 8} y={y + 3} textAnchor="end" className="fill-white/45 text-[10px] tabular-nums">
                {i}
              </text>
            )}
          </g>
        );
      })}
      {/* Floor */}
      <path d={`M${left} ${bottom} L${W - 20} ${bottom} L${W - 8} ${bottom - dy} L${left + dx} ${bottom - dy} Z`} fill="#fff" fillOpacity="0.05" />
      {points.map((p, i) => {
        const x = left + i * slot + (slot - bw) / 2;
        const h = Math.max(0.4, p.value) * unit;
        const y = bottom - h;
        return (
          <g key={p.key}>
            <ellipse cx={x + bw / 2 + dx / 2} cy={bottom - dy / 2} rx={bw * 0.75} ry="6" fill={p.color} opacity="0.25" />
            {/* side */}
            <path d={`M${x + bw} ${y} L${x + bw + dx} ${y - dy} L${x + bw + dx} ${bottom - dy} L${x + bw} ${bottom} Z`} fill={p.color} />
            <path d={`M${x + bw} ${y} L${x + bw + dx} ${y - dy} L${x + bw + dx} ${bottom - dy} L${x + bw} ${bottom} Z`} fill="#000" opacity="0.35" />
            {/* front */}
            <rect x={x} y={y} width={bw} height={h} fill={p.color} />
            <rect x={x} y={y} width={bw * 0.35} height={h} fill="#fff" opacity="0.12" />
            {/* top */}
            <path d={`M${x} ${y} L${x + dx} ${y - dy} L${x + bw + dx} ${y - dy} L${x + bw} ${y} Z`} fill={p.color} />
            <path d={`M${x} ${y} L${x + dx} ${y - dy} L${x + bw + dx} ${y - dy} L${x + bw} ${y} Z`} fill="#fff" opacity="0.35" />
            <text x={x + bw / 2 + dx / 2} y={y - dy - 7} textAnchor="middle" className="fill-white text-[13px] font-semibold tabular-nums">
              {p.value}
            </text>
            <text x={x + bw / 2} y={bottom + 20} textAnchor="middle" className="fill-white/70 text-[10.5px] font-medium">
              {p.label}
            </text>
          </g>
        );
      })}
    </svg>
  );
}

/* ------------------------------------------------------------------ */

const MBS_COLOR = { mind: '#F5B301', body: '#E11D2E', spirit: '#8B5CF6' } as const;
export type MbsPart = keyof typeof MBS_COLOR;
export { MBS_COLOR };

/** Pie of mind / body / spirit shares, each slice labelled with its percentage. */
export function MindBodySpiritPie({
  values,
  labels,
  className,
}: {
  values: Record<MbsPart, number>;
  labels: Record<MbsPart, string>;
  className?: string;
}) {
  const parts: MbsPart[] = ['mind', 'body', 'spirit'];
  const R = 90;
  let start = -Math.PI / 2;
  return (
    <svg viewBox="0 0 220 220" className={className} role="img" aria-label={parts.map((p) => `${labels[p]} ${values[p]}%`).join(', ')}>
      <circle cx="110" cy="110" r={R + 8} fill={MBS_COLOR.spirit} opacity="0.06" />
      {parts.map((p) => {
        const sweep = (values[p] / 100) * Math.PI * 2;
        const end = start + sweep;
        const mid = start + sweep / 2;
        const large = sweep > Math.PI ? 1 : 0;
        const a = [r2(110 + R * Math.cos(start)), r2(110 + R * Math.sin(start))];
        const b = [r2(110 + R * Math.cos(end)), r2(110 + R * Math.sin(end))];
        const lx = r2(110 + R * 0.6 * Math.cos(mid));
        const ly = r2(110 + R * 0.6 * Math.sin(mid));
        start = end;
        if (values[p] <= 0) return null;
        return (
          <g key={p}>
            <path
              d={values[p] >= 100 ? `M110 ${110 - R} A${R} ${R} 0 1 1 109.99 ${110 - R} Z` : `M110 110 L${a[0]} ${a[1]} A${R} ${R} 0 ${large} 1 ${b[0]} ${b[1]} Z`}
              fill={MBS_COLOR[p]}
              stroke="#fff"
              strokeWidth="2.5"
            />
            <text x={lx} y={ly - 2} textAnchor="middle" className="fill-white text-[17px] font-semibold tabular-nums">
              {values[p]}%
            </text>
            <text x={lx} y={ly + 13} textAnchor="middle" className="fill-white/90 text-[9.5px] font-medium tracking-wide uppercase">
              {labels[p]}
            </text>
          </g>
        );
      })}
    </svg>
  );
}

/* ------------------------------------------------------------------ */

/**
 * A wave whose ripple grows as the chakras grow uneven. The stroke runs through the
 * person's aura colours; a faint flat line marks perfect calm for comparison.
 */
export function AuraWave({ amplitude, colors, className }: { amplitude: number; colors: string[]; className?: string }) {
  const id = useId().replace(/:/g, '');
  const W = 520;
  const H = 150;
  const mid = H / 2;
  const A = 8 + amplitude * 52;
  const pts: string[] = [];
  for (let x = 0; x <= W; x += 4) {
    const t = x / W;
    const jitter = amplitude * (Math.sin(t * 47) * 0.35 + Math.sin(t * 83 + 2) * 0.2);
    const y = mid + A * (Math.sin(t * Math.PI * 6) * 0.75 + jitter) * Math.sin(t * Math.PI) ** 0.4;
    pts.push(`${x},${y.toFixed(1)}`);
  }
  return (
    <svg viewBox={`0 0 ${W} ${H}`} className={cn('w-full', className)} aria-hidden>
      <defs>
        <linearGradient id={`wave-${id}`} x1="0" x2="1">
          {colors.map((c, i) => (
            <stop key={i} offset={`${(i / Math.max(1, colors.length - 1)) * 100}%`} stopColor={c} />
          ))}
        </linearGradient>
      </defs>
      {[0.25, 0.5, 0.75].map((f) => (
        <line key={f} x1="0" x2={W} y1={H * f} y2={H * f} stroke="currentColor" strokeOpacity="0.07" />
      ))}
      <line x1="0" x2={W} y1={mid} y2={mid} stroke="currentColor" strokeOpacity="0.18" strokeDasharray="4 6" />
      <polyline points={pts.join(' ')} fill="none" stroke={`url(#wave-${id})`} strokeWidth="10" strokeOpacity="0.18" strokeLinejoin="round" />
      <polyline points={pts.join(' ')} fill="none" stroke={`url(#wave-${id})`} strokeWidth="3" strokeLinejoin="round" strokeLinecap="round" />
    </svg>
  );
}

/* ------------------------------------------------------------------ */

/**
 * The seven chakra colours as a wheel, with a yin needle (incoming, left zone)
 * and a yang needle (outgoing, right zone).
 */
export function YinYangWheel({
  colors,
  yin,
  yang,
  className,
}: {
  colors: Record<ChakraType, string>;
  yin: ChakraType;
  yang: ChakraType;
  className?: string;
}) {
  const R = 100;
  const r = 52;
  const n = WHEEL_ORDER.length;
  const seg = (Math.PI * 2) / n;
  const angleOf = (c: ChakraType) => -Math.PI / 2 + (WHEEL_ORDER.indexOf(c) + 0.5) * seg;
  const pt = (rad: number, a: number) => [r2(120 + rad * Math.cos(a)), r2(120 + rad * Math.sin(a))];
  // When both needles point at the same colour, fan them apart a little so both stay visible.
  const spread = yin === yang ? seg * 0.18 : 0;
  const needles = [
    { a: angleOf(yin) - spread, sign: '♀', color: '#EC4899' },
    { a: angleOf(yang) + spread, sign: '♂', color: '#2563EB' },
  ];
  return (
    <svg viewBox="0 0 240 240" className={className} aria-hidden>
      {WHEEL_ORDER.map((c, i) => {
        const a0 = -Math.PI / 2 + i * seg;
        const a1 = a0 + seg;
        const [x0, y0] = pt(R, a0);
        const [x1, y1] = pt(R, a1);
        const [x2, y2] = pt(r, a1);
        const [x3, y3] = pt(r, a0);
        const on = c === yin || c === yang;
        return (
          <path
            key={c}
            d={`M${x0} ${y0} A${R} ${R} 0 0 1 ${x1} ${y1} L${x2} ${y2} A${r} ${r} 0 0 0 ${x3} ${y3} Z`}
            fill={colors[c]}
            opacity={on ? 1 : 0.55}
            stroke="#fff"
            strokeWidth="2"
          />
        );
      })}
      {/* yin-yang */}
      <g transform="translate(120 120)">
        <circle r="26" fill="#fff" stroke="#1F2937" strokeWidth="1.5" />
        <path d="M0 -26 A26 26 0 0 1 0 26 A13 13 0 0 1 0 0 A13 13 0 0 0 0 -26 Z" fill="#1F2937" />
        <circle cy="-13" r="4" fill="#fff" />
        <circle cy="13" r="4" fill="#1F2937" />
      </g>
      {needles.map(({ a, sign, color }) => {
        const [x0, y0] = pt(30, a);
        const [x1, y1] = pt(R + 6, a);
        const [lx, ly] = pt(R + 18, a);
        return (
          <g key={sign}>
            <line x1={x0} y1={y0} x2={x1} y2={y1} stroke={color} strokeWidth="3.5" strokeLinecap="round" />
            <circle cx={x1} cy={y1} r="3.5" fill={color} />
            <text x={lx} y={ly + 5} textAnchor="middle" className="text-[15px] font-bold" fill={color}>
              {sign}
            </text>
          </g>
        );
      })}
    </svg>
  );
}

/* ------------------------------------------------------------------ */

/** Ten rising bars, the first `level` of them filled blue. */
export function RelaxationBars({ level, low, high, className }: { level: number; low: string; high: string; className?: string }) {
  return (
    <div className={className}>
      <div className="flex h-32 items-end gap-1.5" aria-hidden>
        {Array.from({ length: 10 }, (_, i) => (
          <span
            key={i}
            className={cn('flex-1 rounded-t-md', i < level ? 'bg-gradient-to-t from-sky-600 to-sky-400' : 'bg-line/70')}
            style={{ height: `${18 + i * 9}%` }}
          />
        ))}
      </div>
      <div className="mt-2 flex justify-between text-[11px] font-medium text-subtle">
        <span>{low}</span>
        <span>{high}</span>
      </div>
    </div>
  );
}
