// Shared components for Solutions UI

const { useState, useEffect, useMemo, useRef } = React;

// Split merge button with "Merge" + "Merge behind flag" dropdown
const MergeButton = ({ merged, onMerge, size = "sm" }) => {
  const [open, setOpen] = useState(false);
  const [mode, setMode] = useState(null); // null | "main" | "flag"
  useEffect(() => {
    if (!open) return;
    const close = () => setOpen(false);
    window.addEventListener("click", close);
    return () => window.removeEventListener("click", close);
  }, [open]);
  const sm = size === "sm";
  const merge = (m, e) => {
    e.stopPropagation();
    if (merged) return;
    setMode(m);
    onMerge && onMerge(m);
    setOpen(false);
  };
  const label = merged
    ? (mode === "flag" ? "✓ Behind flag" : "✓ Merged")
    : "Merge";
  return (
    <span className="merge-split" style={{ display: "inline-flex", position: "relative" }} onClick={(e) => e.stopPropagation()}>
      <button
        className={"inline-merge" + (merged ? " merged" : "")}
        onClick={(e) => merge("main", e)}
        disabled={merged}
        style={{ borderTopRightRadius: 0, borderBottomRightRadius: 0, ...(sm ? {} : { fontSize: 13, padding: "7px 14px" }) }}
      >
        {label}
      </button>
      <button
        className={"inline-merge" + (merged ? " merged" : "")}
        onClick={(e) => { e.stopPropagation(); if (!merged) setOpen(o => !o); }}
        disabled={merged}
        title="More merge options"
        style={{ borderTopLeftRadius: 0, borderBottomLeftRadius: 0, borderLeft: "1px solid rgba(255,255,255,0.22)", padding: sm ? "5px 7px" : "7px 9px" }}
      >
        <span style={{ fontSize: 9 }}>▾</span>
      </button>
      {open && !merged && (
        <div style={{ position: "absolute", top: "calc(100% + 4px)", right: 0, background: "#fff", border: "1px solid #e6dfd0", borderRadius: 6, boxShadow: "0 8px 24px rgba(0,0,0,0.08)", zIndex: 20, minWidth: 200, padding: 4 }}>
          <button onClick={(e) => merge("main", e)} style={{ display: "block", width: "100%", textAlign: "left", padding: "7px 10px", border: "none", background: "transparent", fontSize: 12.5, color: "#3a3d4a", borderRadius: 4, cursor: "pointer", fontFamily: "inherit" }}>
            <div style={{ fontWeight: 600 }}>Merge to main</div>
            <div style={{ fontSize: 11, color: "#8a8d99" }}>Ship now</div>
          </button>
          <button onClick={(e) => merge("flag", e)} style={{ display: "block", width: "100%", textAlign: "left", padding: "7px 10px", border: "none", background: "transparent", fontSize: 12.5, color: "#3a3d4a", borderRadius: 4, cursor: "pointer", fontFamily: "inherit" }}>
            <div style={{ fontWeight: 600 }}>Merge behind flag</div>
            <div style={{ fontSize: 11, color: "#8a8d99" }}>Ship dark · 0% rollout</div>
          </button>
        </div>
      )}
    </span>
  );
};

// Copy-sharing-link button – inline (icon-only) or labelled.
const CopyLinkButton = ({ id, variant = "icon", urlBase = "https://app.posthog.com/code/inbox/" }) => {
  const [copied, setCopied] = useState(false);
  const onCopy = (e) => {
    e.stopPropagation();
    const url = urlBase + id;
    if (navigator.clipboard && navigator.clipboard.writeText) {
      navigator.clipboard.writeText(url).catch(() => {});
    }
    setCopied(true);
    setTimeout(() => setCopied(false), 1400);
  };
  if (variant === "icon") {
    return (
      <button
        className="inline-dismiss"
        onClick={onCopy}
        title={copied ? "Copied!" : "Copy sharing link"}
        aria-label="Copy sharing link"
      >
        {copied ? (
          <svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="#2f9e44" strokeWidth="2.4" strokeLinecap="round" strokeLinejoin="round" aria-hidden="true">
            <polyline points="20 6 9 17 4 12"></polyline>
          </svg>
        ) : (
          <svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.8" strokeLinecap="round" strokeLinejoin="round" aria-hidden="true">
            <path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"></path>
            <path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"></path>
          </svg>
        )}
      </button>
    );
  }
  return (
    <button className="t-btn" onClick={onCopy} style={{ display: "inline-flex", alignItems: "center", gap: 6 }} title={copied ? "Copied to clipboard" : "Copy a link to share this with a teammate"}>
      {copied ? (
        <>
          <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="#2f9e44" strokeWidth="2.4" strokeLinecap="round" strokeLinejoin="round" aria-hidden="true">
            <polyline points="20 6 9 17 4 12"></polyline>
          </svg>
          <span style={{ color: "#2f9e44" }}>Link copied</span>
        </>
      ) : (
        <>
          <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.8" strokeLinecap="round" strokeLinejoin="round" aria-hidden="true">
            <path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"></path>
            <path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"></path>
          </svg>
          Copy link
        </>
      )}
    </button>
  );
};

// "Why?" popover – small ghost trigger that reveals the agent's reasoning.
const WhyPopover = ({ title, children }) => {
  const [open, setOpen] = useState(false);
  const ref = useRef(null);
  useEffect(() => {
    if (!open) return;
    const onDown = (e) => { if (ref.current && !ref.current.contains(e.target)) setOpen(false); };
    const onEsc = (e) => { if (e.key === "Escape") setOpen(false); };
    document.addEventListener("mousedown", onDown);
    document.addEventListener("keydown", onEsc);
    return () => { document.removeEventListener("mousedown", onDown); document.removeEventListener("keydown", onEsc); };
  }, [open]);
  return (
    <span className="why" ref={ref}>
      <button
        type="button"
        className={"why-trigger" + (open ? " open" : "")}
        onClick={(e) => { e.stopPropagation(); setOpen(o => !o); }}
        aria-expanded={open}
        title="See the agent's reasoning"
      >Why?</button>
      {open && (
        <div className="why-pop" role="tooltip">
          {title && <div className="why-title">{title}</div>}
          <div className="why-body">{children}</div>
          <div className="why-foot">
            <span>The agent decided this – disagree?</span>
            <button className="why-link" onClick={() => setOpen(false)}>Discuss in chat ↗</button>
          </div>
        </div>
      )}
    </span>
  );
};

// Composed "PriorityChip with Why" – used in detail headers.
const PriorityWithWhy = ({ p, reasoning }) => (
  <span style={{ display: "inline-flex", alignItems: "center", gap: 6 }}>
    <PriorityChip p={p} />
    <WhyPopover title={`Why ${p}?`}>{reasoning}</WhyPopover>
  </span>
);

const ActionabilityWithWhy = ({ label, color, reasoning }) => (
  <span style={{ display: "inline-flex", alignItems: "center", gap: 6 }}>
    <span style={{ color }}>{label}</span>
    <WhyPopover title="Why this actionability?">{reasoning}</WhyPopover>
  </span>
);

const PriorityChip = ({ p }) => {
  const meta = PRIORITY[p];
  if (!meta) return null;
  return (
    <span className="pchip" style={{ background: meta.bg, color: meta.color }} title={meta.desc}>
      {meta.label}
    </span>
  );
};

const Avatar = ({ user, size = 18 }) => {
  const u = TEAMMATES[user] || TEAMMATES.marius;
  return (
    <div className="av" style={{
      background: u.color, width: size, height: size,
      fontSize: Math.max(8, size * 0.45),
    }}>{u.initials}</div>
  );
};

const Reviewers = ({ list, size = 18 }) => (
  <div className="reviewers">
    {list.slice(0, 3).map(h => <Avatar key={h} user={h} size={size} />)}
  </div>
);

const ConfidenceBar = ({ value }) => {
  const pct = Math.round(value * 100);
  const cls = value >= 0.85 ? "" : value >= 0.65 ? "med" : "low";
  return (
    <span className="card-confidence" title={`Agent confidence: ${pct}%`}>
      <span className={"confidence-bar " + cls}><span style={{ width: pct + "%" }} /></span>
      {pct}%
    </span>
  );
};

const SignalDot = ({ type }) => {
  const colors = {
    error: "#d8503a", replay: "#7c5cff", issue: "#3858d6",
    support: "#1f8a5b", funnel: "#b88800",
  };
  return <span className="dot" style={{ background: colors[type] || "#6b6e7a" }} />;
};

const SignalStrip = ({ signals }) => (
  <div className="signal-strip">
    {signals.slice(0, 3).map((s, i) => (
      <span key={i} className="signal-pill" title={s.title}>
        <SignalDot type={s.type} />
        {s.type === "replay" ? `${s.count} replays` :
         s.type === "error" ? `${s.count.toLocaleString()} errors` :
         s.type === "issue" ? "issue" :
         s.type === "support" ? `${s.count} tickets` :
         s.type === "funnel" ? s.count : "signal"}
      </span>
    ))}
  </div>
);

// ---- Solution card (kanban / list shared) ----
const SolutionCard = ({ s, selected, onClick, density = "compact", showImpact = true, onMerge, merged, onDismiss }) => {
  const isReady = s.kind === "ready";
  return (
    <div className={"card kind-" + s.kind + (selected ? " selected" : "")} onClick={onClick}>
      <div className="card-row card-meta-row">
        <PriorityChip p={s.priority} />
        <span className="card-id">{s.repo}#{s.pr}</span>
        <span className="card-age" style={{ marginLeft: "auto" }}>{s.age}</span>
      </div>
      <div className="card-title">{s.title}</div>
      {showImpact && s.impact && density !== "compact" && (
        <div style={{ fontSize: 11.5, color: "#6b6e7a", lineHeight: 1.45, marginTop: 2 }}>{s.impact}</div>
      )}
      <SignalStrip signals={s.signals} />
      <div className="card-foot">
        <span className="card-repo">⎇ {s.branch}</span>
        <span className="card-stats">
          <span className="add">+{s.additions}</span>
          <span className="del">−{s.deletions}</span>
        </span>
        <ConfidenceBar value={s.confidence} />
        <Reviewers list={s.reviewers} />
      </div>
      <div style={{ display: "flex", gap: 6, marginTop: 8, paddingTop: 8, borderTop: "1px dashed #e8e3d5" }}>
        {isReady ? (
          <MergeButton merged={merged} onMerge={(mode) => onMerge && onMerge(mode)} />
        ) : (
          <button className="inline-review" onClick={(e) => { e.stopPropagation(); onClick && onClick(); }}>
            Review
          </button>
        )}
        <button className="inline-dismiss" onClick={(e) => { e.stopPropagation(); onDismiss && onDismiss(); }}>Dismiss</button>
      </div>
    </div>
  );
};

// Small list-row variant
const SolutionRow = ({ s, selected, unread, onClick, onMerge, merged, onDismiss, density = "compact", showImpact = true }) => {
  const isReady = s.kind === "ready";
  const showImpactRow = showImpact && density === "comfortable" && s.impact;
  const summary = s.summary;
  return (
    <div className={"list-row" + (density === "comfortable" ? " comfortable" : "") + (selected ? " selected" : "") + (showImpactRow ? " has-impact" : "") + (summary ? " has-summary" : "") + (unread ? " unread" : "")} onClick={onClick}>
      <PriorityChip p={s.priority} />
      <div className="lr-title">
        <span className="t">{s.title}</span>
        {summary && <span className="d">{summary}</span>}
        <span className="m">
          <span style={{ color: isReady ? "#2f9e44" : "#b88800" }}>{isReady ? "● ready" : "● review"}</span>
          <span className="sep">·</span>
          <span>{s.repo}#{s.pr}</span>
          <span className="sep">·</span>
          <span>⎇ {s.branch}</span>
          <span className="sep">·</span>
          <span>{s.signals.length} signals</span>
          <span className="sep">·</span>
          <span>{s.age}</span>
          {s.origin && <OriginChip origin={s.origin} compact />}
        </span>
      </div>
      <span className="card-stats col-hide-narrow">
        <span className="add">+{s.additions}</span>
        <span className="del">−{s.deletions}</span>
      </span>
      <Reviewers list={s.reviewers} />
      <span className="col-hide-narrow" style={{ width: 1, height: 22, background: "#e8e3d5" }} />
      <span className="row-actions">
        <button className="inline-review" onClick={(e) => { e.stopPropagation(); onClick(); }}>Review</button>
        <button className="inline-dismiss" onClick={(e) => { e.stopPropagation(); onDismiss && onDismiss(); }} title="Dismiss">
          <svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.8" strokeLinecap="round" strokeLinejoin="round" aria-hidden="true">
            <path d="M10 15v4a3 3 0 0 0 3 3l4-9V2H5.72a2 2 0 0 0-2 1.7l-1.38 9a2 2 0 0 0 2 2.3z"></path>
            <path d="M17 13h2.67A2.31 2.31 0 0 0 22 11V4a2.31 2.31 0 0 0-2.33-2H17"></path>
          </svg>
        </button>
      </span>
      {showImpactRow && <div className="lr-impact">{s.impact}</div>}
    </div>
  );
};

// ---- Evidence widgets ----
const SourceIcon = ({ type }) => {
  const map = { error: "⚠", replay: "▶", issue: "◆", support: "✉", funnel: "⫶" };
  return <div className={"evidence-icon " + type}>{map[type] || "•"}</div>;
};

const ErrorWidget = ({ ev }) => {
  // Generate a fake daily count chart
  const bars = useMemo(() => {
    const seed = ev.title.length;
    return Array.from({ length: 30 }, (_, i) => {
      const t = (i + seed) % 7;
      return 20 + (t * 11 + i * 3) % 80 + (i > 22 ? 60 : 0);
    });
  }, [ev.title]);
  const max = Math.max(...bars);
  return (
    <div className="evidence">
      <div className="evidence-head">
        <SourceIcon type="error" />
        <div style={{ flex: 1, minWidth: 0 }}>
          <div className="evidence-title">{ev.title}</div>
          <div className="evidence-source">{ev.source} · {ev.when}</div>
        </div>
        <span className="evidence-count">{ev.count.toLocaleString()}</span>
      </div>
      <div className="mini-chart">
        {bars.map((b, i) => <div key={i} className="bar" style={{ height: (b / max * 100) + "%" }} />)}
      </div>
    </div>
  );
};

const ReplayWidget = ({ ev }) => {
  // Stable pseudo-random "replay segments"
  const segs = useMemo(() => {
    const out = []; let p = 4;
    for (let i = 0; i < 6; i++) { const w = 6 + (i*7) % 14; out.push({ left: p, w }); p += w + 5; }
    return out;
  }, []);
  return (
    <div className="evidence">
      <div className="evidence-head">
        <SourceIcon type="replay" />
        <div style={{ flex: 1, minWidth: 0 }}>
          <div className="evidence-title">{ev.title}</div>
          <div className="evidence-source">{ev.source} · {ev.when}</div>
        </div>
        <span className="evidence-count">{typeof ev.count === "number" ? ev.count.toLocaleString() : ev.count}</span>
      </div>
      <div className="replay-strip">
        <div className="replay-thumb">▶</div>
        <div className="replay-track">
          {segs.map((s, i) => <div key={i} className="seg" style={{ left: s.left + "%", width: s.w + "%" }} />)}
        </div>
        <div className="replay-meta">
          <span>00:00</span>
          <span>tap to scrub · 6 highlighted moments</span>
          <span>02:48</span>
        </div>
      </div>
    </div>
  );
};

const IssueWidget = ({ ev }) => (
  <div className="evidence">
    <div className="evidence-head">
      <SourceIcon type="issue" />
      <div style={{ flex: 1, minWidth: 0 }}>
        <div className="evidence-title">{ev.title}</div>
        <div className="evidence-source">{ev.source} · {ev.when}</div>
      </div>
      <span className="evidence-count">↗</span>
    </div>
    <div className="issue-body">
      "{ev.title.replace(/^"|"$/g, "")}" – opened by an external user, 6 thumbs-up reactions, last comment 4 days ago.
    </div>
  </div>
);

const SupportWidget = ({ ev }) => (
  <div className="evidence">
    <div className="evidence-head">
      <SourceIcon type="support" />
      <div style={{ flex: 1, minWidth: 0 }}>
        <div className="evidence-title">{ev.title}</div>
        <div className="evidence-source">{ev.source} · {ev.when}</div>
      </div>
      <span className="evidence-count">{ev.count}</span>
    </div>
    <div className="issue-body">
      Themed cluster of {ev.count} tickets. Top quote: "I noticed the numbers in my dashboard look off compared to last week."
    </div>
  </div>
);

const FunnelWidget = ({ ev }) => (
  <div className="evidence">
    <div className="evidence-head">
      <SourceIcon type="funnel" />
      <div style={{ flex: 1, minWidth: 0 }}>
        <div className="evidence-title">{ev.title}</div>
        <div className="evidence-source">{ev.source} · {ev.when}</div>
      </div>
      <span className="evidence-count" style={{ color: "#d8503a" }}>{ev.count}</span>
    </div>
    <div className="mini-chart" style={{ alignItems: "stretch", padding: "8px 12px" }}>
      <div style={{ display: "flex", flex: 1, gap: 8, alignItems: "flex-end" }}>
        {[100, 88, 78, 60].map((h, i) => (
          <div key={i} style={{ flex: 1, display: "flex", flexDirection: "column", alignItems: "center", gap: 4 }}>
            <div style={{ width: "100%", height: h * 0.4, background: i === 2 ? "#d8503a" : "#b88800", borderRadius: 2, opacity: 0.85 }} />
            <span style={{ fontFamily: "var(--font-mono)", fontSize: 9, color: "#8a8d99" }}>{h}%</span>
          </div>
        ))}
      </div>
    </div>
  </div>
);

const Evidence = ({ ev }) => {
  if (ev.type === "error") return <ErrorWidget ev={ev} />;
  if (ev.type === "replay") return <ReplayWidget ev={ev} />;
  if (ev.type === "issue") return <IssueWidget ev={ev} />;
  if (ev.type === "support") return <SupportWidget ev={ev} />;
  if (ev.type === "funnel") return <FunnelWidget ev={ev} />;
  return null;
};

// Origin chip – shows whether a PR or report came from a Responder or a Scout.
const OriginChip = ({ origin, compact = false }) => {
  if (!origin) return null;
  const isScout = origin.kind === "scout";
  const sourceLabel = (typeof SIGNAL_SOURCES !== "undefined" ? (SIGNAL_SOURCES.find(s => s.key === origin.source)?.label || origin.source) : origin.source);
  const label = isScout
    ? `Scout · ${origin.scoutName || origin.scoutId}`
    : `Responder · ${sourceLabel}`;
  const color = isScout ? "#3858d6" : "#1f8a5b";
  const bg = isScout ? "rgba(56, 88, 214, 0.08)" : "rgba(31, 138, 91, 0.08)";
  const borderColor = isScout ? "rgba(56, 88, 214, 0.22)" : "rgba(31, 138, 91, 0.22)";
  return (
    <span
      className="origin-chip"
      style={{ color, background: bg, borderColor }}
      title={isScout ? `Found by Scout: ${origin.scoutName}` : `Spawned by Responder run on ${sourceLabel}`}
    >
      <svg width="11" height="11" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" aria-hidden="true">
        {isScout
          ? (<><circle cx="11" cy="11" r="7"></circle><path d="m21 21-4.3-4.3"></path></>)
          : (<><polyline points="13 2 13 8 19 8"></polyline><path d="M19 22V8L13 2H6a2 2 0 0 0-2 2v18a2 2 0 0 0 2 2h11a2 2 0 0 0 2-2Z"></path></>)}
      </svg>
      {compact ? (isScout ? origin.scoutName : "Responder") : label}
    </span>
  );
};

// 14-day reports/day sparkline.
const Sparkline = ({ values, width = 96, height = 22, color = "#3858d6" }) => {
  if (!values || values.length === 0) return null;
  const max = Math.max(1, ...values);
  const stepW = width / values.length;
  return (
    <svg width={width} height={height} viewBox={`0 0 ${width} ${height}`} aria-hidden="true" style={{ display: "block" }}>
      {values.map((v, i) => {
        const h = Math.max(2, Math.round((v / max) * (height - 4)));
        const x = i * stepW + 1;
        const w = Math.max(1, stepW - 1.5);
        return <rect key={i} x={x} y={height - h} width={w} height={h} rx="1" fill={v === 0 ? "#e8e3d5" : color} />;
      })}
    </svg>
  );
};

Object.assign(window, {
  PriorityChip, Avatar, Reviewers, ConfidenceBar, SignalStrip,
  SolutionCard, SolutionRow, Evidence, MergeButton, CopyLinkButton,
  WhyPopover, PriorityWithWhy, ActionabilityWithWhy,
  OriginChip, Sparkline,
});
