// FilterBar – search + source dropdown (multi-select) + (in reports tab) status filter.
// All filters compose; render below the toolbar and above whatever layout is active.

const { useState: useStateF, useMemo: useMemoF, useRef: useRefF, useEffect: useEffectF } = React;

// Granular sources, derived from the `source` field on each signal.
// We map the prefix (before " · ") to a canonical source key. New strings auto-fall-through to "other".
const SIGNAL_SOURCES = [
  { key: "error-tracking", label: "Error tracking",  icon: "⚠", color: "#d8503a", types: ["error"],   internal: true,  responderEligible: true, description: "Surface new issues, reopenings, and volume spikes." },
  { key: "session-replay", label: "Session replay",  icon: "▶", color: "#7c5cff", types: ["replay"],  internal: true,  responderEligible: false, description: "Spot UX friction from recordings." },
  { key: "github",         label: "GitHub",          icon: "◯", color: "#3a3d4a", types: ["issue"],   internal: false, responderEligible: false, description: "Monitor new issues and updates." },
  { key: "linear",         label: "Linear",          icon: "▤", color: "#3858d6", types: ["issue"],   internal: false, responderEligible: false, description: "Monitor new issues and updates." },
  { key: "slack",          label: "Slack",           icon: "#", color: "#7c5cff", types: ["issue"],   internal: false, responderEligible: false, description: "Listen to conversations in connected channels." },
  { key: "support",        label: "PostHog Support", icon: "✉", color: "#1f8a5b", types: ["support"], internal: true,  responderEligible: true, description: "Turn support conversations into signals." },
  { key: "zendesk",        label: "Zendesk",         icon: "✉", color: "#1f8a5b", types: ["support"], internal: false, responderEligible: true, description: "Watch incoming support tickets." },
  { key: "pagerduty",      label: "PagerDuty",       icon: "⛐", color: "#d8503a", types: ["error"],   internal: false, responderEligible: false, description: "React to pages and incidents." },
  { key: "notion",         label: "Notion",          icon: "✎", color: "#3a3d4a", types: [],          internal: false, responderEligible: false },
  { key: "other",          label: "Other",           icon: "·", color: "#8a8d99", types: [],          internal: true,  responderEligible: false },
];

// Convert a signal's source string to a canonical source key.
const sourceKeyOf = (signal) => {
  const raw = (signal.source || "").toLowerCase();
  if (raw.startsWith("error tracking")) return "error-tracking";
  if (raw.startsWith("session replay")) return "session-replay";
  if (raw.startsWith("github")) return "github";
  if (raw.startsWith("linear")) return "linear";
  if (raw.startsWith("slack")) return "slack";
  if (raw.startsWith("support · zendesk") || raw.startsWith("zendesk")) return "zendesk";
  if (raw.startsWith("support")) return "support";
  if (raw.startsWith("pagerduty") || raw.startsWith("pager duty")) return "pagerduty";
  if (raw.startsWith("funnel")) return "funnel";
  return "other";
};

const REPORT_STATUSES = [
  { key: "researching",    label: "Researching" },
  { key: "needs-input",    label: "Needs input" },
  { key: "ready",          label: "Ready" },
  { key: "failed",         label: "Failed" },
  { key: "non-actionable", label: "Non-actionable" },
];

const toggle = (arr, v) => arr.includes(v) ? arr.filter(x => x !== v) : [...arr, v];

// True if `item` should pass the filter
const matchesFilter = ({ query, sources, reportStatuses, reviewers }, item) => {
  if (query) {
    const q = query.toLowerCase();
    const hay = (item.title + " " + (item.summary || "") + " " + (item.id || "")).toLowerCase();
    if (!hay.includes(q)) return false;
  }
  if (sources && sources.length) {
    const has = (item.signals || []).some(sig => sources.includes(sourceKeyOf(sig)));
    if (!has) return false;
  }
  if (reportStatuses && reportStatuses.length && item.status) {
    if (!reportStatuses.includes(item.status)) return false;
  }
  if (reviewers && reviewers.length) {
    const itemReviewers = item.reviewers || [];
    const has = reviewers.some(r => itemReviewers.includes(r));
    if (!has) return false;
  }
  return true;
};

// SourceDropdown – multi-select, with counts and click-outside-to-close
const SourceDropdown = ({ filter, setFilter, sourceCounts }) => {
  const [open, setOpen] = useStateF(false);
  const ref = useRefF(null);
  useEffectF(() => {
    if (!open) return;
    const onDown = (e) => { if (ref.current && !ref.current.contains(e.target)) setOpen(false); };
    document.addEventListener("mousedown", onDown);
    return () => document.removeEventListener("mousedown", onDown);
  }, [open]);

  const selected = filter.sources || [];
  const visibleSources = SIGNAL_SOURCES.filter(s => (sourceCounts?.[s.key] || 0) > 0 || selected.includes(s.key));
  const totalSources = visibleSources.length;
  const totalSelected = selected.length;

  let buttonLabel;
  if (totalSelected === 0) buttonLabel = "All sources";
  else if (totalSelected === 1) buttonLabel = SIGNAL_SOURCES.find(s => s.key === selected[0])?.label || "1 source";
  else buttonLabel = `${totalSelected} sources`;

  return (
    <div className="src-dd" ref={ref}>
      <button
        className={"src-trigger" + (totalSelected ? " has-selection" : "")}
        onClick={() => setOpen(o => !o)}
        aria-haspopup="listbox" aria-expanded={open}
      >
        <span className="src-icon">⌖</span>
        <span className="src-label">Source</span>
        <span className="src-value">{buttonLabel}</span>
        {totalSelected > 0 && (
          <span className="src-clear" onClick={(e) => { e.stopPropagation(); setFilter({ ...filter, sources: [] }); }} title="Clear">✕</span>
        )}
        <span className="src-caret">▾</span>
      </button>
      {open && (
        <div className="src-menu" role="listbox">
          <div className="src-menu-head">
            <span>Filter by source</span>
            {totalSelected > 0 && (
              <button className="src-menu-clear" onClick={() => setFilter({ ...filter, sources: [] })}>Clear</button>
            )}
          </div>
          <div className="src-menu-body">
            {visibleSources.map(s => {
              const n = sourceCounts?.[s.key] || 0;
              const isSelected = selected.includes(s.key);
              return (
                <button
                  key={s.key}
                  className={"src-option" + (isSelected ? " selected" : "")}
                  onClick={() => setFilter({ ...filter, sources: toggle(selected, s.key) })}
                  role="option" aria-selected={isSelected}
                >
                  <span className="src-check">{isSelected ? "✓" : ""}</span>
                  <span className="src-opt-icon" style={{ color: s.color }}>{s.icon}</span>
                  <span className="src-opt-label">{s.label}</span>
                  <span className="src-opt-count">{n}</span>
                </button>
              );
            })}
            {totalSources === 0 && (
              <div className="src-empty">No sources in this view.</div>
            )}
          </div>
        </div>
      )}
    </div>
  );
};

// ReviewerDropdown – multi-select filter by suggested reviewer
const ReviewerDropdown = ({ filter, setFilter, reviewerCounts }) => {
  const [open, setOpen] = useStateF(false);
  const ref = useRefF(null);
  useEffectF(() => {
    if (!open) return;
    const onDown = (e) => { if (ref.current && !ref.current.contains(e.target)) setOpen(false); };
    document.addEventListener("mousedown", onDown);
    return () => document.removeEventListener("mousedown", onDown);
  }, [open]);
  const selected = filter.reviewers || [];
  // Show only reviewers that appear at least once in the current pool, plus any currently-selected.
  const handles = Object.keys(reviewerCounts || {}).filter(h => (reviewerCounts[h] > 0) || selected.includes(h));
  return (
    <div className="src-dd" ref={ref}>
      <button
        className={"src-trigger" + (selected.length ? " has-selection" : "") + " rev-trigger"}
        onClick={() => setOpen(o => !o)}
        title="Filter by suggested reviewer"
        aria-haspopup="listbox" aria-expanded={open}
      >
        <svg width="15" height="15" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.8" strokeLinecap="round" strokeLinejoin="round" aria-hidden="true">
          <path d="M17 21v-2a4 4 0 0 0-4-4H5a4 4 0 0 0-4 4v2"></path>
          <circle cx="9" cy="7" r="4"></circle>
          <path d="M23 21v-2a4 4 0 0 0-3-3.87"></path>
          <path d="M16 3.13a4 4 0 0 1 0 7.75"></path>
        </svg>
        {selected.length > 0 && <span className="rev-count">{selected.length}</span>}
      </button>
      {open && (
        <div className="src-menu" role="listbox" style={{ right: 0, left: "auto", minWidth: 220 }}>
          <div className="src-menu-head">
            <span>Suggested reviewer</span>
            {selected.length > 0 && (
              <button className="src-menu-clear" onClick={() => setFilter({ ...filter, reviewers: [] })}>Clear</button>
            )}
          </div>
          <div className="src-menu-body">
            {handles.length === 0 && <div className="src-empty">Nobody to filter by.</div>}
            {handles.map(h => {
              const u = (typeof TEAMMATES !== "undefined" ? TEAMMATES[h] : null) || { handle: h, name: h, initials: h.slice(0, 2).toUpperCase(), color: "#8a8d99" };
              const isSelected = selected.includes(h);
              const n = reviewerCounts?.[h] || 0;
              return (
                <button
                  key={h}
                  className={"src-option" + (isSelected ? " selected" : "")}
                  onClick={() => setFilter({ ...filter, reviewers: toggle(selected, h) })}
                  role="option" aria-selected={isSelected}
                >
                  <span className="src-check">{isSelected ? "✓" : ""}</span>
                  <span style={{ width: 20, height: 20, borderRadius: "50%", background: u.color, color: "#fff", fontSize: 9, fontWeight: 700, display: "inline-flex", alignItems: "center", justifyContent: "center", flexShrink: 0 }}>{u.initials}</span>
                  <span className="src-opt-label">{u.name}</span>
                  <span className="src-opt-count">{n}</span>
                </button>
              );
            })}
          </div>
        </div>
      )}
    </div>
  );
};

// StatusDropdown – multi-select status filter for the Reports tab
const StatusDropdown = ({ filter, setFilter, statusCounts }) => {
  const [open, setOpen] = useStateF(false);
  const ref = useRefF(null);
  useEffectF(() => {
    if (!open) return;
    const onDown = (e) => { if (ref.current && !ref.current.contains(e.target)) setOpen(false); };
    document.addEventListener("mousedown", onDown);
    return () => document.removeEventListener("mousedown", onDown);
  }, [open]);
  const selected = filter.reportStatuses || [];
  const visible = REPORT_STATUSES.filter(s => (statusCounts?.[s.key] || 0) > 0 || selected.includes(s.key));
  const totalSelected = selected.length;
  let buttonLabel;
  if (totalSelected === 0) buttonLabel = "All statuses";
  else if (totalSelected === 1) buttonLabel = REPORT_STATUSES.find(s => s.key === selected[0])?.label || "1 status";
  else buttonLabel = `${totalSelected} statuses`;
  return (
    <div className="src-dd" ref={ref}>
      <button
        className={"src-trigger" + (totalSelected ? " has-selection" : "")}
        onClick={() => setOpen(o => !o)}
        aria-haspopup="listbox" aria-expanded={open}
      >
        <span className="src-icon">⊙</span>
        <span className="src-label">Status</span>
        <span className="src-value">{buttonLabel}</span>
        {totalSelected > 0 && (
          <span className="src-clear" onClick={(e) => { e.stopPropagation(); setFilter({ ...filter, reportStatuses: [] }); }} title="Clear">✕</span>
        )}
        <span className="src-caret">▾</span>
      </button>
      {open && (
        <div className="src-menu" role="listbox">
          <div className="src-menu-head">
            <span>Filter by status</span>
            {totalSelected > 0 && (
              <button className="src-menu-clear" onClick={() => setFilter({ ...filter, reportStatuses: [] })}>Clear</button>
            )}
          </div>
          <div className="src-menu-body">
            {visible.map(s => {
              const n = statusCounts?.[s.key] || 0;
              const isSelected = selected.includes(s.key);
              return (
                <button
                  key={s.key}
                  className={"src-option" + (isSelected ? " selected" : "")}
                  onClick={() => setFilter({ ...filter, reportStatuses: toggle(selected, s.key) })}
                  role="option" aria-selected={isSelected}
                >
                  <span className="src-check">{isSelected ? "✓" : ""}</span>
                  <span className={"report-status " + s.key} style={{ padding: 0, background: "transparent" }} />
                  <span className="src-opt-label">{s.label}</span>
                  <span className="src-opt-count">{n}</span>
                </button>
              );
            })}
            {visible.length === 0 && <div className="src-empty">No statuses in this view.</div>}
          </div>
        </div>
      )}
    </div>
  );
};

const FilterBar = ({
  filter, setFilter,
  showStatus,
  sourceCounts,    // { "error-tracking": 4, "linear": 2, ... }
  statusCounts,    // { researching: 1, ... }
  sortControl,     // optional JSX node (Sort dropdown)
}) => {
  return (
    <div className="filter-bar">
      <div className="search-wrap">
        <span className="ico">⌕</span>
        <input
          className="filter-search"
          placeholder="Search by title or description…"
          value={filter.query}
          onChange={e => setFilter({ ...filter, query: e.target.value })}
        />
        {filter.query && (
          <button className="clear" onClick={() => setFilter({ ...filter, query: "" })} title="Clear">✕</button>
        )}
      </div>

      <SourceDropdown filter={filter} setFilter={setFilter} sourceCounts={sourceCounts} />

      {showStatus && (
        <StatusDropdown filter={filter} setFilter={setFilter} statusCounts={statusCounts} />
      )}

      {sortControl}

      {(filter.query || (filter.sources && filter.sources.length) || (filter.reportStatuses && filter.reportStatuses.length) || (filter.reviewers && filter.reviewers.length)) ? (
        <button
          className="t-btn ghost"
          onClick={() => setFilter({ query: "", sources: [], reportStatuses: [], reviewers: [] })}
        >Clear all</button>
      ) : null}
    </div>
  );
};

const FilterEmpty = ({ onClear }) => (
  <div className="filter-empty">
    <div>Nothing matches your filters.</div>
    <button onClick={onClear}>Clear filters</button>
  </div>
);

Object.assign(window, { FilterBar, FilterEmpty, matchesFilter, SIGNAL_SOURCES, REPORT_STATUSES, sourceKeyOf });
