/* global React, PR */
const { useState, useMemo } = React;
const { I, Avatar } = PR;

const EVAL_STAGES = ["idea", "greybox", "prototype", "coldtest"];

// =================================================================
// Radar / Spider Chart — pure SVG, follows the registry's visual system
// =================================================================
function Radar({ axes, polygons, size = 360 }) {
  // Wheel itself is square (size × size). Extend the SVG viewBox horizontally
  // to give right/left label gutters so long labels never clip the panel.
  const sideGutter = 110;
  const totalW = size + sideGutter * 2;
  const wheelR = size / 2 - 12;
  const cx = sideGutter + size / 2, cy = size / 2;
  const r = wheelR;
  const N = axes.length;
  const angle = (i) => -Math.PI / 2 + (i / N) * Math.PI * 2;
  const point = (i, value) => {
    const a = angle(i);
    const rr = r * (value / 10);
    return [cx + Math.cos(a) * rr, cy + Math.sin(a) * rr];
  };
  const ringValues = [2, 4, 6, 8, 10];

  const polygonPath = (scores) => {
    return axes.map((ax, i) => {
      const v = scores[ax.id] ?? 0;
      const [x, y] = point(i, v);
      return `${i === 0 ? "M" : "L"}${x.toFixed(1)},${y.toFixed(1)}`;
    }).join(" ") + " Z";
  };

  return (
    <svg
      className="ev-radar"
      viewBox={`0 0 ${totalW} ${size}`}
      preserveAspectRatio="xMidYMid meet"
      width="100%"
      style={{ maxWidth: totalW, height: "auto" }}
    >
      {ringValues.map((v) => (
        <polygon
          key={v}
          className="ev-radar-ring"
          points={axes.map((_, i) => point(i, v).map(n => n.toFixed(1)).join(",")).join(" ")}
        />
      ))}
      {axes.map((_, i) => {
        const [x, y] = point(i, 10);
        return <line key={i} className="ev-radar-spoke" x1={cx} y1={cy} x2={x} y2={y} />;
      })}
      {polygons.map((p) => (
        <g key={p.key} className={`ev-radar-poly ev-radar-poly-${p.kind}`}>
          <path d={polygonPath(p.scores)} />
          {p.kind === "you" && axes.map((ax, i) => {
            const [x, y] = point(i, p.scores[ax.id] ?? 0);
            return <circle key={ax.id} cx={x} cy={y} r="3" />;
          })}
        </g>
      ))}
      {axes.map((ax, i) => {
        const a = angle(i);
        const lx = cx + Math.cos(a) * (r + 14);
        const ly = cy + Math.sin(a) * (r + 14);
        const cosA = Math.cos(a);
        const anchor = Math.abs(cosA) < 0.25 ? "middle" : (cosA > 0 ? "start" : "end");
        return (
          <text key={ax.id} x={lx} y={ly} textAnchor={anchor} dominantBaseline="middle" className="ev-radar-label">
            {ax.label}
          </text>
        );
      })}
      {ringValues.map(v => {
        const [, y] = point(0, v);
        return <text key={v} x={cx + 4} y={y + 3} className="ev-radar-num">{v}</text>;
      })}
    </svg>
  );
}

// =================================================================
// Vote view — independent scoring sliders
// =================================================================
function VoteView({ draft, onChange, onSubmit, votersCount, alreadySubmitted }) {
  const groups = window.EVALUATOR_DATA.groups;
  const totalAxes = groups.reduce((n, g) => n + g.axes.length, 0);
  const filled = Object.values(draft || {}).filter(v => v != null).length;
  const complete = filled === totalAxes;

  return (
    <div className="ev-vote">
      <div className="ev-vote-head">
        <div>
          <div className="ev-vote-title">Independent evaluation</div>
          <div className="ev-vote-sub">
            Score 1–10 on each criterion. Your scores are hidden from the team until you submit.
            {votersCount > 0 && ` ${votersCount} ${votersCount === 1 ? "teammate has" : "teammates have"} already voted.`}
          </div>
        </div>
        <div className="ev-progress">
          <div className="ev-progress-bar">
            <div className="ev-progress-fill" style={{ width: `${(filled / totalAxes) * 100}%` }}></div>
          </div>
          <div className="ev-progress-label mono">{filled} / {totalAxes}</div>
        </div>
      </div>

      <div className="ev-groups">
        {groups.map(g => (
          <div key={g.id} className="ev-group">
            <div className="ev-group-head">
              <div className="ev-group-label">{g.label}</div>
              <div className="ev-group-sub">{g.sub}</div>
            </div>
            <div className="ev-group-axes">
              {g.axes.map(ax => {
                const v = draft?.[ax.id] ?? null;
                return (
                  <div key={ax.id} className="ev-axis-row">
                    <div className="ev-axis-text">
                      <div className="ev-axis-label">
                        {ax.label}
                        {ax.examples && (
                          <span className="ev-axis-help" tabIndex="0" aria-label="Scoring examples">
                            <span className="ev-axis-help-glyph">?</span>
                            <span className="ev-axis-help-pop" role="tooltip">
                              <span className="ev-axis-help-row">
                                <span className="ev-axis-help-tag ev-tag-high mono">10</span>
                                <span className="ev-axis-help-text">{ax.examples.high}</span>
                              </span>
                              <span className="ev-axis-help-row">
                                <span className="ev-axis-help-tag ev-tag-low mono">1</span>
                                <span className="ev-axis-help-text">{ax.examples.low}</span>
                              </span>
                            </span>
                          </span>
                        )}
                      </div>
                      <div className="ev-axis-hint">{ax.hint}</div>
                    </div>
                    <div className="ev-slider-wrap">
                      <input
                        type="range"
                        min="1" max="10" step="1"
                        value={v ?? 5}
                        onChange={(e) => onChange(ax.id, parseInt(e.target.value, 10))}
                        className={`ev-slider ${v == null ? "ev-slider-untouched" : ""}`}
                      />
                      <div className="ev-slider-ticks">
                        {[1,2,3,4,5,6,7,8,9,10].map(n => <span key={n}>{n === 1 || n === 10 ? n : ""}</span>)}
                      </div>
                    </div>
                    <div className={`ev-axis-score mono ${v == null ? "muted" : ""}`}>
                      {v == null ? "—" : v}
                    </div>
                  </div>
                );
              })}
            </div>
          </div>
        ))}
      </div>

      <div className="ev-vote-foot">
        <div className="ev-vote-foot-text">
          {alreadySubmitted
            ? "You already submitted a vote on this idea. Updating will overwrite your previous scores."
            : complete
              ? "All criteria scored. You're ready to submit."
              : `Score the remaining ${totalAxes - filled} criteria to submit.`
          }
        </div>
        <button
          className="btn btn-primary ev-submit"
          disabled={!complete}
          onClick={onSubmit}
        >
          {I.check}<span>Submit score &amp; view report</span>
        </button>
      </div>
    </div>
  );
}

// =================================================================
// Report view — radar, strengths/weaknesses, AI assistant
// =================================================================
function ReportView({ hypothesis, axes, teamAvg, yourScores, voters }) {
  const polygons = [
    { key: "team", kind: "team", scores: teamAvg },
    ...(yourScores ? [{ key: "you", kind: "you", scores: yourScores }] : []),
  ];

  const sortedAxes = axes.slice().sort((a, b) => (teamAvg[b.id] ?? 0) - (teamAvg[a.id] ?? 0));
  const strengths = sortedAxes.filter(ax => (teamAvg[ax.id] ?? 0) >= 7.5).slice(0, 3);
  const weaknesses = sortedAxes.slice().reverse().filter(ax => (teamAvg[ax.id] ?? 0) <= 5.5).slice(0, 3);

  const overall = (axes.reduce((sum, ax) => sum + (teamAvg[ax.id] ?? 0), 0) / axes.length);

  const groupAvgs = window.EVALUATOR_DATA.groups.map(g => {
    const sum = g.axes.reduce((s, ax) => s + (teamAvg[ax.id] ?? 0), 0);
    return { id: g.id, label: g.label, avg: sum / g.axes.length };
  });

  const aiInsights = useMemo(
    () => buildInsights(hypothesis, teamAvg, axes),
    [hypothesis.id, JSON.stringify(teamAvg)],
  );

  return (
    <div className="ev-report">
      <div className="ev-report-grid">
        <div className="panel ev-radar-panel">
          <div className="ev-radar-head">
            <div>
              <h3>Score profile</h3>
              <p className="panel-sub">Overlay of your evaluation against the team average across {axes.length} criteria.</p>
            </div>
            <div className="ev-radar-legend">
              <div className="ev-legend-row"><span className="ev-legend-swatch ev-legend-team"></span>Team average</div>
              {yourScores && <div className="ev-legend-row"><span className="ev-legend-swatch ev-legend-you"></span>Your score</div>}
            </div>
          </div>
          <div className="ev-radar-wrap">
            <Radar axes={axes} polygons={polygons} size={380} />
          </div>
          <div className="ev-radar-foot">
            <div className="ev-overall">
              <div className="ev-overall-label">Consolidated score</div>
              <div className="ev-overall-value mono">{overall.toFixed(1)}<span className="ev-overall-max">/10</span></div>
            </div>
            <div className="ev-group-avgs">
              {groupAvgs.map(ga => (
                <div key={ga.id} className="ev-group-avg">
                  <div className="ev-group-avg-label">{ga.label}</div>
                  <div className="ev-group-avg-value mono">{ga.avg.toFixed(1)}</div>
                </div>
              ))}
            </div>
          </div>
        </div>

        <div className="panel ev-voters-panel">
          <h3>Evaluated by</h3>
          <p className="panel-sub">{voters.length} {voters.length === 1 ? "person has" : "people have"} submitted independent scores.</p>
          <div className="ev-voters">
            <div className="ev-voters-stack">
              {voters.slice(0, 6).map(v => (
                <div key={v.id} className="ev-voter-avatar" title={v.name}>
                  <Avatar author={v} />
                </div>
              ))}
            </div>
            <div className="ev-voters-names">
              {voters.length === 0
                ? "No teammate scores yet."
                : voters.length <= 3
                  ? voters.map(v => v.name).join(", ")
                  : `${voters.slice(0, 2).map(v => v.name).join(", ")} and ${voters.length - 2} others`}
            </div>
          </div>

          <div className="ev-voter-divider"></div>

          <div className="ev-tags-block">
            <div className="ev-tags-label">{I.check}<span>Strengths</span></div>
            <div className="ev-tag-row">
              {strengths.length === 0 && <span className="ev-tag-empty">No criteria scored ≥ 7.5 yet.</span>}
              {strengths.map(ax => (
                <span key={ax.id} className="ev-tag ev-tag-good">
                  {ax.label}<span className="mono ev-tag-num">{(teamAvg[ax.id] ?? 0).toFixed(1)}</span>
                </span>
              ))}
            </div>
          </div>

          <div className="ev-tags-block">
            <div className="ev-tags-label ev-tags-label-warn">{I.flag}<span>Weaknesses</span></div>
            <div className="ev-tag-row">
              {weaknesses.length === 0 && <span className="ev-tag-empty">No criteria scored ≤ 5.5.</span>}
              {weaknesses.map(ax => (
                <span key={ax.id} className="ev-tag ev-tag-bad">
                  {ax.label}<span className="mono ev-tag-num">{(teamAvg[ax.id] ?? 0).toFixed(1)}</span>
                </span>
              ))}
            </div>
          </div>
        </div>
      </div>

      <div className="panel ev-ai-panel">
        <div className="ev-ai-head">
          <div className="ev-ai-mark">AI</div>
          <div>
            <h3 style={{ margin: 0 }}>R&amp;D Lab Assistant</h3>
            <p className="panel-sub" style={{ margin: "2px 0 0" }}>Actionable recommendations generated from the lowest-scoring axes.</p>
          </div>
        </div>
        <div className="ev-ai-body">
          {aiInsights.map((ins, i) => (
            <div key={i} className={`ev-ai-card ev-ai-${ins.tone}`}>
              <div className="ev-ai-card-head">
                <span className="ev-ai-axis">{ins.axis}</span>
                <span className="mono ev-ai-score">{ins.score.toFixed(1)}/10</span>
              </div>
              <div className="ev-ai-card-body">{ins.body}</div>
              {ins.suggestion && (
                <div className="ev-ai-suggestion">
                  <span className="ev-ai-suggestion-label">Suggestion</span>
                  <span>{ins.suggestion}</span>
                </div>
              )}
            </div>
          ))}
        </div>
        <div className="ev-ai-foot">
          <button className="btn">{I.arrow}<span>Suggest iteration</span></button>
          <button className="btn btn-primary">{I.check}<span>Approve for prototyping</span></button>
        </div>
      </div>
    </div>
  );
}

function buildInsights(hypothesis, teamAvg, axes) {
  const recipes = {
    three_sec: {
      tone: "warn",
      body: "Players don't read the core action within the first three seconds. That's the hyper-casual death zone — drop-off before the first feedback loop fires.",
      suggestion: "Simplify the visual language: strong color contrast on the interactable, hide most UI on first run, and make the core action a single swipe or tap.",
    },
    playable_ad: {
      tone: "warn",
      body: "Translating the loop into a 15-second playable creative looks expensive. Without that, paid UA can't validate at scale.",
      suggestion: "Identify a 5-second 'wow' moment and storyboard a creative around just that beat — even if it skips the meta layer entirely.",
    },
    one_screen: {
      tone: "warn",
      body: "The loop currently spans multiple screens. Test cycles will be slow and signal will be noisy.",
      suggestion: "Compress the entire core loop onto one screen for the greybox build. Save navigation for after the prototype gate.",
    },
    ltv: {
      tone: "info",
      body: "Meta depth scored low. The game can hook but may not retain past D7 without more economy or progression hooks.",
      suggestion: "Sketch the second-week loop now — what does the player chase on day 8? Define currencies and unlock cadence before scale.",
    },
    viral: {
      tone: "info",
      body: "Shareability is below threshold. Without organic creators, paid UA absorbs the entire growth budget.",
      suggestion: "Add one moment per session that a player would film: a slow-mo, a chain reaction, an unexpected fail state.",
    },
    satisfying: {
      tone: "info",
      body: "The core action lacks tactile satisfaction. The metric most strongly correlated with D1 retention in our archive.",
      suggestion: "Pass the build to audio next sprint. Layered SFX, screen shake, and chunky particles before more features.",
    },
    ai_assets: {
      tone: "info",
      body: "Asset pipeline isn't AI-friendly — the genre or art direction blocks generative tools.",
      suggestion: "Consider a stylization pass: low-poly, flat-shaded, or hand-drawn looks reduce iteration cost dramatically.",
    },
    innovation: {
      tone: "info",
      body: "The team rates this as familiar. That's not necessarily bad, but it sets a high bar for execution polish.",
      suggestion: "Double down on a single distinguishing element. If you can't name it in one sentence, the player can't either.",
    },
    positioning: {
      tone: "info",
      body: "Positioning is unclear — the team can't predict why a player would download this over a closest comp.",
      suggestion: "Write the App Store subtitle now (max 30 chars). If three teammates write three different subtitles, the concept needs sharpening.",
    },
  };

  const sorted = axes.slice().sort((a, b) => (teamAvg[a.id] ?? 0) - (teamAvg[b.id] ?? 0));
  const out = [];
  for (const ax of sorted) {
    if (out.length >= 2) break;
    const score = teamAvg[ax.id] ?? 0;
    if (score >= 6.5) break;
    const r = recipes[ax.id];
    if (r) out.push({ axis: ax.label, score, ...r });
  }

  const sortedDesc = axes.slice().sort((a, b) => (teamAvg[b.id] ?? 0) - (teamAvg[a.id] ?? 0));
  const top = sortedDesc[0];
  if (top && (teamAvg[top.id] ?? 0) >= 8) {
    out.push({
      axis: top.label,
      score: teamAvg[top.id],
      tone: "good",
      body: `${top.label} scored highest across the team — this is the load-bearing pillar of the pitch.`,
      suggestion: "Build the next prototype iteration around amplifying this. Cut anything that distracts from it.",
    });
  }

  if (out.length === 0) {
    out.push({
      axis: "Overall",
      score: axes.reduce((s, ax) => s + (teamAvg[ax.id] ?? 0), 0) / axes.length,
      tone: "info",
      body: "Scores are middling across the board — no single weakness, but no breakout signal either.",
      suggestion: "Schedule a half-day pitch revision. Pick one criterion and aim for a 9 on it specifically.",
    });
  }

  return out;
}

// =================================================================
// Container — switches between Vote and Report
// =================================================================
function EvaluatorView({ data }) {
  const evalData = window.EVALUATOR_DATA;

  // Build the candidate list: real hypotheses in evaluable stages, ordered by
  // the pinned list first (mock votes refer to those), then the rest.
  const evaluable = useMemo(() => {
    const all = data.hypotheses.filter(h => EVAL_STAGES.includes(h.stage));
    const pinIndex = new Map(evalData.evaluable.map((id, i) => [id, i]));
    return all.slice().sort((a, b) => {
      const ai = pinIndex.has(a.id) ? pinIndex.get(a.id) : Infinity;
      const bi = pinIndex.has(b.id) ? pinIndex.get(b.id) : Infinity;
      if (ai !== bi) return ai - bi;
      return (b.updated || "").localeCompare(a.updated || "");
    });
  }, [data.hypotheses]);

  const [selectedId, setSelectedId] = useState(evaluable[0]?.id || null);
  const [tab, setTab]               = useState("vote");
  const [drafts, setDrafts]         = useState(() => {
    const seed = {};
    Object.entries(evalData.drafts || {}).forEach(([id, d]) => { seed[id] = d ? { ...d } : {}; });
    return seed;
  });
  const [submittedSet, setSubmittedSet] = useState(() => new Set(evalData.submitted));

  // Author map: real authors merged with synthetic mock voter authors so
  // avatars / names resolve for the pre-baked teammate votes.
  const authorMap = useMemo(() => {
    const m = Object.fromEntries(data.authors.map(a => [a.id, a]));
    (evalData.voterAuthors || []).forEach(a => { if (!m[a.id]) m[a.id] = a; });
    return m;
  }, [data.authors]);

  const hypothesis = evaluable.find(h => h.id === selectedId) || null;
  const author     = hypothesis ? authorMap[hypothesis.author] : null;

  const axes = useMemo(() => evalData.groups.flatMap(g => g.axes), []);

  const allVotes  = evalData.votes.filter(v => v.h === selectedId);
  const teamVotes = allVotes.filter(v => v.v !== evalData.currentVoter);
  const voterIds  = [...new Set(teamVotes.map(v => v.v))];
  const voters    = voterIds.map(id => authorMap[id]).filter(Boolean);

  const teamAvg = useMemo(() => {
    const out = {};
    axes.forEach(ax => {
      const vals = teamVotes.map(v => v.s[ax.id]).filter(n => typeof n === "number");
      out[ax.id] = vals.length ? vals.reduce((a, b) => a + b, 0) / vals.length : 0;
    });
    return out;
  }, [selectedId]);

  const draft = drafts[selectedId] || {};
  const alreadySubmitted = submittedSet.has(selectedId);
  const yourScores = alreadySubmitted ? draft : null;

  const handleChange = (axisId, value) => {
    setDrafts(prev => ({ ...prev, [selectedId]: { ...(prev[selectedId] || {}), [axisId]: value } }));
  };

  const handleSubmit = () => {
    setSubmittedSet(prev => new Set([...prev, selectedId]));
    setTab("report");
  };

  const handleSelect = (id) => {
    setSelectedId(id);
    setTab(submittedSet.has(id) ? "report" : "vote");
  };

  if (!hypothesis) return <div className="empty-hint">No hypotheses to evaluate.</div>;

  return (
    <div className="ev-wrap">
      <aside className="ev-rail">
        <div className="ev-rail-head">
          <div className="nav-section-title" style={{ padding: "0 0 6px" }}>Pitches awaiting evaluation</div>
        </div>
        <div className="ev-rail-list">
          {evaluable.map(h => {
            const a = authorMap[h.author];
            const submitted = submittedSet.has(h.id);
            const draftFilled = drafts[h.id] && Object.keys(drafts[h.id]).length > 0;
            const otherVoters = new Set(
              evalData.votes.filter(v => v.h === h.id && v.v !== evalData.currentVoter).map(v => v.v),
            ).size;
            return (
              <div
                key={h.id}
                className={`ev-rail-item ${selectedId === h.id ? "active" : ""}`}
                onClick={() => handleSelect(h.id)}
              >
                <div className="ev-rail-item-head">
                  <span className="cell-id">{h.id}</span>
                  {submitted && <span className="ev-rail-badge submitted">{I.check}<span>Voted</span></span>}
                  {!submitted && draftFilled && <span className="ev-rail-badge draft">Draft</span>}
                </div>
                <div className="ev-rail-item-title">{h.title}</div>
                <div className="ev-rail-item-foot">
                  <Avatar author={a} />
                  <span className="ev-rail-item-meta">
                    {otherVoters > 0 ? `${otherVoters} ${otherVoters === 1 ? "vote" : "votes"}` : "No votes yet"}
                  </span>
                </div>
              </div>
            );
          })}
        </div>
      </aside>

      <section className="ev-main">
        <header className="ev-pitch-head">
          <div className="ev-pitch-head-top">
            <div>
              <div className="passport-id">
                <span className="mono">{hypothesis.id}</span>
                <span> · </span>
                <span>Pitched by {author?.name || "—"}</span>
              </div>
              <h2 className="ev-pitch-title">{hypothesis.title}</h2>
            </div>
            <div className="ev-pitch-stats">
              <div className="ev-pitch-stat">
                <div className="ev-pitch-stat-label">Voters</div>
                <div className="ev-pitch-stat-value mono">{voterIds.length + (alreadySubmitted ? 1 : 0)}</div>
              </div>
              <div className="ev-pitch-stat">
                <div className="ev-pitch-stat-label">Tags</div>
                <div className="tag-row" style={{ marginTop: 2 }}>
                  {(hypothesis.tags || []).map(t => <span key={t} className="tag">{t}</span>)}
                </div>
              </div>
            </div>
          </div>
          {hypothesis.coreLoop && <p className="ev-pitch-loop">{hypothesis.coreLoop}</p>}
        </header>

        <div className="ev-tabs">
          <button className={tab === "vote" ? "active" : ""} onClick={() => setTab("vote")}>
            <span>Evaluate</span>
            {alreadySubmitted && <span className="ev-tab-status">submitted</span>}
          </button>
          <button
            className={tab === "report" ? "active" : ""}
            onClick={() => setTab("report")}
            disabled={voterIds.length === 0 && !alreadySubmitted}
          >
            <span>Report</span>
            <span className="ev-tab-count mono">{voterIds.length + (alreadySubmitted ? 1 : 0)}</span>
          </button>
        </div>

        <div className="ev-content">
          {tab === "vote" ? (
            <VoteView
              draft={draft}
              onChange={handleChange}
              onSubmit={handleSubmit}
              votersCount={voterIds.length}
              alreadySubmitted={alreadySubmitted}
            />
          ) : (
            <ReportView
              hypothesis={hypothesis}
              axes={axes}
              teamAvg={teamAvg}
              yourScores={yourScores}
              voters={voters}
            />
          )}
        </div>
      </section>
    </div>
  );
}

window.PREvaluator = { EvaluatorView };
