// Auto React campaigns: list + form + history. No nick picker. No session strings.

const { useState } = React;

const CAMPAIGN_SEARCH_FIELDS = [
  (c) => c.name,
  (c) => c.channelLink,
  (c) => c.username,
  (c) => c.platform_group_id,
];

const CAMPAIGN_SORT_GETTERS = {
  name: (c) => c.name || "",
  channel: (c) => c.username || c.platform_group_id || "",
  range: (c) => c.reactMin || 0,
  pool: (c) => c.poolSize || 0,
  status: (c) => (c.active ? "active" : "off"),
  last_run: (c) => c.lastRun?.createdAt || c.lastRun?.startedAt || null,
  updated_at: (c) => modifiedAtMs(c),
};

function channelLabel(c) {
  if (c.username) return `@${c.username}`;
  return c.platform_group_id || "—";
}

function poolLabel(c) {
  const max = c.reactMax || 0;
  const pool = c.poolSize != null ? c.poolSize : "—";
  return `${pool} / ${max}`;
}

const ReactCampaignModal = ({ open, onClose, onSaved, initial = {} }) => {
  const toast = useToast();
  const isEdit = !!initial._id;
  const [form, setForm] = useState({
    name: "",
    channelLink: "",
    inviteLink: "",
    reactMin: 3,
    reactMax: 8,
    active: true,
    ...initial,
    active: initial.active !== false,
  });
  const [saving, setSaving] = useState(false);
  const [checking, setChecking] = useState(false);
  const [preview, setPreview] = useState(null);
  const set = (k, v) => setForm((f) => ({ ...f, [k]: v }));

  const handleCheck = async () => {
    if (!form.channelLink) {
      toast.error("Channel link is required");
      return;
    }
    setChecking(true);
    try {
      const result = await ReactCampaignApi.inspect({
        channelLink: form.channelLink,
        inviteLink: form.inviteLink,
      });
      const info = result.data || result;
      setPreview(info);
      if (info?.title && !String(form.name || "").trim()) set("name", info.title);
      if (info?.visibility === "private" && info?.platform_group_id) {
        set("channelLink", info.platform_group_id);
      }
      const vis = info?.visibility === "public" ? "Public" : "Private";
      toast.success(`${vis} ${info?.kind || "channel"}`);
    } catch (e) {
      setPreview(null);
      toast.error(e.message);
    } finally {
      setChecking(false);
    }
  };

  const handleSave = async () => {
    if (!form.channelLink) {
      toast.error("Channel link is required");
      return;
    }
    setSaving(true);
    try {
      const result = await ReactCampaignApi.save({
        id: form._id,
        name: form.name,
        channelLink: form.channelLink,
        inviteLink: form.inviteLink,
        reactMin: Number(form.reactMin),
        reactMax: Number(form.reactMax),
        active: !!form.active,
      });
      if (result?.apply && result.apply.ok === false) {
        toast.error(result.apply.error || "Saved, but watcher did not attach");
      } else {
        toast.success(isEdit ? "Campaign updated" : "Campaign added");
      }
      onSaved();
      onClose();
    } catch (e) {
      toast.error(e.message);
    } finally {
      setSaving(false);
    }
  };

  if (!open) return null;
  return (
    <Modal
      open={open}
      onClose={onClose}
      title={isEdit ? "Edit Auto React" : "Add Auto React"}
      subtitle="Watch every new post on this channel"
      width={520}
      footer={
        <>
          <button className="btn ghost" onClick={onClose}>Cancel</button>
          <button className="btn primary" onClick={handleSave} disabled={saving}>
            {saving ? "Saving…" : "Save"}
          </button>
        </>
      }
    >
      <div className="field">
        <label className="field-label">Name <span className="muted">(optional)</span></label>
        <input className="input" value={form.name || ""} onChange={(e) => set("name", e.target.value)} placeholder="House channel" />
        <div className="field-help">Tên gợi nhớ trên dashboard. Không bắt buộc.</div>
      </div>
      <div className="field">
        <label className="field-label">Channel link <span className="muted">(required)</span></label>
        <div style={{ display: "flex", gap: 8 }}>
          <input
            className="input mono"
            style={{ flex: 1 }}
            value={form.channelLink || ""}
            onChange={(e) => { setPreview(null); set("channelLink", e.target.value); }}
            placeholder="t.me/… / @channel / -100…"
          />
          <button type="button" className="btn" onClick={handleCheck} disabled={checking || saving}>
            {checking ? "Checking…" : "Check"}
          </button>
        </div>
        <div className="field-help">
          Channel link is required. Public: dán @username hoặc t.me/name. Private / dest copy Hub: dán -100… vào đây — Invite alone is not enough. Không dán t.me/+ vào ô này. Dán @username public thì react không bắt tin copy vào dest C | … (-100).
        </div>
        {preview && (
          <div className="muted" style={{ fontSize: 12, marginTop: 6, display: "flex", gap: 8, alignItems: "center" }}>
            <span className={`badge ${preview.visibility === "public" ? "green" : ""}`}>
              <span className="dot"></span>
              {preview.visibility === "public" ? "Public" : "Private"} {preview.kind || "channel"}
            </span>
            {preview.username ? <span>@{preview.username}</span> : null}
            {preview.platform_group_id ? <span className="mono">{preview.platform_group_id}</span> : null}
          </div>
        )}
      </div>
      <div className="field">
        <label className="field-label">Invite link <span className="muted">(required for private)</span></label>
        <input
          className="input mono"
          value={form.inviteLink || ""}
          onChange={(e) => set("inviteLink", e.target.value)}
          placeholder="https://t.me/+hash"
        />
        <div className="field-help">
          Private dest: required t.me/+hash. Check join 1 nick rồi điền -100 vào Channel link. Public: để trống — đừng dán lại t.me/username vào đây.
        </div>
      </div>
      <div className="field" style={{ display: "grid", gridTemplateColumns: "1fr 1fr", gap: 12 }}>
        <div>
          <label className="field-label">React min</label>
          <input className="input" type="number" min="1" max="50" value={form.reactMin} onChange={(e) => set("reactMin", e.target.value)} />
        </div>
        <div>
          <label className="field-label">React max</label>
          <input className="input" type="number" min="1" max="50" value={form.reactMax} onChange={(e) => set("reactMax", e.target.value)} />
        </div>
      </div>
      <div className="field-help" style={{ marginTop: -4, marginBottom: 12 }}>
        Số react mỗi post, random trong khoảng min–max. Nên để 4–6 cho giống người.
      </div>
      <div className="field">
        <label className="field-label" style={{ display: "flex", justifyContent: "space-between" }}>
          <span>Active</span>
          <input type="checkbox" checked={!!form.active} onChange={(e) => set("active", e.target.checked)} />
        </label>
        <div className="field-help">Bật = watch mọi post mới trên channel này.</div>
      </div>
      <div className="field-help">
        Dùng nick đã tick Thêm vào pool react. Mỗi react +1 view trên cùng nick.
      </div>
      <div
        style={{
          marginTop: 12,
          padding: "10px 12px",
          borderRadius: 8,
          border: "1px solid var(--border-2)",
          background: "var(--yellow-bg)",
          color: "var(--yellow-fg)",
          fontSize: 12.5,
          lineHeight: 1.45
        }}
      >
        Lưu ý: Tại phần setting của channel, chỉnh lại Reactions — chỉ nên để 4-6 react thôi.
      </div>
    </Modal>
  );
};

const ReactCampaignsScreen = ({ listQuery = "", onQuery, onOpenHistory }) => {
  const toast = useToast();
  const confirm = useConfirm();
  const [showAdd, setShowAdd] = useState(false);
  const [editItem, setEditItem] = useState(null);
  const { data: campaigns, loading, error, refetch } = useApi(ReactCampaignApi.list, []);
  const { sortKey, sortDir, toggleSort } = useListSort("updated_at", "desc");

  const rows = campaigns || [];
  const filtered = rows.filter((c) => matchQuery(c, listQuery, CAMPAIGN_SEARCH_FIELDS));
  const visible = sortItems(filtered, { key: sortKey, dir: sortDir, getters: CAMPAIGN_SORT_GETTERS });

  const handleDelete = async (c) => {
    const ok = await confirm("Delete campaign", `Delete "${c.name || channelLabel(c)}"?`);
    if (!ok) return;
    try {
      await ReactCampaignApi.delete(c._id);
      toast.success("Campaign deleted");
      refetch();
    } catch (e) {
      toast.error(e.message);
    }
  };

  if (error) return (
    <div className="page">
      <Empty icon={I.AlertTriangle} title="Failed to load Auto React" sub={error} action={<button className="btn" onClick={refetch}><I.Refresh /> Retry</button>} />
    </div>
  );

  return (
    <div className="page">
      <div className="page-head sticky-title">
        <div>
          <h1 className="page-title">Auto React</h1>
          <div className="page-sub">
            {loading ? "Loading…" : `${visible.length} campaign${visible.length === 1 ? "" : "s"}`}
          </div>
        </div>
        <div style={{ display: "flex", gap: 8 }}>
          <button className="btn" onClick={refetch}><I.Refresh /> Refresh</button>
          <button className="btn primary" onClick={() => setShowAdd(true)}><I.Plus /> Add campaign</button>
        </div>
      </div>

      <div className="toolbar">
        <ListSearch value={listQuery} onChange={onQuery} placeholder="Search name or Telegram ID…" />
      </div>

      <div className="card flush">
        <div style={{ overflow: "auto" }}>
          <table className="table">
            <thead>
              <tr>
                <SortableTh label="Name" column="name" sortKey={sortKey} sortDir={sortDir} onToggle={toggleSort} />
                <SortableTh label="Channel" column="channel" sortKey={sortKey} sortDir={sortDir} onToggle={toggleSort} />
                <SortableTh label="Min–Max" column="range" sortKey={sortKey} sortDir={sortDir} onToggle={toggleSort} />
                <SortableTh label="Pool" column="pool" sortKey={sortKey} sortDir={sortDir} onToggle={toggleSort} />
                <SortableTh label="Status" column="status" sortKey={sortKey} sortDir={sortDir} onToggle={toggleSort} />
                <SortableTh label="Last run" column="last_run" sortKey={sortKey} sortDir={sortDir} onToggle={toggleSort} />
                <SortableTh label="Modified" column="updated_at" sortKey={sortKey} sortDir={sortDir} onToggle={toggleSort} />
                <th style={{ width: 120 }}>Actions</th>
              </tr>
            </thead>
            <tbody>
              {loading ? (
                <SkeletonRows cols={8} rows={4} />
              ) : rows.length === 0 ? (
                <tr><td colSpan={8}><Empty icon={I.Activity} title="No campaigns" sub="Paste a channel link and set min–max reacts." /></td></tr>
              ) : visible.length === 0 ? (
                <tr><td colSpan={8}><Empty icon={I.Search} title="No campaigns match" sub="Clear search to see all campaigns." /></td></tr>
              ) : (
                visible.map((c) => (
                  <tr key={c._id} onClick={() => setEditItem(c)} style={{ cursor: "pointer" }}>
                    <td style={{ fontWeight: 500 }}>{c.name || channelLabel(c)}</td>
                    <td className="mono muted">{channelLabel(c)}</td>
                    <td className="tnum">{c.reactMin}–{c.reactMax}</td>
                    <td className="muted">{poolLabel(c)}</td>
                    <td>{c.active ? <span className="badge green"><span className="dot"></span>On</span> : <span className="muted">Off</span>}</td>
                    <td className="muted">{c.lastRun ? `${c.lastRun.status || "—"} · ${formatModifiedDate({ updated_at: c.lastRun.createdAt || c.lastRun.finishedAt })}` : "—"}</td>
                    <td className="muted tnum">{formatModifiedDate(c)}</td>
                    <td>
                      <div style={{ display: "flex", gap: 4 }} onClick={(e) => e.stopPropagation()}>
                        <button className="btn ghost sm" onClick={() => onOpenHistory && onOpenHistory(c)}>History</button>
                        <button className="btn ghost icon-only sm" onClick={() => setEditItem(c)}><I.Edit size={12} /></button>
                        <button className="btn ghost icon-only sm" onClick={() => handleDelete(c)} style={{ color: "var(--red-fg)" }}><I.Trash size={12} /></button>
                      </div>
                    </td>
                  </tr>
                ))
              )}
            </tbody>
          </table>
        </div>
      </div>

      <ReactCampaignModal open={showAdd} onClose={() => setShowAdd(false)} onSaved={refetch} />
      {editItem && (
        <ReactCampaignModal open={true} onClose={() => setEditItem(null)} onSaved={() => { setEditItem(null); refetch(); }} initial={editItem} />
      )}
    </div>
  );
};

const RUN_SEARCH_FIELDS = [
  (r) => r.messageId,
  (r) => r.status,
];

const ReactHistoryScreen = ({ campaignId, onBack, listQuery = "", onQuery }) => {
  const { data: runs, loading, error, refetch } = useApi(
    () => ReactCampaignApi.runs(campaignId),
    [campaignId]
  );
  const { data: campaign } = useApi(() => ReactCampaignApi.get(campaignId), [campaignId]);
  const { sortKey, sortDir, toggleSort } = useListSort("createdAt", "desc");
  const [openId, setOpenId] = useState(null);

  const rows = runs || [];
  const filtered = rows.filter((r) => matchQuery(r, listQuery, RUN_SEARCH_FIELDS));
  const visible = sortItems(filtered, { key: sortKey, dir: sortDir, getters: {
    createdAt: (r) => r.createdAt,
    messageId: (r) => r.messageId,
    requestedCount: (r) => r.requestedCount || 0,
    success: (r) => (r.successBotIds || []).length,
    status: (r) => r.status,
    failed: (r) => (r.failed || []).length,
  } });

  return (
    <div className="page">
      <div className="page-head sticky-title">
        <div>
          <h1 className="page-title">React history</h1>
          <div className="page-sub">{campaign?.name || campaign?.platform_group_id || campaignId}</div>
        </div>
        <div style={{ display: "flex", gap: 8 }}>
          <button className="btn" onClick={onBack}>Back</button>
          <button className="btn" onClick={refetch}><I.Refresh /> Refresh</button>
        </div>
      </div>
      <div className="toolbar">
        <ListSearch value={listQuery} onChange={onQuery} placeholder="Search message id…" />
      </div>
      <div className="card flush">
        <div style={{ overflow: "auto" }}>
          <table className="table">
            <thead>
              <tr>
                <SortableTh label="Time" column="createdAt" sortKey={sortKey} sortDir={sortDir} onToggle={toggleSort} />
                <SortableTh label="Message" column="messageId" sortKey={sortKey} sortDir={sortDir} onToggle={toggleSort} />
                <SortableTh label="Requested" column="requestedCount" sortKey={sortKey} sortDir={sortDir} onToggle={toggleSort} />
                <SortableTh label="Success" column="success" sortKey={sortKey} sortDir={sortDir} onToggle={toggleSort} />
                <SortableTh label="Status" column="status" sortKey={sortKey} sortDir={sortDir} onToggle={toggleSort} />
                <SortableTh label="Failed" column="failed" sortKey={sortKey} sortDir={sortDir} onToggle={toggleSort} />
              </tr>
            </thead>
            <tbody>
              {error ? (
                <tr><td colSpan={6}><Empty icon={I.AlertTriangle} title="Failed to load history" sub={error} /></td></tr>
              ) : loading ? (
                <SkeletonRows cols={6} rows={4} />
              ) : visible.length === 0 ? (
                <tr><td colSpan={6}><Empty icon={I.Activity} title="No runs yet" sub="Post in the dest channel while seeding-bot is running." /></td></tr>
              ) : (
                visible.map((r) => (
                  <React.Fragment key={r._id}>
                    <tr onClick={() => setOpenId(openId === r._id ? null : r._id)} style={{ cursor: "pointer" }}>
                      <td className="muted tnum">{formatModifiedDate({ updated_at: r.createdAt || r.startedAt })}</td>
                      <td className="mono">{r.messageId}</td>
                      <td className="tnum">{r.requestedCount}</td>
                      <td className="tnum">{(r.successBotIds || []).length}</td>
                      <td>{r.status}</td>
                      <td className="tnum">{(r.failed || []).length}</td>
                    </tr>
                    {openId === r._id && (r.failed || []).length > 0 && (
                      <tr>
                        <td colSpan={6} className="muted" style={{ fontSize: 12 }}>
                          {(r.failed || []).map((f, i) => (
                            <div key={i}>{String(f.botId || "")}: {f.error}</div>
                          ))}
                        </td>
                      </tr>
                    )}
                  </React.Fragment>
                ))
              )}
            </tbody>
          </table>
        </div>
      </div>
    </div>
  );
};

Object.assign(window, { ReactCampaignsScreen, ReactHistoryScreen, ReactCampaignModal });
