function outreachTodayDateKey(value) {
  if (!value) return null;
  const date = new Date(value);
  if (Number.isNaN(date.getTime())) return null;
  return new Intl.DateTimeFormat("en-CA", { timeZone: "Europe/Berlin", year: "numeric", month: "2-digit", day: "2-digit" }).format(date);
}

function outreachTodayBucket(task, now) {
  if (!task?.dueAt) return "needsAttention";
  const due = outreachTodayDateKey(task.dueAt);
  const today = outreachTodayDateKey(now);
  if (!due || !today) return "needsAttention";
  if (due < today) return "overdue";
  if (due === today) return "today";
  return "later";
}

function outreachTodayDateLabel(value, lang) {
  if (!value) return lang === "de" ? "Datum unbekannt" : "Date unknown";
  const date = new Date(value);
  if (Number.isNaN(date.getTime())) return lang === "de" ? "Datum unbekannt" : "Date unknown";
  return date.toLocaleDateString(lang === "de" ? "de-DE" : "en-GB", { day: "2-digit", month: "2-digit", year: "numeric", timeZone: "Europe/Berlin" });
}

function CrmOutreachToday({ user, lang, navigate }) {
  const [ownerId, setOwnerId] = React.useState(user?.id || "");
  const [data, setData] = React.useState(null);
  const [loading, setLoading] = React.useState(true);
  const [error, setError] = React.useState(null);
  const [busy, setBusy] = React.useState("");
  const [snoozeDates, setSnoozeDates] = React.useState({});

  const load = React.useCallback(async () => {
    setLoading(true); setError(null);
    try {
      if (!window.MesperOutreachDB) throw Object.assign(new Error("Outreach-Datenzugriff ist nicht konfiguriert"), { code: "NOT_CONFIGURED" });
      setData(await window.MesperOutreachDB.today(ownerId || null));
    } catch (loadError) { setError(loadError); }
    finally { setLoading(false); }
  }, [ownerId]);

  React.useEffect(() => { load(); }, [load]);

  const allTasks = data?.tasks || [];
  const attention = data?.needsAttention || [];
  const owners = [...allTasks, ...attention].reduce((result, item) => {
    if (item.ownerId && !result.some((owner) => owner.id === item.ownerId)) result.push({ id: item.ownerId, name: item.ownerName || item.ownerId });
    return result;
  }, []);
  const grouped = { overdue: [], today: [], later: [], needsAttention: [] };
  allTasks.forEach((task) => {
    const bucket = outreachTodayBucket(task, new Date());
    if (bucket === "needsAttention" && attention.some((item) => item.memberId === task.memberId)) return;
    grouped[bucket].push(task);
  });
  attention.forEach((item) => grouped.needsAttention.push({ ...item, isAttention: true }));
  const morningCounts = {
    pitches: grouped.today.filter((task) => task.purpose === "prepare").length,
    followups: grouped.today.filter((task) => task.purpose === "follow_up").length,
    overdue: grouped.overdue.length,
    accepted: new Set([...allTasks, ...attention].filter((item) => item.acceptedToday && item.connectionState === "connected" && item.stage === "ready").map((item) => item.memberId)).size,
    attention: grouped.needsAttention.length,
  };

  async function runCommand(task, action, payload) {
    const key = `${action}:${task.id || task.memberId}`;
    setBusy(key); setError(null);
    try {
      const nextPayload = { taskId: task.id || null, taskRevision: task.revision ?? null, ...payload };
      if (nextPayload.dueAt && typeof outreachTaskDueAtIso === "function") nextPayload.dueAt = outreachTaskDueAtIso(nextPayload.dueAt) || nextPayload.dueAt;
      await window.MesperOutreachDB.command({ memberId: task.memberId, expectedVersion: task.memberVersion || task.version || 1, action, payload: nextPayload });
      await load();
    } catch (commandError) { setError(commandError); }
    finally { setBusy(""); }
  }

  const labels = lang === "de"
    ? { owner: "Outreach Owner", all: "Alle", overdue: "Überfällig", today: "Heute", later: "Später", needsAttention: "Zu klären", complete: "Erledigen", snooze: "Verschieben", ownerMissing: "Owner fehlt", noNextStep: "Kein nächster Schritt", contact: "Kontakt öffnen", linkedin: "LinkedIn öffnen", lastTouch: "Letzter Kontakt", source: "Quelle", due: "Fällig", noTasks: "Keine Outreach-Aufgaben" }
    : { owner: "Outreach Owner", all: "All", overdue: "Overdue", today: "Today", later: "Later", needsAttention: "Needs attention", complete: "Complete", snooze: "Snooze", ownerMissing: "Owner missing", noNextStep: "No next step", contact: "Open contact", linkedin: "Open LinkedIn", lastTouch: "Last touch", source: "Source", due: "Due", noTasks: "No outreach tasks" };

  function taskCard(task) {
    const completeKey = `complete_task:${task.id}`;
    const snoozeKey = `snooze_task:${task.id}`;
    const linkedin = typeof CrmOutreachEngine === "object" && CrmOutreachEngine?.safeExternalUrl ? CrmOutreachEngine.safeExternalUrl(task.linkedinUrl) : null;
    return <article className="crm-outreach-today-task" key={`${task.memberId || "attention"}-${task.id || task.reason}`}>
      <div className="crm-outreach-today-task-main"><strong>{task.nextAction || task.title || task.contactName || labels.noNextStep}</strong><span>{task.companyName || ""}{task.contactName ? ` · ${task.contactName}` : ""}</span><span>{labels.owner}: {task.ownerName || task.ownerId || labels.ownerMissing} · {labels.due}: {task.dueAt ? outreachTodayDateLabel(task.dueAt, lang) : (lang === "de" ? "Datum fehlt" : "Date missing")}</span><span>{labels.lastTouch}: {task.lastTouchSubject ? `${task.lastTouchSubject} · ` : ""}{task.lastTouchOn || task.lastTouchAt ? outreachTodayDateLabel(task.lastTouchOn || task.lastTouchAt, lang) : (lang === "de" ? "nicht dokumentiert" : "not documented")} · {labels.source}: {task.sourceTitle || "CRM"}</span></div>
      <div className="crm-outreach-today-task-actions">
        {task.memberId && <button type="button" className="crm-outreach-button crm-outreach-button-secondary" onClick={() => navigate(`/crm/outreach/m/${task.memberId}`)}>{labels.contact}</button>}
        {linkedin && <a className="crm-outreach-button crm-outreach-button-secondary" href={linkedin} target="_blank" rel="noopener noreferrer">{labels.linkedin}</a>}
        {!task.isAttention && <button type="button" className="crm-outreach-button" onClick={() => runCommand(task, "complete_task", {})} disabled={!!busy}>{busy === completeKey ? "…" : labels.complete}</button>}
        {!task.isAttention && <div className="crm-outreach-today-snooze"><input aria-label={`${labels.snooze} ${task.title || task.id}`} type="date" value={snoozeDates[task.id] || ""} onChange={(event) => setSnoozeDates((current) => ({ ...current, [task.id]: event.target.value }))} /><button type="button" className="crm-outreach-button crm-outreach-button-secondary" onClick={() => runCommand(task, "snooze_task", { dueAt: snoozeDates[task.id] || null })} disabled={!!busy || !snoozeDates[task.id]}>{busy === snoozeKey ? "…" : labels.snooze}</button></div>}
        {!task.isAttention && owners.length > 0 && <select aria-label={`${labels.owner} ${task.title || task.id}`} value={task.ownerId || ""} onChange={(event) => runCommand(task, "assign_owner", { ownerId: event.target.value || null })} disabled={!!busy}><option value="">{labels.ownerMissing}</option>{owners.map((owner) => <option key={owner.id} value={owner.id}>{owner.name}</option>)}</select>}
      </div>
    </article>;
  }

  const groups = ["overdue", "today", "later", "needsAttention"];
  return <section className="crm-outreach-today" aria-label={lang === "de" ? "Outreach Heute" : "Outreach today"}>
    <div className="crm-outreach-today-header"><div><h2>{lang === "de" ? "Outreach" : "Outreach"}</h2><p className="crm-outreach-muted">{lang === "de" ? "Aufgaben aus aktiven Outreach-Teilnahmen. Drafts erzeugen keine Reminder." : "Tasks from active outreach memberships. Drafts do not create reminders."}</p></div><label className="crm-outreach-field"><span>{labels.owner}</span><select aria-label={labels.owner} value={ownerId} onChange={(event) => setOwnerId(event.target.value)}><option value="">{labels.all}</option>{owners.map((owner) => <option key={owner.id} value={owner.id}>{owner.name}</option>)}</select></label></div>
    {loading && <div className="crm-outreach-state" role="status">{lang === "de" ? "Lade Outreach-Aufgaben…" : "Loading outreach tasks…"}</div>}
    {!loading && error && <div className="crm-outreach-state crm-outreach-state-error" role="alert"><strong>{lang === "de" ? "Outreach-Aufgaben konnten nicht geladen werden" : "Could not load outreach tasks"}</strong><span>{error.message}</span><button type="button" className="crm-outreach-button crm-outreach-button-secondary" onClick={load}>{lang === "de" ? "Erneut laden" : "Retry"}</button></div>}
    {!loading && !error && <p className="crm-outreach-muted" aria-label={lang === "de" ? "Outreach-Morgencheck" : "Outreach morning check"}>{lang === "de" ? `Morgencheck: ${morningCounts.pitches} Pitches heute · ${morningCounts.followups} Follow-ups heute · ${morningCounts.overdue} überfällig · ${morningCounts.accepted} neue Annahmen ohne Pitch · ${morningCounts.attention} zu klären` : `Morning check: ${morningCounts.pitches} pitches today · ${morningCounts.followups} follow-ups today · ${morningCounts.overdue} overdue · ${morningCounts.accepted} new accepts without pitch · ${morningCounts.attention} need attention`}</p>}
    {!loading && !error && groups.map((group) => grouped[group].length > 0 && <div className="crm-outreach-today-group" key={group}><h3>{labels[group]} · {grouped[group].length}</h3>{grouped[group].map(taskCard)}</div>)}
    {!loading && !error && groups.every((group) => grouped[group].length === 0) && <div className="crm-outreach-state">{labels.noTasks}</div>}
  </section>;
}

function CrmOutreachActivity({ lang }) {
  const [filters, setFilters] = React.useState({ campaignId: "", ownerId: "", channel: "", from: "", to: "" });
  const [items, setItems] = React.useState([]);
  const [nextCursor, setNextCursor] = React.useState(null);
  const [loading, setLoading] = React.useState(true);
  const [error, setError] = React.useState(null);
  const [loadingMore, setLoadingMore] = React.useState(false);
  const requestKey = JSON.stringify(filters);
  const labels = lang === "de" ? { title: "Aktivitäten", subtitle: "Outreach-Events und verknüpfte CRM-Aktivitäten.", campaign: "Kampagne", owner: "Aktivitäts-Owner", channel: "Kanal", all: "Alle", from: "Von", to: "Bis", unknown: "Datum unbekannt", noItems: "Keine Aktivitäten gefunden", error: "Aktivitäten konnten nicht geladen werden", retry: "Erneut laden", more: "Mehr laden", dated: "zeitlich zugeordnet" } : { title: "Activities", subtitle: "Outreach events and linked CRM activities.", campaign: "Campaign", owner: "Activity owner", channel: "Channel", all: "All", from: "From", to: "To", unknown: "Date unknown", noItems: "No activities found", error: "Could not load activities", retry: "Retry", more: "Load more", dated: "with a known time" };

  const load = React.useCallback(async (cursor = null, append = false) => {
    if (append) setLoadingMore(true); else { setLoading(true); setError(null); }
    try {
      const result = await window.MesperOutreachDB.activity(filters, { limit: 50, cursor });
      const incoming = (result.items || []).filter((item, index, list) => list.findIndex((other) => (other.eventKey || other.id) === (item.eventKey || item.id)) === index);
      setItems((current) => append ? [...current, ...incoming.filter((item) => !current.some((existing) => (existing.eventKey || existing.id) === (item.eventKey || item.id)))] : incoming);
      setNextCursor(result.nextCursor || null);
    } catch (loadError) { setError(loadError); }
    finally { setLoading(false); setLoadingMore(false); }
  }, [requestKey]);
  React.useEffect(() => { load(); }, [load]);

  const options = items.reduce((result, item) => {
    if (item.ownerId && !result.owners.some((option) => option.id === item.ownerId)) result.owners.push({ id: item.ownerId, name: item.ownerName || item.ownerId });
    if (item.campaignId && !result.campaigns.some((option) => option.id === item.campaignId)) result.campaigns.push({ id: item.campaignId, name: item.campaignName || item.campaignId });
    if (item.channel && !result.channels.includes(item.channel)) result.channels.push(item.channel);
    return result;
  }, { owners: [], campaigns: [], channels: [] });
  const updateFilter = (key, value) => setFilters((current) => ({ ...current, [key]: value }));
  const uniqueItems = items.filter((item, index, list) => list.findIndex((other) => (other.eventKey || other.id) === (item.eventKey || item.id)) === index);
  const knownDate = uniqueItems.filter((item) => item.datePrecision !== "unknown" && (item.occurredAt || item.occurredOn));
  const unknownDate = uniqueItems.filter((item) => item.datePrecision === "unknown" || (!item.occurredAt && !item.occurredOn));
  const activityDate = (item) => item.occurredOn ? outreachTodayDateLabel(item.occurredOn, lang) : item.occurredAt ? new Date(item.occurredAt).toLocaleString(lang === "de" ? "de-DE" : "en-GB", { dateStyle: "short", timeStyle: "short", timeZone: "Europe/Berlin" }) : labels.unknown;
  const card = (item) => <article className="crm-outreach-activity-item" key={item.eventKey || item.id}><div><strong>{item.contactName || item.companyName || (lang === "de" ? "Unbekannter Kontakt" : "Unknown contact")}</strong><span>{item.companyName || ""}{item.ownerName ? ` · ${item.ownerName}` : ""}</span></div><div><strong>{item.body || item.type || "Activity"}</strong><span>{activityDate(item)}</span></div></article>;

  return <section className="crm-outreach-shell crm-outreach-activity"><div className="crm-outreach-header"><div><h1 className="crm-outreach-title">{labels.title}</h1><p className="crm-outreach-muted">{labels.subtitle}</p></div></div><div className="crm-outreach-filters" aria-label={lang === "de" ? "Aktivitätsfilter" : "Activity filters"}><label className="crm-outreach-field"><span>{labels.campaign}</span><select aria-label={labels.campaign} value={filters.campaignId} onChange={(event) => updateFilter("campaignId", event.target.value)}><option value="">{labels.all}</option>{options.campaigns.map((option) => <option key={option.id} value={option.id}>{option.name}</option>)}</select></label><label className="crm-outreach-field"><span>{labels.owner}</span><select aria-label={labels.owner} value={filters.ownerId} onChange={(event) => updateFilter("ownerId", event.target.value)}><option value="">{labels.all}</option>{options.owners.map((option) => <option key={option.id} value={option.id}>{option.name}</option>)}</select></label><label className="crm-outreach-field"><span>{labels.channel}</span><select aria-label={labels.channel} value={filters.channel} onChange={(event) => updateFilter("channel", event.target.value)}><option value="">{labels.all}</option>{options.channels.map((option) => <option key={option} value={option}>{option}</option>)}</select></label><label className="crm-outreach-field"><span>{labels.from}</span><input aria-label={labels.from} type="date" value={filters.from} onChange={(event) => updateFilter("from", event.target.value)} /></label><label className="crm-outreach-field"><span>{labels.to}</span><input aria-label={labels.to} type="date" value={filters.to} onChange={(event) => updateFilter("to", event.target.value)} /></label></div>{loading && <div className="crm-outreach-state" role="status">{lang === "de" ? "Lade Aktivitäten…" : "Loading activities…"}</div>}{!loading && error && <div className="crm-outreach-state crm-outreach-state-error" role="alert"><strong>{labels.error}</strong><span>{error.message}</span><button type="button" className="crm-outreach-button crm-outreach-button-secondary" onClick={() => load()}>{labels.retry}</button></div>}{!loading && !error && uniqueItems.length === 0 && <div className="crm-outreach-state">{labels.noItems}</div>}{!loading && !error && uniqueItems.length > 0 && <><div className="crm-outreach-list-meta">{knownDate.length} {labels.dated}</div><div className="crm-outreach-activity-list">{knownDate.map(card)}{unknownDate.length > 0 && <div className="crm-outreach-activity-unknown"><h2>{labels.unknown}</h2>{unknownDate.map(card)}</div>}</div>{nextCursor && <button type="button" className="crm-outreach-button crm-outreach-load-more" onClick={() => load(nextCursor, true)} disabled={loadingMore}>{loadingMore ? "…" : labels.more}</button>}</>}</section>;
}
