// Promises tab — scorecard + promise list with status badges.
// "Reversed" promises get a Promise-vs-Vote red flag callout.

const PROMISE_STATUSES = {
  kept:         { label: "Kept",        color: "#0F6E47", soft: "#DCEFE3", icon: "✓", order: 4 },
  "in-progress":{ label: "In progress", color: "#5C7A14", soft: "#E3ECC5", icon: "~", order: 3 },
  stalled:      { label: "Stalled",     color: "#6E5A14", soft: "#F4ECCB", icon: "—", order: 2 },
  broken:       { label: "Broken",      color: "#B07A1A", soft: "#F4E6B8", icon: "✗", order: 1 },
  reversed:     { label: "Reversed",    color: "#A93232", soft: "#F4E3E3", icon: "⚑", order: 0 },
};

function TabPromises({ p, onPickBill, scope, onScope }) {
  const promises = p.promises || [];
  if (promises.length === 0) {
    return (
      <section>
        <SectionHead title="Promises tracker" sub="Promises this politician has made — and what they did about them." />
        <EmptyState
          text="No promises have been documented yet for this politician."
          detail="ClarionVote staff manually source promises from campaign websites, debates, and press statements. Each promise must have a primary source link before it goes live."
        />
      </section>
    );
  }

  // Sort: reversed first, then broken, stalled, in-progress, kept
  const sorted = [...promises].sort((a, b) => {
    return PROMISE_STATUSES[a.status].order - PROMISE_STATUSES[b.status].order;
  });

  const counts = promises.reduce((acc, pr) => {
    acc[pr.status] = (acc[pr.status] || 0) + 1;
    return acc;
  }, {});

  return (
    <section>
      <SectionHead
        title="Promises tracker"
        sub={<>What they said they'd do — and what they did about it. Sources are linked for both sides.</>}
        right={<SourceButton label="Methodology · campaign sources" />}
      />
      {onScope && <ScopeToggle scope={scope} onChange={onScope} hint={scope === "career" ? "Every promise from every campaign · no expiration" : "Promises from the current term"}/>}
      <PromiseScorecard counts={counts} total={promises.length}/>
      <h4 className="cv-h4">
        <span>All promises</span>
        <span className="cv-h4-sub">{promises.length} tracked</span>
      </h4>
      <div className="cv-prom-list">
        {sorted.map((pr, i) => (
          <PromiseRow key={i} promise={pr} onPickBill={onPickBill}/>
        ))}
      </div>
      <div className="cv-prom-foot">
        <SourceIcon/>
        Promises are documented by ClarionVote editors from primary sources only — campaign sites, official statements,
        debate transcripts, and archived social posts. <a className="cv-link" href="#" onClick={(e) => e.preventDefault()}>Submit a missing promise →</a>
      </div>
    </section>
  );
}

function PromiseScorecard({ counts, total }) {
  const order = ["kept", "in-progress", "stalled", "broken", "reversed"];
  return (
    <div className="cv-prom-score">
      <div className="cv-prom-score-bar" role="img" aria-label="Promise status breakdown">
        {order.map((k) => {
          const n = counts[k] || 0;
          if (n === 0) return null;
          const meta = PROMISE_STATUSES[k];
          return (
            <span
              key={k}
              className={`cv-prom-score-seg cv-prom-seg-${k}`}
              style={{ width: `${(n / total) * 100}%`, background: meta.color }}
              title={`${n} ${meta.label}`}
            >
              {n / total > 0.08 && <span className="cv-prom-score-seg-l">{n}</span>}
            </span>
          );
        })}
      </div>
      <div className="cv-prom-score-legend">
        {order.map((k) => {
          const n = counts[k] || 0;
          const meta = PROMISE_STATUSES[k];
          return (
            <div key={k} className={`cv-prom-score-tag cv-prom-tag-${k}`}>
              <span className="cv-prom-score-tag-d" style={{ background: meta.color }}/>
              <span className="cv-prom-score-tag-l">{meta.label}</span>
              <span className="cv-prom-score-tag-n">{n}</span>
            </div>
          );
        })}
      </div>
    </div>
  );
}

function PromiseRow({ promise, onPickBill }) {
  const [open, setOpen] = React.useState(promise.status === "reversed"); // reversed default expanded
  const meta = PROMISE_STATUSES[promise.status];

  // Years between promise made and the contradicting vote
  const yearsApart = (() => {
    if (promise.status !== "reversed" || !promise.vote || !promise.source) return null;
    const a = new Date(promise.source.date).getFullYear();
    const b = new Date(promise.vote.date).getFullYear();
    if (isNaN(a) || isNaN(b)) return null;
    return b - a;
  })();
  return (
    <article className={`cv-prom cv-prom-${promise.status} ${open ? "is-open" : ""}`}>
      <button type="button" className="cv-prom-hd" onClick={() => setOpen(o => !o)} aria-expanded={open}>
        {promise.status === "reversed" && (
          <span className="cv-prom-flag" aria-label="Promise vs vote conflict">🚩</span>
        )}
        <span className={`cv-prom-badge cv-prom-badge-${promise.status}`} style={{ color: meta.color, background: meta.soft }}>
          <span className="cv-prom-badge-i">{meta.icon}</span>
          {meta.label}
        </span>
        <div className="cv-prom-text">"{promise.text}"</div>
        <div className="cv-prom-issues">
          {(promise.issues || []).map((iss) => (
            <span key={iss} className="cv-prom-issue">{iss}</span>
          ))}
        </div>
        <span className="cv-prom-chevron" aria-hidden="true">{open ? "▾" : "▸"}</span>
      </button>

      {open && (
        <div className="cv-prom-body">
          <div className="cv-prom-source-row">
            <span className="cv-prom-row-l">Said</span>
            <div className="cv-prom-row-v">
              <span className="cv-prom-src-where">{promise.source.what}</span>
              <span className="cv-prom-src-date">{fmtDate(promise.source.date)}</span>
              <SourceLink label="archived source" href={promise.source.href}/>
            </div>
          </div>

          {promise.status === "reversed" && promise.vote && (
            <div className="cv-prom-conflict">
              <div className="cv-prom-conflict-hd">
                <span className="cv-prom-flag-lg">🚩</span>
                <span className="cv-prom-conflict-l">Promise vs vote conflict</span>
                {yearsApart != null && yearsApart > 0 && (
                  <span className="cv-prom-years-apart">{yearsApart} year{yearsApart === 1 ? "" : "s"} apart</span>
                )}
              </div>
              <div className="cv-prom-conflict-grid">
                <div className="cv-prom-conflict-row">
                  <span className="cv-prom-conflict-side">Promised</span>
                  <span className="cv-prom-conflict-body">
                    "{promise.text}"
                    <span className="cv-prom-conflict-when">— {promise.source.what}</span>
                  </span>
                </div>
                <div className="cv-prom-conflict-row">
                  <span className="cv-prom-conflict-side cv-prom-conflict-side-vote">Voted</span>
                  <span className="cv-prom-conflict-body">
                    <strong>{promise.vote.position}</strong> on{" "}
                    <button className="cv-link-bill" onClick={() => onPickBill && onPickBill(promise.vote.bill)}>
                      <span style={{ textDecoration: "underline", textDecorationColor: "var(--cv-accent)", textUnderlineOffset: "3px" }}>
                        {promise.vote.bill}
                      </span>
                    </button>{" "}
                    — {promise.vote.title}
                    {promise.vote.impact && (
                      <span className="cv-prom-conflict-when">{promise.vote.impact}</span>
                    )}
                  </span>
                </div>
              </div>
              <div className="cv-prom-conflict-foot">
                <SourceLink label="bill text" />
                <SourceLink label="vote record" />
                <span className="cv-prom-conflict-cav">
                  ClarionVote states the promise (sourced) and the vote (sourced). You decide what it means.
                </span>
              </div>
            </div>
          )}

          <div className="cv-prom-evidence">
            <div className="cv-prom-row-l">Evidence</div>
            <ul className="cv-prom-ev-list">
              {(promise.evidence || []).map((ev, i) => (
                <li key={i} className="cv-prom-ev">
                  <span className="cv-prom-ev-bullet">·</span>
                  <span className="cv-prom-ev-what">{ev.what}</span>
                  <SourceLink label="" href={ev.href}/>
                </li>
              ))}
            </ul>
          </div>
        </div>
      )}
    </article>
  );
}

Object.assign(window, { TabPromises, PROMISE_STATUSES });
