/* global React, Icon */
// Agents — the named specialists working under "Team Addy".
// Each agent has: a jurisdiction (what it watches/does), a default trust tier
// (how autonomously it acts), a visual identity (tone + glyph), and a voice
// (first-person tone of its outputs).
//
// Three agents at launch (no zoo). Coach lands later for manager-mode coaching.

const AGENTS = {
  scout: {
    id: "scout",
    name: "Scout",
    role: "Buyer signal watcher",
    voice: "Observation-first — 'I noticed …'",
    tone: "info",                  // violet — neutral signal
    accent: "oklch(0.70 0.13 280)",
    glyph: "eye",
    jurisdiction: "Reads mail / calendar / LinkedIn / CRM activity. Surfaces what changed on the buyer side.",
    defaultTier: "inform",         // inform-only by default — never sends customer-facing
    tagline: "Watches the buyer side so you don't have to.",
  },
  drafter: {
    id: "drafter",
    name: "Drafter",
    role: "Message composer",
    voice: "Proposal — 'I drafted … want to review?'",
    tone: "accent",                // ember — the doer
    accent: "oklch(0.74 0.16 55)",
    glyph: "pen",
    jurisdiction: "Picks channel, writes drafts, adapts tone. Proposes the move; never sends without consent.",
    defaultTier: "propose",        // proposes; user reviews each send
    tagline: "Composes the next move in the right channel.",
  },
  forecaster: {
    id: "forecaster",
    name: "Forecaster",
    role: "Number defender",
    voice: "Assessment — 'Evidence supports X, not Y.'",
    tone: "good",                  // green — the calibrator
    accent: "oklch(0.74 0.15 158)",
    glyph: "scale",
    jurisdiction: "Recalculates forecast through the evidence engine, raises theatre flags, builds the manager case.",
    defaultTier: "propose",        // proposes category moves; manager confirms
    tagline: "Defends the forecast with buyer evidence.",
  },
};

// Trust tier metadata — same vocabulary in every receipts/promise UI so users
// learn the ladder once and apply it everywhere.
const TRUST_TIERS = {
  inform:           { label: "Inform-only",       desc: "Surfaces signals; never acts.",                                 tone: "muted"  },
  propose:          { label: "Propose",           desc: "Drafts; you explicitly accept each send.",                       tone: "info"   },
  "send-with-window": { label: "Send (5m window)", desc: "Sends after a cancel-window; meant for low-risk / internal.",    tone: "amber"  },
  autonomous:       { label: "Autonomous",        desc: "Acts without per-action approval. Reversible, audited.",         tone: "warn"   },
};

// Map every nudge id → which agent is responsible (so existing nudges become
// agent-attributed without changing data.jsx every time we add an agent).
const NUDGE_AGENT_MAP = {
  n1: "scout",      // Linnworks repost signal
  n2: "scout",      // Champion changed jobs (LinkedIn telemetry)
  n3: "forecaster", // Procurement cleared — momentum read → forecast lift
  n4: "drafter",    // Legal redline summary — drafted output
  n5: "scout",      // Economic buyer discovery — signal mapping
};

// Map deal-level nudges (per the deal's nudges[] array) to an agent. Keyed by
// the nudge.kind string so it's resilient to data reshuffling.
const NUDGE_KIND_AGENT = {
  "GAP DETECTED":             "scout",
  "MISSING STAKEHOLDERS":     "scout",
  "MISSING APPROVAL PATH":    "scout",
  "FOLLOW-UP READY":          "drafter",
  "DRAFT READY":              "drafter",
  "FORECAST DRIFT":           "forecaster",
  "CATEGORY RECOMMENDATION":  "forecaster",
};

function agentForNudge(nudge) {
  if (!nudge) return null;
  if (nudge.agentId && AGENTS[nudge.agentId]) return AGENTS[nudge.agentId];
  if (nudge.id && NUDGE_AGENT_MAP[nudge.id])   return AGENTS[NUDGE_AGENT_MAP[nudge.id]];
  if (nudge.kind && NUDGE_KIND_AGENT[nudge.kind]) return AGENTS[NUDGE_KIND_AGENT[nudge.kind]];
  return AGENTS.scout; // default: Scout (most signals come from observation)
}

// ---------- Receipts: how/why an agent produced an output ----------
// Hand-authored mock receipts per nudge so the slide-over reads as if a real
// signal pipeline + rule engine fired. Real product would derive these from
// the agent run log.
const RECEIPTS = {
  n1: {
    agentId: "scout",
    title: "Sarah Chen reposted Linnworks",
    confidence: 0.92,
    signals: [
      { source: "LinkedIn",   text: "Sarah Chen reposted 'Linnworks 4.0 — warehouse automation' (public, 2.4k reactions).", when: "Today, 7:42 AM" },
      { source: "Gmail",      text: "Last buyer-side reply on the Atlas thread: 5 days ago (Apr 22).",                     when: "Apr 22, 4:02 PM" },
      { source: "Salesforce", text: "Atlas stage unchanged for 8 days · close date Apr 30.",                                when: "Today" },
    ],
    rules: [
      "Champion engagement with a named competitor while seller thread quiet >48h → competitive-displacement flag.",
      "If competitor is on the battlecard list AND last buyer reply >72h, escalate to warn.",
    ],
    quotes: [
      { source: "LinkedIn", author: "Sarah Chen (VP Ops · Atlas)", text: "This is the future of warehouse ops. Wish more vendors thought this way.", when: "Today, 7:42 AM" },
    ],
  },
  n2: {
    agentId: "scout",
    title: "Champion changed jobs",
    confidence: 0.96,
    signals: [
      { source: "LinkedIn", text: "Daniel Okafor updated title: 'Director of Ops, Northline Systems.'", when: "Yesterday" },
      { source: "Gmail",    text: "Daniel's @globalsolutions.com address bounced on the last follow-up.", when: "Yesterday, 6:08 PM" },
      { source: "LinkedIn", text: "Amara Nwosu promoted to 'Head of Ops, Global Solutions' — matches replacement-champion profile.", when: "Today, 9:01 AM" },
    ],
    rules: [
      "Champion title change + bounce on primary email = champion-departed flag.",
      "Replacement-champion match: same org, same function, ≤2 levels of seniority delta.",
    ],
    quotes: [],
  },
  n3: {
    agentId: "forecaster",
    title: "Procurement cleared security review",
    confidence: 0.88,
    signals: [
      { source: "Gmail",    text: "InfoSec → Procurement: 'Vendor passed security review · approved Apr 24.'", when: "Apr 24, 3:11 PM" },
      { source: "Calendar", text: "New event held: 'Acme · contracting next steps' (Procurement + Legal).",     when: "Apr 25" },
    ],
    rules: [
      "Security cleared + contracting meeting scheduled → momentum lift (buyer score +12).",
      "When buyer score crosses 70 within 14d of close, recommend 'push for verbal commit.'",
    ],
    quotes: [
      { source: "Gmail", author: "Priya R. (InfoSec, Acme)", text: "We're good on our side. Procurement has the green light.", when: "Apr 24, 3:11 PM" },
    ],
  },
  n4: {
    agentId: "drafter",
    title: "Legal review stalled 6 days",
    confidence: 0.84,
    signals: [
      { source: "Gmail",    text: "Last reply from TechStart counsel: Apr 22.",                                  when: "Apr 22" },
      { source: "Outreach", text: "3 follow-ups sent · 0 replies in 6 days.",                                    when: "Apr 22–28" },
    ],
    rules: [
      "No counsel reply >5 days during Negotiation = redline-stall flag.",
      "If redlines unresolved, propose a 1-page summary to escalate to the deal owner.",
    ],
    quotes: [],
  },
  n5: {
    agentId: "scout",
    title: "No economic buyer identified",
    confidence: 0.79,
    signals: [
      { source: "Salesforce", text: "Required field 'Economic Buyer' is empty.",                                    when: "—" },
      { source: "Gong",       text: "Discovery call (Apr 18) — Marta Singh mentioned 'I'd need to loop in finance.'", when: "Apr 18, 2:14 PM" },
    ],
    rules: [
      "Discovery complete + EB unset → finance-gap flag.",
      "Match candidate from call transcript: speaker × 'finance / budget / approver' mention.",
    ],
    quotes: [
      { source: "Gong", author: "Marta Singh (Head of Ops, StartupCo)", text: "I'd need to loop in finance on something this size — probably our CFO Dave.", when: "Apr 18, 2:14 PM" },
    ],
  },
  // Generic per-deal receipt fallback — keyed by deal.id + kind. Lets Deal
  // Detail nudges render a receipt without per-nudge id mapping.
  "atlas:GAP DETECTED": {
    agentId: "scout",
    title: "Linnworks competitive signal",
    confidence: 0.92,
    signals: [
      { source: "LinkedIn",   text: "Sarah Chen reposted Linnworks' warehouse automation launch.", when: "Today" },
      { source: "Gmail",      text: "Atlas buying thread quiet for 72h.",                          when: "—" },
    ],
    rules: ["Champion engages competitor + thread silent >48h → competitive flag."],
    quotes: [{ source: "LinkedIn", author: "Sarah Chen", text: "This is the future of warehouse ops.", when: "Today" }],
  },
};

function receiptFor(nudge, deal) {
  if (!nudge) return null;
  if (nudge.id && RECEIPTS[nudge.id]) return RECEIPTS[nudge.id];
  if (deal && nudge.kind && RECEIPTS[`${deal.id}:${nudge.kind}`])
    return RECEIPTS[`${deal.id}:${nudge.kind}`];
  // Last-resort: synth a small receipt so the panel still reads convincingly.
  const agent = agentForNudge(nudge);
  return {
    agentId: agent.id,
    title: nudge.title || "Agent output",
    confidence: 0.75,
    signals: nudge.evidence ? [{
      source: nudge.evidence.source || "Activity",
      text: nudge.evidence.detail || nudge.evidence.proof || nudge.sub || "",
      when: nudge.evidence.time || "—",
    }] : [],
    rules: nudge.sub ? [nudge.sub] : [],
    quotes: [],
  };
}

// ---------- AgentChip — inline attribution ----------
const AgentGlyph = ({ name, size = 12 }) => {
  // Simple inline SVG glyphs per agent — distinguishable without a real icon
  // library, scales with currentColor.
  const stroke = { stroke: "currentColor", strokeWidth: 1.6, fill: "none", strokeLinecap: "round", strokeLinejoin: "round" };
  if (name === "eye") {
    return (
      <svg width={size} height={size} viewBox="0 0 16 16" aria-hidden="true">
        <path {...stroke} d="M1.5 8s2.6-4.5 6.5-4.5S14.5 8 14.5 8s-2.6 4.5-6.5 4.5S1.5 8 1.5 8z" />
        <circle cx="8" cy="8" r="2" {...stroke} />
      </svg>
    );
  }
  if (name === "pen") {
    return (
      <svg width={size} height={size} viewBox="0 0 16 16" aria-hidden="true">
        <path {...stroke} d="M11.5 2.5l2 2-8 8H3.5v-2l8-8z" />
        <path {...stroke} d="M10 4l2 2" />
      </svg>
    );
  }
  if (name === "scale") {
    return (
      <svg width={size} height={size} viewBox="0 0 16 16" aria-hidden="true">
        <path {...stroke} d="M8 2v12M3 5h10M4 5L2.5 9h3L4 5zm8 0l-1.5 4h3L12 5z" />
        <path {...stroke} d="M2.5 9a1.5 1.5 0 003 0M10.5 9a1.5 1.5 0 003 0" />
      </svg>
    );
  }
  return null;
};

const AgentChip = ({ agentId, nudge, deal, onOpenReceipt, compact = false, label }) => {
  const agent = agentId
    ? AGENTS[agentId]
    : agentForNudge(nudge);
  if (!agent) return null;
  const handleClick = (e) => {
    e.stopPropagation();
    if (onOpenReceipt) {
      onOpenReceipt({ nudge, deal, agentId: agent.id });
      return;
    }
    if (typeof window !== "undefined" && window.openReceipts) {
      window.openReceipts({ nudge, deal, agentId: agent.id });
    }
  };
  return (
    <button
      type="button"
      className={`agent-chip tone-${agent.tone} ${compact ? "is-compact" : ""}`}
      onClick={handleClick}
      title={`${agent.name} · ${agent.role}. Click for receipt.`}
      aria-label={`Receipt from ${agent.name}`}
    >
      <span className="agent-chip-glyph" aria-hidden="true">
        <AgentGlyph name={agent.glyph} size={compact ? 10 : 12} />
      </span>
      <span className="agent-chip-name">{label || agent.name}</span>
      {!compact && <span className="agent-chip-why" aria-hidden="true">· why?</span>}
    </button>
  );
};

// ---------- Receipts slide-over ----------
const ReceiptsPanel = ({ payload, onClose }) => {
  React.useEffect(() => {
    if (!payload) return undefined;
    const onKey = (e) => { if (e.key === "Escape") onClose(); };
    document.addEventListener("keydown", onKey);
    return () => document.removeEventListener("keydown", onKey);
  }, [payload, onClose]);

  if (!payload) return null;
  const agent = AGENTS[payload.agentId] || agentForNudge(payload.nudge);
  const receipt = receiptFor(payload.nudge, payload.deal);
  if (!receipt) return null;
  const tier = TRUST_TIERS[agent.defaultTier];
  const confidencePct = Math.round((receipt.confidence ?? 0.75) * 100);

  return (
    <div className="receipts-back" role="dialog" aria-modal="true" aria-label={`Receipt from ${agent.name}`} onClick={onClose}>
      <aside className={`receipts-panel tone-${agent.tone}`} onClick={(e) => e.stopPropagation()}>
        <div className="receipts-accent" aria-hidden="true" />

        <div className="receipts-sticky">
          <header className="receipts-head">
            <div className="receipts-head-l">
              <span className={`agent-avatar lg tone-${agent.tone}`}>
                <AgentGlyph name={agent.glyph} size={20} />
              </span>
              <div className="receipts-head-text">
                <b>{agent.name}</b>
                <em>{agent.role}</em>
                <span className="receipts-jurisdiction">{agent.jurisdiction}</span>
              </div>
            </div>
            <button type="button" className="receipts-close" onClick={onClose} aria-label="Close receipt">
              <Icon name="close" size={14} />
            </button>
          </header>

          <div className="receipts-meta-block">
            <div className="receipts-meta">
              <span className={`chip tone-${tier.tone}`} title={tier.desc}>{tier.label}</span>
              {payload.deal && (
                <span className="receipts-deal-tag">
                  <Icon name="target" size={11} />
                  <b>{payload.deal.company}</b>
                </span>
              )}
            </div>
            <div className="receipts-confidence" role="meter" aria-valuenow={confidencePct} aria-valuemin={0} aria-valuemax={100} aria-label="Confidence">
              <div className="receipts-confidence-label">
                <em>Confidence</em>
                <b className="mono">{confidencePct}%</b>
              </div>
              <div className="receipts-confidence-bar">
                <span className={`receipts-confidence-fill tone-${agent.tone}`} style={{ width: `${confidencePct}%` }} />
              </div>
            </div>
          </div>
        </div>

        <div className="receipts-body">
          <div className="receipts-title">
            <em className="cp-eyebrow"><span className={`cp-eyebrow-dot ${agent.tone}`} /> Why I did this</em>
            <h3 className="h3">{receipt.title}</h3>
          </div>

          <section className="receipts-section">
            <header className="receipts-section-h">
              <em className="cp-eyebrow">Signals consumed</em>
              <span className="receipts-section-count">{receipt.signals.length}</span>
            </header>
            {receipt.signals.length === 0 && <p className="muted small receipts-empty">No signals attached.</p>}
            {receipt.signals.map((s, i) => (
              <div key={i} className="receipts-signal">
                <div className="receipts-signal-h">
                  <span className="receipts-source">{s.source}</span>
                  <em className="receipts-signal-when">{s.when}</em>
                </div>
                <p>{s.text}</p>
              </div>
            ))}
          </section>

          <section className="receipts-section">
            <header className="receipts-section-h">
              <em className="cp-eyebrow">Rules fired</em>
              <span className="receipts-section-count">{receipt.rules.length}</span>
            </header>
            {receipt.rules.length === 0 && <p className="muted small receipts-empty">No rules fired.</p>}
            <ul className="receipts-rules">
              {receipt.rules.map((r, i) => (
                <li key={i} className={`receipts-rule tone-${agent.tone}`}>{r}</li>
              ))}
            </ul>
          </section>

          {receipt.quotes.length > 0 && (
            <section className="receipts-section">
              <header className="receipts-section-h">
                <em className="cp-eyebrow">Source quotes</em>
                <span className="receipts-section-count">{receipt.quotes.length}</span>
              </header>
              {receipt.quotes.map((q, i) => (
                <blockquote key={i} className={`receipts-quote tone-${agent.tone}`}>
                  <p>{q.text}</p>
                  <em>— {q.author} · {q.source} · {q.when}</em>
                </blockquote>
              ))}
            </section>
          )}
        </div>

        <footer className="receipts-foot">
          <div className="receipts-foot-actions">
            <button type="button" className="btn sm primary">
              <Icon name="check" size={12} /> Looks right
            </button>
            <button type="button" className="btn sm ghost">
              <Icon name="bolt" size={12} /> Correct {agent.name}
            </button>
          </div>
          <span className="receipts-foot-note">Teaching feedback updates the rule, not just this output.</span>
        </footer>
      </aside>
    </div>
  );
};

// ---------- Global mount ----------
window.AGENTS         = AGENTS;
window.TRUST_TIERS    = TRUST_TIERS;
window.agentForNudge  = agentForNudge;
window.receiptFor     = receiptFor;
window.AgentChip      = AgentChip;
window.AgentGlyph     = AgentGlyph;
window.ReceiptsPanel  = ReceiptsPanel;
