/* ============================================================
   昆虫整理人格 · 结果页
   ============================================================ */

function radarGeometry(scores, dims, cx, cy, R, startAngle = -Math.PI / 2) {
  const n = dims.length;
  return dims.map((d, i) => {
    const ang = startAngle + (i / n) * Math.PI * 2;
    const v = Math.max(0, Math.min(100, scores[d.key] || 0)) / 100;
    const r = v * R;
    return {
      key: d.key, label: d.label, color: d.color, score: scores[d.key] || 0,
      ang,
      x: cx + Math.cos(ang) * r, y: cy + Math.sin(ang) * r,
      ax: cx + Math.cos(ang) * R, ay: cy + Math.sin(ang) * R,
      lx: cx + Math.cos(ang) * (R + 26), ly: cy + Math.sin(ang) * (R + 26),
    };
  });
}

function RadarSVG({ scores, dims, accent }) {
  const W = 360, cx = W / 2, cy = 168, R = 118;
  const rings = [0.25, 0.5, 0.75, 1];
  const pts = radarGeometry(scores, dims, cx, cy, R);
  const polygon = pts.map((p) => `${p.x.toFixed(1)},${p.y.toFixed(1)}`).join(" ");
  const ringPoly = (f) => dims.map((d, i) => {
    const ang = -Math.PI / 2 + (i / dims.length) * Math.PI * 2;
    return `${(cx + Math.cos(ang) * R * f).toFixed(1)},${(cy + Math.sin(ang) * R * f).toFixed(1)}`;
  }).join(" ");

  return (
    <svg viewBox={`0 0 ${W} 340`}>
      {rings.map((f, i) => (
        <polygon key={i} points={ringPoly(f)} fill="none"
          stroke="var(--line)" strokeWidth={i === rings.length - 1 ? 1.6 : 1} opacity={i === rings.length - 1 ? 1 : .7} />
      ))}
      {pts.map((p) => (
        <line key={p.key} x1={cx} y1={cy} x2={p.ax} y2={p.ay} stroke="var(--line)" strokeWidth="1" />
      ))}
      <polygon points={polygon} fill={accent} fillOpacity="0.18" stroke={accent} strokeWidth="2.4"
        style={{ transition: "all .8s cubic-bezier(.3,.8,.3,1)" }} />
      {pts.map((p) => (
        <circle key={p.key} cx={p.x} cy={p.y} r="4.2" fill={p.color} stroke="var(--card)" strokeWidth="1.8" />
      ))}
      {pts.map((p) => {
        const anchor = Math.abs(p.lx - cx) < 8 ? "middle" : (p.lx > cx ? "start" : "end");
        return (
          <g key={p.key}>
            <text x={p.lx} y={p.ly - 3} textAnchor={anchor}
              fontFamily="var(--font-display)" fontSize="14" fontWeight="700" fill="var(--fg)">{p.label}</text>
            <text x={p.lx} y={p.ly + 13} textAnchor={anchor}
              fontSize="11" fontWeight="700" fill={p.color} style={{ fontVariantNumeric: "tabular-nums" }}>{p.score}</text>
          </g>
        );
      })}
    </svg>
  );
}

function PersonaGlyph({ type }) {
  const body = {
    butterfly: (
      <React.Fragment>
        <path className="area" d="M46 47H32c-11 0-18-7-18-17 0-12 9-20 20-20 8 0 12 5 12 13v24z" />
        <path className="area" d="M50 47h14c11 0 18-7 18-17 0-12-9-20-20-20-8 0-12 5-12 13v24z" />
        <path className="area" d="M46 50H34c-10 0-17 8-17 18v10h13c10 0 16-7 16-17V50z" />
        <path className="area" d="M50 50h12c10 0 17 8 17 18v10H66c-10 0-16-7-16-17V50z" />
        <path className="thin" d="M46 20c-2-13-15-18-40-20 M50 20c2-13 15-18 40-20" />
      </React.Fragment>
    ),
    ladybug: (
      <React.Fragment>
        <path className="thin" d="M39 25c-9-9 -17-18 -28-12M57 25c9-9 17-18 28-12" />
        <path className="line" d="M35 34c3-16 23-16 26 0" />
        <ellipse className="area" cx="48" cy="62" rx="26" ry="28" />
        <path className="thin" d="M48 35v50" />
        <circle className="fill" cx="37" cy="57" r="3.2" />
        <circle className="fill" cx="59" cy="57" r="3.2" />
        <circle className="fill" cx="39" cy="73" r="3.2" />
        <circle className="fill" cx="57" cy="73" r="3.2" />
      </React.Fragment>
    ),
    bee: (
      <React.Fragment>
        <path className="thin" d="M38 29c-6-18-23-21-33-7M58 29c6-18 23-21 33-7" />
        <path className="area" d="M19 53c12-15 29-15 38 0-11 13-27 13-38 0z" />
        <path className="area" d="M39 53c9-15 26-15 38 0-11 13-27 13-38 0z" />
        <circle className="area" cx="48" cy="35" r="12" />
        <path className="area" d="M29 60c0-15 8-25 19-25s19 10 19 25c0 14-8 23-19 31-11-8-19-17-19-31z" />
        <path className="thin" d="M33 61h30M36 74h24" />
      </React.Fragment>
    ),
    cricket: (
      <React.Fragment>
        <path className="area" d="M48 38c18 15 21 36 0 52-21-16-18-37 0-52z" />
        <path className="area" d="M36 31c-11 6-18 18-18 35v19c15-6 24-17 24-35 0-7-2-13-6-19z" />
        <path className="area" d="M60 31c11 6 18 18 18 35v19c-15-6-24-17-24-35 0-7 2-13 6-19z" />
        <circle className="area" cx="48" cy="34" r="10" />
        <path className="thin" d="M40 28c-4-18-20-25-32-12M56 28c4-18 20-25 32-12" />
      </React.Fragment>
    ),
  }[type];
  return (
    <svg className="persona-glyph" viewBox="0 0 96 96" aria-hidden="true">
      {body}
    </svg>
  );
}

function ResultView({ survey, scores, answers, persona, pKey, accent, onRestart, toast }) {
  const dims = survey.dimensions;
  const source = survey.source || {};
  const sorted = [...dims].sort((a, b) => (scores[b.key] || 0) - (scores[a.key] || 0));
  const topScore = scores[sorted[0].key] || 0;
  const companions = sorted
    .filter((d, i) => i > 0 && topScore - (scores[d.key] || 0) <= 6)
    .map((d) => d.full);

  const exportImage = async () => {
    try { await document.fonts.ready; } catch (e) {}
    const S = 2;
    const W = 540, H = 720;
    const cvs = document.createElement("canvas");
    cvs.width = W * S; cvs.height = H * S;
    const ctx = cvs.getContext("2d");
    ctx.scale(S, S);

    ctx.fillStyle = "#FAF6EE"; ctx.fillRect(0, 0, W, H);
    const g = ctx.createRadialGradient(W / 2, -40, 40, W / 2, 200, 460);
    g.addColorStop(0, "rgba(251,239,196,.55)"); g.addColorStop(1, "rgba(251,239,196,0)");
    ctx.fillStyle = g; ctx.fillRect(0, 0, W, H);
    ctx.strokeStyle = "rgba(31,42,46,.16)"; ctx.lineWidth = 2;
    ctx.strokeRect(20, 20, W - 40, H - 40);

    ctx.textAlign = "center";
    ctx.fillStyle = persona.color;
    ctx.font = "700 13px 'Noto Sans SC',sans-serif";
    ctx.fillText("昆 虫 整 理 人 格 · 测 试 结 果", W / 2, 58);

    drawPersonaGlyph(ctx, pKey, W / 2 - 54, 84, 108, persona.color);

    ctx.fillStyle = "#1F2A2E";
    ctx.font = "700 34px 'Noto Serif SC',serif";
    ctx.fillText(persona.name, W / 2, 222);
    ctx.fillStyle = "#4a5550";
    ctx.font = "500 15px 'Noto Serif SC',serif";
    wrapText(ctx, persona.line, W / 2, 252, W - 120, 24);

    const rcx = W / 2, rcy = 430, R = 96;
    const pts = radarGeometry(scores, dims, rcx, rcy, R);
    [0.25, 0.5, 0.75, 1].forEach((f, i) => {
      ctx.beginPath();
      dims.forEach((d, k) => {
        const ang = -Math.PI / 2 + (k / dims.length) * Math.PI * 2;
        const x = rcx + Math.cos(ang) * R * f, y = rcy + Math.sin(ang) * R * f;
        k ? ctx.lineTo(x, y) : ctx.moveTo(x, y);
      });
      ctx.closePath();
      ctx.strokeStyle = "rgba(31,42,46,.15)"; ctx.lineWidth = i === 3 ? 1.4 : 1; ctx.stroke();
    });
    pts.forEach((p) => { ctx.beginPath(); ctx.moveTo(rcx, rcy); ctx.lineTo(p.ax, p.ay); ctx.strokeStyle = "rgba(31,42,46,.12)"; ctx.lineWidth = 1; ctx.stroke(); });
    ctx.beginPath();
    pts.forEach((p, i) => i ? ctx.lineTo(p.x, p.y) : ctx.moveTo(p.x, p.y));
    ctx.closePath();
    ctx.fillStyle = hexA(accent, .2); ctx.fill();
    ctx.strokeStyle = accent; ctx.lineWidth = 2.4; ctx.stroke();
    pts.forEach((p) => { ctx.beginPath(); ctx.arc(p.x, p.y, 3.4, 0, Math.PI * 2); ctx.fillStyle = p.color; ctx.fill(); });
    ctx.font = "700 13px 'Noto Sans SC',sans-serif";
    pts.forEach((p) => {
      ctx.textAlign = Math.abs(p.lx - rcx) < 10 ? "center" : (p.lx > rcx ? "left" : "right");
      ctx.fillStyle = "#1F2A2E";
      const ly = p.ly + (Math.abs(p.ly - rcy) < 10 ? (p.ly < rcy ? -2 : 10) : 4);
      ctx.fillText(p.label, p.lx, ly);
    });

    ctx.textAlign = "center";
    ctx.fillStyle = persona.color;
    ctx.font = "700 14px 'Noto Sans SC',sans-serif";
    ctx.fillText("# " + persona.role, W / 2, H - 56);
    ctx.fillStyle = "#7c857f";
    ctx.font = "500 12px 'Noto Sans SC',sans-serif";
    ctx.fillText("题目摘自《" + source.bookTitle + "》", W / 2, H - 36);

    cvs.toBlob((blob) => {
      const url = URL.createObjectURL(blob);
      const a = document.createElement("a");
      a.href = url; a.download = "昆虫整理人格-测试结果.png";
      document.body.appendChild(a); a.click(); a.remove();
      setTimeout(() => URL.revokeObjectURL(url), 2000);
      toast("已保存分享图");
    }, "image/png");
  };

  const shareLink = () => {
    const enc = btoa(unescape(encodeURIComponent(JSON.stringify({ s: scores, p: pKey }))));
    const url = location.origin + location.pathname + "#r=" + enc;
    if (navigator.clipboard) {
      navigator.clipboard.writeText(url).then(() => toast("结果链接已复制")).catch(() => prompt("复制此链接分享：", url));
    } else prompt("复制此链接分享：", url);
  };

  return (
    <div className="result" style={{ "--p-color": persona.color }}>
      <div className="persona-card">
        <div className="glow"></div>
        <div className="persona-symbol"><PersonaGlyph type={pKey} /></div>
        <div className="kicker">你 的 整 理 人 格</div>
        <h2>{persona.name}</h2>
        <p className="line">{persona.line}</p>
        <p className="blurb">{persona.blurb}</p>
        <div className="tags">
          {persona.strength.map((s) => <span key={s}>{s}</span>)}
        </div>
        {companions.length > 0 && (
          <div className="tip"><b>组合倾向</b><span>你也带有 {companions.join("、")} 的影子。不同空间里出现不同人格，很正常。</span></div>
        )}
        <div className="tip"><b>整理诀窍</b><span>{persona.tip}</span></div>
      </div>

      <div className="report">
        <div className="radar-box">
          <h3>四类整理人格分布</h3>
          <div className="sub">主导倾向 · {survey.personas[pKey].role}</div>
          <RadarSVG scores={scores} dims={dims} accent={accent} />
          <div className="bars">
            {sorted.map((d) => (
              <div className="bar-row" key={d.key}>
                <span className="nm">{d.full}</span>
                <span className="tk"><i style={{ width: (scores[d.key] || 0) + "%", background: d.color }}></i></span>
                <span className="vl">{scores[d.key] || 0}</span>
              </div>
            ))}
          </div>
        </div>
        <div className="source-card">
          <h3>出处与延伸阅读</h3>
          <p>本互动问卷摘自《{source.bookTitle}》，{source.author} 著，{source.translator} 译，{source.publisher} / {source.imprint}，{source.published}，ISBN {source.isbn}。</p>
          <p>{source.authorIntro}</p>
          <p>{source.usageNote}</p>
        </div>
        <div className="result-actions">
          <button className="btn primary" onClick={exportImage}>{Icon.download()}保存为图片</button>
          <button className="btn ghost" onClick={shareLink}>{Icon.share()}复制链接</button>
          <button className="btn ghost" onClick={onRestart}>{Icon.refresh()}再测一次</button>
        </div>
      </div>
    </div>
  );
}

function hexA(hex, a) {
  const h = hex.replace("#", "");
  const r = parseInt(h.substr(0, 2), 16), g = parseInt(h.substr(2, 2), 16), b = parseInt(h.substr(4, 2), 16);
  return `rgba(${r},${g},${b},${a})`;
}
function wrapText(ctx, text, x, y, maxW, lh) {
  const chars = text.split("");
  let line = "", yy = y;
  for (const ch of chars) {
    if (ctx.measureText(line + ch).width > maxW && line) { ctx.fillText(line, x, yy); line = ch; yy += lh; }
    else line += ch;
  }
  ctx.fillText(line, x, yy);
}

function roundedRect(ctx, x, y, w, h, r) {
  ctx.beginPath();
  ctx.moveTo(x + r, y);
  ctx.arcTo(x + w, y, x + w, y + h, r);
  ctx.arcTo(x + w, y + h, x, y + h, r);
  ctx.arcTo(x, y + h, x, y, r);
  ctx.arcTo(x, y, x + w, y, r);
  ctx.closePath();
}

function drawPersonaGlyph(ctx, type, x, y, size, color) {
  ctx.save();
  const s = size / 96;
  ctx.translate(x, y);
  ctx.scale(s, s);
  ctx.lineCap = "round";
  ctx.lineJoin = "round";

  const drawPath = (d, mode, width = 5.2) => {
    const path = new Path2D(d);
    ctx.lineWidth = width;
    ctx.strokeStyle = color;
    if (mode === "area") {
      ctx.fillStyle = hexA(color, .1);
      ctx.fill(path);
    }
    ctx.stroke(path);
  };
  const drawCircle = (cx, cy, r, mode) => {
    ctx.beginPath();
    ctx.arc(cx, cy, r, 0, Math.PI * 2);
    if (mode === "area") {
      ctx.fillStyle = hexA(color, .1);
      ctx.fill();
      ctx.lineWidth = 5.2;
      ctx.strokeStyle = color;
      ctx.stroke();
    } else {
      ctx.fillStyle = color;
      ctx.fill();
    }
  };
  const drawEllipse = (cx, cy, rx, ry) => {
    ctx.beginPath();
    ctx.ellipse(cx, cy, rx, ry, 0, 0, Math.PI * 2);
    ctx.fillStyle = hexA(color, .1);
    ctx.fill();
    ctx.lineWidth = 5.2;
    ctx.strokeStyle = color;
    ctx.stroke();
  };

  if (type === "butterfly") {
    drawPath("M46 47H32c-11 0-18-7-18-17 0-12 9-20 20-20 8 0 12 5 12 13v24z", "area");
    drawPath("M50 47h14c11 0 18-7 18-17 0-12-9-20-20-20-8 0-12 5-12 13v24z", "area");
    drawPath("M46 50H34c-10 0-17 8-17 18v10h13c10 0 16-7 16-17V50z", "area");
    drawPath("M50 50h12c10 0 17 8 17 18v10H66c-10 0-16-7-16-17V50z", "area");
    drawPath("M46 20c-2-13-15-18-40-20 M50 20c2-13 15-18 40-20", "line", 3.8);
  } else if (type === "ladybug") {
    drawPath("M39 25c-9-9 -17-18 -28-12M57 25c9-9 17-18 28-12", "line", 3.8);
    drawPath("M35 34c3-16 23-16 26 0", "line", 5.2);
    drawEllipse(48, 62, 26, 28);
    drawPath("M48 35v50", "line", 3.8);
    drawCircle(37, 57, 3.2);
    drawCircle(59, 57, 3.2);
    drawCircle(39, 73, 3.2);
    drawCircle(57, 73, 3.2);
  } else if (type === "bee") {
    drawPath("M38 29c-6-18-23-21-33-7M58 29c6-18 23-21 33-7", "line", 3.8);
    drawPath("M19 53c12-15 29-15 38 0-11 13-27 13-38 0z", "area");
    drawPath("M39 53c9-15 26-15 38 0-11 13-27 13-38 0z", "area");
    drawCircle(48, 35, 12, "area");
    drawPath("M29 60c0-15 8-25 19-25s19 10 19 25c0 14-8 23-19 31-11-8-19-17-19-31z", "area");
    drawPath("M33 61h30M36 74h24", "line", 3.8);
  } else {
    drawPath("M48 38c18 15 21 36 0 52-21-16-18-37 0-52z", "area");
    drawPath("M36 31c-11 6-18 18-18 35v19c15-6 24-17 24-35 0-7-2-13-6-19z", "area");
    drawPath("M60 31c11 6 18 18 18 35v19c-15-6-24-17-24-35 0-7 2-13 6-19z", "area");
    drawCircle(48, 34, 10, "area");
    drawPath("M40 28c-4-18-20-25-32-12M56 28c4-18 20-25 32-12", "line", 3.8);
  }
  ctx.restore();
}

Object.assign(window, { ResultView, RadarSVG, radarGeometry, PersonaGlyph });
