// Ministry network — radial chord-style.
// Smaller circles, edges between ministries that co-appear in the same suositus.

const MinistryViz = () => {
  const data = window.TUTKE_DATA;

  const stats = React.useMemo(() => {
    const counts = {};
    const goalsByMin = {};
    data.goals.forEach(g => {
      g.ministries.forEach(m => {
        counts[m] = (counts[m] || 0) + 1;
        (goalsByMin[m] = goalsByMin[m] || []).push(g.id);
      });
    });
    const entries = Object.entries(counts).sort((a, b) => b[1] - a[1]);

    // Co-occurrence: pairs of ministries sharing the same suositus
    const pairs = {};
    data.goals.forEach(g => {
      const ms = g.ministries;
      for (let i = 0; i < ms.length; i++) {
        for (let j = i+1; j < ms.length; j++) {
          const k = [ms[i], ms[j]].sort().join('|');
          pairs[k] = (pairs[k] || 0) + 1;
        }
      }
    });
    return { entries, goalsByMin, pairs };
  }, [data.goals]);

  // Radial layout — pulled inward so outward labels stay inside the viewBox
  const layout = React.useMemo(() => {
    const items = stats.entries.map(([name, count], i) => {
      const total = stats.entries.length;
      const angle = (i / total) * Math.PI * 2 - Math.PI / 2;
      const r = 28;  // was 38 — much more room for outward labels
      return {
        name,
        count,
        angle,
        x: 50 + Math.cos(angle) * r,
        y: 50 + Math.sin(angle) * r,
        size: 1.6 + count * 0.7,
      };
    });
    return items;
  }, [stats]);

  const lookup = React.useMemo(() => {
    const m = {};
    layout.forEach(L => { m[L.name] = L; });
    return m;
  }, [layout]);

  const [hovered, setHovered] = React.useState(null);

  React.useEffect(() => {
    if (!window.gsap || !window.ScrollTrigger) return;
    gsap.registerPlugin(ScrollTrigger);
    const ctx = gsap.context(() => {
      gsap.from('.ministry-svg circle.min-node', {
        scale: 0, transformOrigin: 'center', opacity: 0,
        stagger: 0.04, duration: 0.6, ease: 'back.out(1.4)',
        scrollTrigger: { trigger: '.ministry-stage', start: 'top 70%', once: true }
      });
      gsap.from('.ministry-svg .min-edge, .ministry-svg .min-spoke', {
        opacity: 0, duration: 0.9, stagger: 0.02,
        scrollTrigger: { trigger: '.ministry-stage', start: 'top 70%', once: true }
      });
    });
    return () => ctx.revert();
  }, []);

  // Build edges (only for pairs where both endpoints are in layout)
  const edges = React.useMemo(() => {
    return Object.entries(stats.pairs).map(([k, weight]) => {
      const [a, b] = k.split('|');
      return { a: lookup[a], b: lookup[b], weight };
    }).filter(e => e.a && e.b);
  }, [stats, lookup]);

  // Label position with outward offset
  const labelPos = (m) => {
    const off = m.size + 3;
    return {
      x: 50 + Math.cos(m.angle) * (28 + off),
      y: 50 + Math.sin(m.angle) * (28 + off),
    };
  };

  return (
    <section className="ministry" data-screen-label="06 Vastuutahot">
      <div className="ministry-head">
        <div className="eyebrow">§ 04 · Vastuutahojen verkosto</div>
        <h2>Kenen pöydällä nämä asiat ovat?</h2>
        <p>Suositukset koskettavat 21 eri vastuutahoa. Solmun koko kertoo kuinka monessa suosituksessa kukin esiintyy. Viivat yhdistävät tahot, jotka jakavat saman suosituksen.</p>
      </div>

      <div className="ministry-stage">
        <svg className="ministry-svg" viewBox="0 0 100 80" preserveAspectRatio="xMidYMid meet">
          <defs>
            <radialGradient id="ministry-core-grad" cx="35%" cy="30%" r="70%">
              <stop offset="0%" stopColor="#4a7c7c" />
              <stop offset="60%" stopColor="#2d5a5a" />
              <stop offset="100%" stopColor="#1a3030" />
            </radialGradient>
            <radialGradient id="ministry-core-glow" cx="50%" cy="50%" r="50%">
              <stop offset="0%" stopColor="#69a3a3" stopOpacity="0.45" />
              <stop offset="55%" stopColor="#69a3a3" stopOpacity="0.12" />
              <stop offset="100%" stopColor="#69a3a3" stopOpacity="0" />
            </radialGradient>
          </defs>

          {/* Spokes — center to each ministry node */}
          {layout.map(m => {
            const isNodeHover = hovered === m.name;
            const dimmed = hovered && !isNodeHover;
            return (
              <line key={'spoke-' + m.name}
                className="min-spoke"
                x1="50" y1="40"
                x2={m.x} y2={m.y - 10}
                stroke={isNodeHover ? '#69a3a3' : '#5a6a55'}
                strokeWidth={isNodeHover ? 0.18 : 0.1}
                strokeOpacity={isNodeHover ? 0.7 : (dimmed ? 0.1 : 0.35)}
                vectorEffect="non-scaling-stroke" />
            );
          })}

          {/* Co-occurrence edges — always visible, lighter by default */}
          {edges.map((e, i) => {
            const isHover = hovered && (e.a.name === hovered || e.b.name === hovered);
            const dimmed = hovered && !isHover;
            return (
              <path key={i}
                className="min-edge"
                d={`M ${e.a.x} ${e.a.y - 10} Q 50 40, ${e.b.x} ${e.b.y - 10}`}
                stroke={isHover ? '#69a3a3' : '#5a6a55'}
                strokeWidth={isHover ? 0.22 : 0.12}
                strokeOpacity={isHover ? 0.95 : (dimmed ? 0.18 : 0.55)}
                fill="none"
                vectorEffect="non-scaling-stroke" />
            );
          })}

          {/* CENTER HUB — glow + single disc (no hover) */}
          <circle cx="50" cy="40" r="14" fill="url(#ministry-core-glow)" pointerEvents="none" />
          <circle cx="50" cy="40" r="8" fill="url(#ministry-core-grad)" stroke="#69a3a3" strokeWidth="0.2" vectorEffect="non-scaling-stroke" pointerEvents="none" />
          <text x="50" y="39.4" textAnchor="middle" dominantBaseline="middle"
            fontSize="2" fontFamily="EB Garamond" fontStyle="normal" fontWeight="500" fill="#f1ece2" pointerEvents="none">
            Suomi
          </text>
          <text x="50" y="41.6" textAnchor="middle" dominantBaseline="middle"
            fontSize="2" fontFamily="EB Garamond" fontStyle="normal" fontWeight="500" fill="#f1ece2" pointerEvents="none">
            2027
          </text>

          {/* Nodes + outward labels */}
          {layout.map(m => {
            const isHover = hovered === m.name;
            const lp = labelPos(m);
            const fullName = (data.ministryFullNames[m.name] || m.name).replace(/\u00ad/g, '');
            const angle = m.angle * 180 / Math.PI;
            const textAnchor = (angle > -90 && angle < 90) ? 'start' : 'end';
            return (
              <g key={m.name}
                style={{ cursor: 'pointer' }}
                onMouseEnter={() => setHovered(m.name)}
                onMouseLeave={() => setHovered(null)}>
                <circle
                  className="min-node"
                  cx={m.x} cy={m.y - 10} r={m.size}
                  fill={isHover ? '#69a3a3' : '#4a7c7c'}
                  fillOpacity={isHover ? 0.98 : 0.62}
                  stroke="#1a1c15"
                  strokeWidth="0.3"
                  vectorEffect="non-scaling-stroke"
                />
                {/* count inside */}
                <text x={m.x} y={m.y - 10 + 0.55}
                  textAnchor="middle" dominantBaseline="middle"
                  fontSize={m.size > 3.5 ? "1.8" : "1.3"}
                  fontFamily="EB Garamond" fontWeight="500"
                  fill="#1a1c15" pointerEvents="none">
                  {m.count}
                </text>
                {/* outward label — single-line, outside the node ring */}
                <text x={lp.x} y={lp.y - 10}
                  textAnchor={textAnchor}
                  dominantBaseline="middle"
                  fontSize="1.25"
                  fontFamily="JetBrains Mono"
                  letterSpacing="0.08em"
                  fill={isHover ? '#f1ece2' : '#9a9785'}>
                  {fullName}
                </text>
              </g>
            );
          })}
        </svg>

        <div className="ministry-mobile-list">
          {stats.entries.map(([name, count]) => (
            <div key={name} className="ministry-mobile-item">
              <div className="ministry-mobile-name">
                {(data.ministryFullNames[name] || name).replace(/­/g, '')}
              </div>
              <div className="ministry-mobile-meta">
                <span className="count">{count} {count === 1 ? 'suositus' : 'suositusta'}</span>
                <span className="ids">{stats.goalsByMin[name].map(id => '№' + id).join(' · ')}</span>
              </div>
            </div>
          ))}
        </div>

        <div className="ministry-legend">
          <div className="item"><span className="swatch" style={{ background: '#4a7c7c' }}></span><span>Solmu = vastuutaho</span></div>
          <div className="item"><span className="swatch" style={{ background: '#69a3a3' }}></span><span>Koko = suositusten määrä</span></div>
          <div className="item"><span className="swatch swatch-line"></span><span>Viiva = jakavat suosituksen</span></div>
          {hovered && (
            <div className="item ministry-legend-active">
              <span>{(data.ministryFullNames[hovered] || hovered).replace('­','')} → suositukset {stats.goalsByMin[hovered].map(id => '№' + id).join(', ')}</span>
            </div>
          )}
        </div>
      </div>
    </section>
  );
};

window.MinistryViz = MinistryViz;
