// Atlas — Cuerpo anatómico de solo lectura, coloreado por intensidad de volumen.
// Reutiliza los trazos SVG licenciados (window.MUSCLE_MAP), el mismo cuerpo que
// usa el Builder. Colorea cada región por series efectivas en 4 niveles de azul
// Atlas (distinguidos por LUMINOSIDAD, no solo por tono). Táctil con hit-testing
// por centro de músculo (como el Builder) y aria-label por músculo.

// slug → id de músculo Atlas, por vista (igual config que el mapa del Builder).
const MH_FRONT = {
  chest:'pecho', obliques:'oblicuos', abs:'core', biceps:'biceps',
  triceps:'triceps', trapezius:'trapecio', deltoids:'delt_lat',
  adductors:'aductores', quadriceps:'cuadriceps', tibialis:'tibial',
  calves:'gemelos', forearm:'antebrazo',
};
const MH_BACK = {
  trapezius:'trapecio', deltoids:'delt_post', triceps:'triceps',
  'upper-back':'dorsal', 'lower-back':'lumbar', forearm:'antebrazo',
  gluteal:'gluteos', adductors:'aductores', hamstring:'isquio', calves:'gemelos',
};
const MH_SMALL = new Set(['antebrazo','tibial','gemelos','biceps','triceps','delt_lat','delt_post','oblicuos','aductores']);

// Nivel de intensidad (0–3) por series efectivas: 0 · 1–4 · 5–9 · 10+.
function mhLevel(series) {
  const s = Number(series) || 0;
  if (s <= 0) return 0;
  if (s < 5) return 1;
  if (s < 10) return 2;
  return 3;
}
// 4 azules Atlas en rampa de luminosidad creciente (sobre fondo navy).
const MH_COLORS = ['#263349', '#1E40AF', '#2563EB', '#60A5FA'];
const MH_LEGEND = [
  { lvl: 0, label: '0' }, { lvl: 1, label: '1–4' }, { lvl: 2, label: '5–9' }, { lvl: 3, label: '10+' },
];

// ¿En qué vista se ve mejor un músculo? (para las mini-siluetas).
function mhViewFor(id) {
  return (['delt_post','dorsal','lumbar','gluteos','isquio','trapecio'].indexOf(id) !== -1) ? 'back' : 'front';
}

// view: 'front'|'back'; volume: { id: series }; onPick(id); highlightId: resalta
// un solo músculo (mini-silueta); solo: dibuja solo el contorno + ese músculo
// (mini-siluetas ligeras); interactive: taps on/off.
// `height` fija + ancho AUTO (el SVG conserva su proporción vía viewBox +
// preserveAspectRatio="xMidYMid meet"; nunca se fuerzan ancho y alto a la vez,
// que es lo que deformaba la silueta dentro de un flex).
function AtlasBodyHeat({ view, volume, onPick, selected, highlightId, highlight, solo = false, interactive = true, height = 220 }) {
  // Id de gradiente ÚNICO por instancia: con varios cuerpos en la página, un id
  // repetido ("mh-body") hace que Safari no resuelva url(#id) y se pinten en
  // blanco. useId garantiza unicidad sin colisiones.
  const uid = (typeof React.useId === 'function') ? React.useId().replace(/[:]/g, '') : React.useMemo(() => 'mh' + Math.random().toString(36).slice(2), []);
  const gradId = 'mhbody-' + uid;
  const svgRef = React.useRef(null);
  const centersRef = React.useRef([]);
  const data    = (typeof window !== 'undefined') ? window.MUSCLE_MAP : null;
  const slugMap = view === 'back' ? MH_BACK : MH_FRONT;
  const parts   = data ? (view === 'back' ? data.back : data.front) : [];
  const viewBox = data ? (view === 'back' ? data.viewBoxBack : data.viewBoxFront) : '0 0 724 1448';
  const outline = data ? (view === 'back' ? data.outlineBack : data.outlineFront) : '';
  const originX = view === 'back' ? 724 : 0;
  const vol = volume || {};

  React.useLayoutEffect(() => {
    const svg = svgRef.current;
    if (!svg || !interactive) return;
    const list = [];
    svg.querySelectorAll('[data-mid]').forEach(el => {
      let bb; try { bb = el.getBBox(); } catch (e) { return; }
      if (!bb || (!bb.width && !bb.height)) return;
      list.push({ id: el.getAttribute('data-mid'), cx: bb.x + bb.width / 2, cy: bb.y + bb.height / 2, small: MH_SMALL.has(el.getAttribute('data-mid')) });
    });
    centersRef.current = list;
  }, [view, interactive]);

  function pickAt(clientX, clientY) {
    const svg = svgRef.current;
    if (!svg || !svg.getScreenCTM) return null;
    const ctm = svg.getScreenCTM(); if (!ctm) return null;
    const pt = svg.createSVGPoint(); pt.x = clientX; pt.y = clientY;
    const p = pt.matrixTransform(ctm.inverse());
    let best = null, bestEff = Infinity, bestRaw = Infinity;
    for (const c of centersRef.current) {
      const raw = Math.hypot(p.x - c.cx, p.y - c.cy);
      const eff = raw * (c.small ? 0.8 : 1);
      if (eff < bestEff) { bestEff = eff; best = c.id; bestRaw = raw; }
    }
    return (best && bestRaw <= 320) ? best : null;
  }

  function fillFor(id) {
    if (highlight) return highlight[id] ? '#3B82F6' : '#41506e';   // primario/secundario vs silueta base
    if (highlightId) return id === highlightId ? MH_COLORS[3] : '#2b3450';
    const lvl = mhLevel(vol[id]);
    return MH_COLORS[lvl];
  }
  function opacityFor(id) {
    if (highlight) { const lv = highlight[id]; return lv === 'primary' ? 1 : lv === 'secondary' ? 0.35 : 0.9; }
    if (highlightId) return id === highlightId ? 1 : 0.45;
    return selected === id ? 1 : 0.95;
  }

  return (
    <svg ref={svgRef} viewBox={viewBox} preserveAspectRatio="xMidYMid meet"
      role={interactive ? 'group' : 'img'}
      aria-label={interactive ? undefined : `Cuerpo ${view === 'back' ? 'de espalda' : 'de frente'}`}
      onClick={interactive ? (e => { const id = pickAt(e.clientX, e.clientY); if (id && onPick) onPick(id); }) : undefined}
      style={{ height, width:'auto', maxWidth:'100%', display:'block', margin:'0 auto', overflow:'visible', touchAction:'manipulation', cursor: interactive ? 'pointer' : 'default' }}>
      <rect x={originX} y="0" width="724" height="1448" fill="#000" fillOpacity="0" />
      <defs>
        <linearGradient id={gradId} x1="0" y1="0" x2="0" y2="1">
          <stop offset="0%" stopColor="#1a2338" /><stop offset="100%" stopColor="#0e1526" />
        </linearGradient>
      </defs>
      {outline && <path d={outline} fill={`url(#${gradId})`} stroke="rgba(120,150,210,0.20)" strokeWidth="2" strokeDasharray="none" style={{ pointerEvents:'none', vectorEffect:'non-scaling-stroke' }} />}
      {parts.map((part, pi) => {
        const id = slugMap[part.slug];
        const path = part.path || {};
        const sides = ['common', 'left', 'right'].filter(s => Array.isArray(path[s]) && path[s].length);
        if (solo) {
          // Mini-silueta: solo el músculo resaltado (azul Atlas) sobre el contorno.
          if (id !== highlightId) return null;
          return sides.map(s => (
            <g key={pi + s} fill="#2563EB" opacity="1" stroke="rgba(10,16,30,0.5)" strokeWidth="1" strokeDasharray="none" style={{ pointerEvents:'none' }}>
              {path[s].map((d, i) => <path key={i} d={d} />)}
            </g>
          ));
        }
        if (!id) {
          return <g key={pi} fill="#232c44" opacity="0.85" style={{ pointerEvents:'none' }}>{sides.flatMap(s => path[s].map((d, i) => <path key={s + i} d={d} />))}</g>;
        }
        const series = vol[id];
        const aria = `${(window.mvLabel ? window.mvLabel(id) : id)}${series != null ? ` · ${(Math.round(series * 10) / 10)} series` : ''}`;
        return sides.map(s => (
          <g key={pi + s} data-mid={id} fill={fillFor(id)} opacity={opacityFor(id)}
            role={interactive ? 'button' : undefined} aria-label={interactive ? aria : undefined}
            stroke="rgba(10,16,30,0.55)" strokeWidth="1"
            style={{ pointerEvents:'none', transition:'fill .16s ease, opacity .16s ease' }}>
            {path[s].map((d, i) => <path key={i} d={d} />)}
          </g>
        ));
      })}
    </svg>
  );
}

// Leyenda de intensidad reutilizable.
function AtlasHeatLegend({ compact }) {
  return (
    <div style={{ display:'flex', alignItems:'center', gap: compact ? 8 : 12, flexWrap:'wrap', justifyContent:'center' }}>
      {MH_LEGEND.map(l => (
        <span key={l.lvl} style={{ display:'inline-flex', alignItems:'center', gap:5, fontFamily:'"Inter",system-ui', fontSize:11, color:'rgba(230,236,247,0.65)' }}>
          <span style={{ width:12, height:12, borderRadius:3, background: MH_COLORS[l.lvl], flexShrink:0, border:'1px solid rgba(255,255,255,0.08)' }} />
          {l.label}
        </span>
      ))}
      <span style={{ fontFamily:'"Inter",system-ui', fontSize:11, color:'rgba(230,236,247,0.4)' }}>series/sem</span>
    </div>
  );
}

// ── Parte B · Distribución muscular de una rutina ─────────────────────────────
// exercises: lista de ejercicios de TODA la rutina (todos los días), cada uno
// con { muscles:{primary,secondary}, sets|setsCount }. Pensado para tarjeta oscura.
function MuscleDistribution({ exercises, onOpenArticle }) {
  const tally = (typeof muscleVolume === 'function') ? muscleVolume(exercises, { completedOnly: false }) : {};
  const total = (typeof mvTotal === 'function') ? mvTotal(tally) : 0;
  if (!total) return null;
  const top = (typeof mvTop === 'function') ? mvTop(tally, 5) : [];
  const all = Object.entries(tally).filter(([, v]) => v > 0).sort((a, b) => b[1] - a[1]);
  const fmt = v => (v % 1 === 0 ? String(v) : String(Math.round(v * 10) / 10).replace('.', ','));
  const T = 'rgba(230,236,247,0.92)', SUB = 'rgba(230,236,247,0.6)', MUT = 'rgba(230,236,247,0.4)';

  return (
    <div style={{ marginTop:14 }}>
      {/* Top músculos: mini silueta + nombre + % */}
      <div style={{ display:'flex', gap:6, overflowX:'auto', paddingBottom:4, WebkitOverflowScrolling:'touch' }}>
        {top.map(t => (
          <div key={t.id} style={{ flex:'1 0 auto', minWidth:64, textAlign:'center', padding:'8px 4px', borderRadius:12, background:'rgba(255,255,255,0.03)', border:'1px solid rgba(255,255,255,0.07)' }}>
            <div style={{ display:'flex', justifyContent:'center', height:64 }}>
              <AtlasBodyHeat view={mhViewFor(t.id)} solo highlightId={t.id} interactive={false} height={64} />
            </div>
            <div style={{ fontFamily:'"Inter",system-ui', fontSize:10.5, fontWeight:600, color:T, lineHeight:1.2, marginTop:2 }}>{mvLabel(t.id)}</div>
            <div style={{ fontFamily:'ui-monospace,Menlo,monospace', fontSize:13, fontWeight:800, color:'#60A5FA' }}>{t.pct}%</div>
          </div>
        ))}
      </div>

      {/* Series/sem por músculo (toda la rutina) + rango orientativo suave */}
      <div style={{ marginTop:12, display:'flex', flexDirection:'column', gap:5 }}>
        {all.map(([id, series]) => {
          const r = (typeof mvRange === 'function') ? mvRange(id) : null;
          return (
            // El nombre puede ocupar dos líneas (flex:1, minWidth:0) sin romper la
            // cifra: "N series/sem · orientativo X–Y" va en un bloque nowrap que no
            // se parte (antes se rompía en 3 líneas a 375 px con nombres largos).
            <div key={id} style={{ display:'flex', alignItems:'baseline', gap:8, fontFamily:'"Inter",system-ui', fontSize:12.5 }}>
              <span style={{ color:T, fontWeight:600, flex:'1 1 auto', minWidth:0 }}>{mvLabel(id)}</span>
              <span style={{ color:SUB, whiteSpace:'nowrap', flexShrink:0 }}>
                {fmt(series)} series/sem
                {r && <span style={{ color:MUT, fontSize:11 }}> · orientativo {r.mev}–{r.mrv}</span>}
              </span>
            </div>
          );
        })}
      </div>

      <div style={{ marginTop:10, fontFamily:'"Inter",system-ui', fontSize:11.5, color:SUB, lineHeight:1.5 }}>
        Más series suelen dar más músculo, con rendimientos decrecientes.
        {onOpenArticle && <> <button onClick={() => onOpenArticle('frecuencia-entrenamiento')} style={{ padding:0, background:'none', border:'none', color:'#93C5FD', fontFamily:'"Inter",system-ui', fontSize:11.5, fontWeight:700, cursor:'pointer', textDecoration:'underline' }}>Volumen y frecuencia</button></>}
      </div>
    </div>
  );
}

Object.assign(window, { AtlasBodyHeat, AtlasHeatLegend, MuscleDistribution, mhViewFor, mhLevel, MH_COLORS });
