// Outreach Forecast — upcoming cadence actions as: Weekly Process Actions, Future
// (everything beyond this week), and a clickable monthly calendar that shows which
// action falls on which date. Built from completed mailings over the past 5 weeks.
(function () {
  const { useState, useEffect, useMemo } = React;
  const F = () => window.VAULT_FIRM || {};
  const BLUE = "#196EA7", INK = "#1A2733", INK2 = "#5A6B7B", MUTE = "#93A1B0", LINE = "#E4E9F0";

  // Real Outreach Playbook (mirrors screens-research.jsx). Each mailing's `cycle`
  // field selects which step sequence projects forward from its done date.
  const OUTREACH_CYCLES = {
    M1: { label: "Initial Mailing", steps: [
      { day: 1, code: "M1", type: "Mailing" }, { day: 5, code: "E1", type: "Email" }, { day: 6, code: "C1", type: "Call" },
      { day: 8, code: "E2", type: "Email" }, { day: 11, code: "E3", type: "Email" }, { day: 12, code: "C2", type: "Call" },
      { day: 14, code: "E4", type: "Email" }, { day: 15, code: "C3", type: "Call" }, { day: 18, code: "E9", type: "Email" }] },
    eM1: { label: "Initial Email", steps: [
      { day: 1, code: "eM1", type: "Email" }, { day: 3, code: "E2", type: "Email" }, { day: 4, code: "C1", type: "Call" },
      { day: 6, code: "E3", type: "Email" }, { day: 9, code: "E4", type: "Email" }, { day: 10, code: "C2", type: "Call" }, { day: 13, code: "E9", type: "Email" }] },
    M2: { label: "Re-Approach Mailing", steps: [
      { day: 1, code: "M2", type: "Mailing" }, { day: 5, code: "E5", type: "Email" }, { day: 6, code: "C1", type: "Call" },
      { day: 8, code: "E6", type: "Email" }, { day: 9, code: "C2", type: "Call" }, { day: 11, code: "E7", type: "Email" },
      { day: 13, code: "E8", type: "Email" }, { day: 14, code: "C3", type: "Call" }, { day: 17, code: "E9", type: "Email" }] },
    eM2: { label: "Re-Approach Email", steps: [
      { day: 1, code: "eM2", type: "Email" }, { day: 3, code: "E6", type: "Email" }, { day: 3, code: "C1", type: "Call" },
      { day: 4, code: "C2", type: "Call" }, { day: 6, code: "E7", type: "Email" }, { day: 8, code: "E8", type: "Email" },
      { day: 9, code: "C3", type: "Call" }, { day: 12, code: "E9", type: "Email" }] },
    CR: { label: "Custom / Tradeshow", steps: [
      { day: 1, code: "eCM1", type: "Email" }, { day: 3, code: "C1", type: "Call" }, { day: 3, code: "E2b", type: "Email" },
      { day: 4, code: "C2", type: "Call" }, { day: 6, code: "E3b", type: "Email" }, { day: 9, code: "E9b", type: "Email" }] },
  };
  const DEFAULT_CYCLE = "M1";
  // addBusinessDays mirrors the research screen (day 1 = start date, so businessDays-1 hops)
  function addBizDays(startStr, businessDays) {
    const d = new Date(startStr + "T00:00:00Z"); let added = 0;
    while (added < businessDays - 1) { d.setUTCDate(d.getUTCDate() + 1); const dow = d.getUTCDay(); if (dow !== 0 && dow !== 6) added++; }
    return d.toISOString().slice(0, 10);
  }
  function mondayOf(date) { const d = (date instanceof Date) ? new Date(Date.UTC(date.getFullYear(), date.getMonth(), date.getDate())) : new Date(date + "T00:00:00Z"); const day = (d.getUTCDay() + 6) % 7; d.setUTCDate(d.getUTCDate() - day); return d.toISOString().slice(0, 10); }
  function shiftWeek(w, delta) { const d = new Date(w + "T00:00:00Z"); d.setUTCDate(d.getUTCDate() + delta * 7); return d.toISOString().slice(0, 10); }

  function OutreachForecastScreen({ user }) {
    const [forecast, setForecast] = useState([]);
    const [loading, setLoading] = useState(true);
    const [ownerFilter, setOwnerFilter] = useState("");
    const [calMonth, setCalMonth] = useState(() => { const d = new Date(); return { y: d.getFullYear(), m: d.getMonth() }; });
    const [pickedDate, setPickedDate] = useState(null);

    const moduleHandle = useMemo(() => {
      const pid = (user && (user.personId || user.id)) || "";
      return String(pid).replace(/^p_/, "").replace(/_gmail$/, "") || "bscott";
    }, [user]);
    const weekStart = useMemo(() => mondayOf(new Date()), []);

    useEffect(() => {
      let cancelled = false;
      (async () => {
        setLoading(true);
        try {
          const fetches = [];
          for (let i = 0; i < 5; i++) fetches.push(window.VaultAPI.listResearchGoals(moduleHandle, shiftWeek(weekStart, -i)).catch(() => []));
          const results = await Promise.all(fetches);
          if (cancelled) return;
          const out = [];
          const allRows = results.flat();
          const mailings = allRows.filter(m => m.section === "mailings");
          const doneMailings = mailings.filter(m => m.done);
          results.forEach((rows, idx) => {
            const wk = shiftWeek(weekStart, -idx);
            (rows || []).forEach(m => {
              if (m.section !== "mailings" || !m.done) return;
              const start = m.doneDate || wk;
              const cycleKey = (m.cycle && OUTREACH_CYCLES[m.cycle]) ? m.cycle : DEFAULT_CYCLE;
              const cyc = OUTREACH_CYCLES[cycleKey];
              cyc.steps.forEach(step => {
                out.push({
                  dueDate: addBizDays(start, step.day), code: step.code, stepType: step.type,
                  project: m.projectName || "", ownerId: m.ownerId || null,
                  type: m.type || "", cycle: cycleKey, id: `${m.id}-${step.code}-${step.day}`,
                });
              });
            });
          });
          console.log("[forecast] module:", moduleHandle, "| rows(5wk):", allRows.length,
            "| mailings:", mailings.length, "| DONE mailings:", doneMailings.length,
            "| forecast actions:", out.length,
            doneMailings.length === 0 && mailings.length > 0 ? "→ mailings exist but none marked Done (mark a mailing Done in R.A.M. to populate)" : "");
          setForecast(out);
        } catch (e) { if (!cancelled) setForecast([]); }
        setLoading(false);
      })();
      return () => { cancelled = true; };
    }, [moduleHandle, weekStart]);

    const ownerOptions = useMemo(() => {
      const ids = new Set(); forecast.forEach(f => { if (f.ownerId) ids.add(f.ownerId); });
      return [...ids].map(id => ({ id, name: F().PEOPLE_BY_ID?.[id]?.name || id })).sort((a, b) => a.name.localeCompare(b.name));
    }, [forecast]);

    const filtered = useMemo(() => ownerFilter ? forecast.filter(f => f.ownerId === ownerFilter) : forecast, [forecast, ownerFilter]);
    const weekEnd = useMemo(() => { const d = new Date(weekStart + "T00:00:00Z"); d.setUTCDate(d.getUTCDate() + 6); return d.toISOString().slice(0, 10); }, [weekStart]);
    const thisWeek = useMemo(() => filtered.filter(f => f.dueDate >= weekStart && f.dueDate <= weekEnd).sort((a, b) => a.dueDate.localeCompare(b.dueDate)), [filtered, weekStart, weekEnd]);
    const future = useMemo(() => filtered.filter(f => f.dueDate > weekEnd).sort((a, b) => a.dueDate.localeCompare(b.dueDate)), [filtered, weekEnd]);

    // calendar: map dueDate -> actions
    const byDate = useMemo(() => { const m = {}; filtered.forEach(f => { (m[f.dueDate] = m[f.dueDate] || []).push(f); }); return m; }, [filtered]);

    function ownerName(id) { return F().PEOPLE_BY_ID?.[id]?.name || id || "—"; }

    function ForecastTable({ title, rows }) {
      return (
        <div style={{ border: `1px solid ${LINE}`, borderRadius: 12, overflow: "hidden", background: "#fff" }}>
          <div style={{ padding: "10px 14px", borderBottom: `1px solid ${LINE}`, fontSize: 13, fontWeight: 600, color: INK }}>{title} <span style={{ color: MUTE, fontWeight: 400 }}>· {rows.length}</span></div>
          {rows.length === 0 ? <div style={{ padding: 16, fontSize: 12.5, color: MUTE }}>No actions.</div> : (
            <div style={{ maxHeight: 360, overflowY: "auto" }}>
              <table style={{ width: "100%", borderCollapse: "collapse", fontSize: 12.5 }}>
                <thead><tr>{["Due", "Code", "Project", "Owner"].map((h, i) => <th key={i} style={{ textAlign: "left", padding: "8px 12px", fontSize: 11, fontWeight: 600, color: MUTE, borderBottom: `1px solid ${LINE}`, position: "sticky", top: 0, background: "#fff" }}>{h}</th>)}</tr></thead>
                <tbody>
                  {rows.map(r => (
                    <tr key={r.id} style={{ borderTop: `1px solid #F0F3F6` }}>
                      <td style={{ padding: "7px 12px", color: INK2, whiteSpace: "nowrap" }}>{r.dueDate}</td>
                      <td style={{ padding: "7px 12px", fontWeight: 600, color: BLUE }}>{r.code}</td>
                      <td style={{ padding: "7px 12px", color: INK, fontWeight: 500 }}>{r.project}</td>
                      <td style={{ padding: "7px 12px", color: INK2 }}>{ownerName(r.ownerId)}</td>
                    </tr>
                  ))}
                </tbody>
              </table>
            </div>
          )}
        </div>
      );
    }

    // monthly calendar grid
    function Calendar() {
      const { y, m } = calMonth;
      const first = new Date(y, m, 1); const startDow = (first.getDay() + 6) % 7; // Mon=0
      const daysInMonth = new Date(y, m + 1, 0).getDate();
      const cells = []; for (let i = 0; i < startDow; i++) cells.push(null);
      for (let d = 1; d <= daysInMonth; d++) cells.push(d);
      const monthName = first.toLocaleString("en-US", { month: "long", year: "numeric" });
      const todayStr = new Date().toISOString().slice(0, 10);
      function dstr(d) { return `${y}-${String(m + 1).padStart(2, "0")}-${String(d).padStart(2, "0")}`; }
      return (
        <div style={{ border: `1px solid ${LINE}`, borderRadius: 12, background: "#fff", padding: 16 }}>
          <div style={{ display: "flex", justifyContent: "space-between", alignItems: "center", marginBottom: 12 }}>
            <button onClick={() => setCalMonth(c => { const d = new Date(c.y, c.m - 1, 1); return { y: d.getFullYear(), m: d.getMonth() }; })} style={navBtn}>‹</button>
            <div style={{ fontSize: 15, fontWeight: 600, color: INK }}>{monthName}</div>
            <button onClick={() => setCalMonth(c => { const d = new Date(c.y, c.m + 1, 1); return { y: d.getFullYear(), m: d.getMonth() }; })} style={navBtn}>›</button>
          </div>
          <div style={{ display: "grid", gridTemplateColumns: "repeat(7,1fr)", gap: 4 }}>
            {["Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"].map(d => <div key={d} style={{ fontSize: 10.5, fontWeight: 600, color: MUTE, textAlign: "center", padding: "2px 0" }}>{d}</div>)}
            {cells.map((d, i) => {
              if (d == null) return <div key={i} />;
              const ds = dstr(d); const acts = byDate[ds] || []; const isToday = ds === todayStr; const isPicked = ds === pickedDate;
              return (
                <button key={i} onClick={() => setPickedDate(ds === pickedDate ? null : ds)} style={{
                  minHeight: 56, border: `1px solid ${isPicked ? BLUE : LINE}`, borderRadius: 8, background: isPicked ? "#EAF3F9" : (acts.length ? "#FBFCFD" : "#fff"),
                  cursor: "pointer", padding: 4, display: "flex", flexDirection: "column", alignItems: "stretch", textAlign: "left",
                }}>
                  <span style={{ fontSize: 11, fontWeight: isToday ? 700 : 500, color: isToday ? BLUE : INK2 }}>{d}</span>
                  {acts.slice(0, 2).map((a, j) => (
                    <span key={j} style={{ fontSize: 9.5, marginTop: 2, padding: "1px 4px", borderRadius: 4, background: "#E8F0F6", color: BLUE, overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap" }}>{a.code} {a.project}</span>
                  ))}
                  {acts.length > 2 && <span style={{ fontSize: 9, color: MUTE, marginTop: 1 }}>+{acts.length - 2} more</span>}
                </button>
              );
            })}
          </div>
          {pickedDate && (
            <div style={{ marginTop: 14, borderTop: `1px solid ${LINE}`, paddingTop: 12 }}>
              <div style={{ fontSize: 12.5, fontWeight: 600, color: INK, marginBottom: 8 }}>{pickedDate} · {(byDate[pickedDate] || []).length} actions</div>
              {(byDate[pickedDate] || []).length === 0 ? <div style={{ fontSize: 12, color: MUTE }}>No actions this day.</div> : (byDate[pickedDate] || []).map(a => (
                <div key={a.id} style={{ display: "flex", gap: 10, fontSize: 12.5, padding: "4px 0" }}>
                  <span style={{ fontWeight: 600, color: BLUE, minWidth: 34 }}>{a.code}</span>
                  <span style={{ color: INK, fontWeight: 500 }}>{a.project}</span>
                  <span style={{ color: INK2, marginLeft: "auto" }}>{ownerName(a.ownerId)}</span>
                </div>
              ))}
            </div>
          )}
        </div>
      );
    }

    const navBtn = { width: 30, height: 30, borderRadius: 8, border: `1px solid ${LINE}`, background: "#fff", color: INK2, cursor: "pointer", fontSize: 16, lineHeight: 1 };

    return (
      <div style={{ maxWidth: 1120, margin: "0 auto" }}>
        <div style={{ display: "flex", justifyContent: "space-between", alignItems: "center", marginBottom: 14, flexWrap: "wrap", gap: 10 }}>
          <h3 style={{ fontSize: 17, fontWeight: 600, color: INK, margin: 0 }}>Outreach Forecast</h3>
          <div style={{ display: "flex", alignItems: "center", gap: 8 }}>
            <span style={{ fontSize: 12, color: MUTE }}>Owner</span>
            <select value={ownerFilter} onChange={e => setOwnerFilter(e.target.value)} style={{ padding: "6px 10px", borderRadius: 8, border: `1px solid ${LINE}`, fontSize: 12.5, color: INK, background: "#fff" }}>
              <option value="">All owners</option>{ownerOptions.map(o => <option key={o.id} value={o.id}>{o.name}</option>)}
            </select>
          </div>
        </div>

        {loading ? <div style={{ color: MUTE, padding: 40, textAlign: "center" }}>Loading forecast…</div> : (
          <div>
            <div style={{ marginBottom: 18 }}><Calendar /></div>
            <div style={{ display: "grid", gridTemplateColumns: "1fr 1fr", gap: 16 }}>
              <ForecastTable title="Weekly Process Actions" rows={thisWeek} />
              <ForecastTable title="Future" rows={future} />
            </div>
            <p style={{ fontSize: 11.5, color: MUTE, marginTop: 14, lineHeight: 1.5 }}>
              Forecast is built from completed mailings over the past 5 weeks, projected through the standard cadence. Click any calendar day to see the actions due that date.
            </p>
          </div>
        )}
      </div>
    );
  }

  window.OutreachForecastScreen = OutreachForecastScreen;
})();