// Messaging platforms — the channel-connection plane that mirrors the Hermes Agent
// dashboard's Channels page: each chat platform (Telegram/Discord/Slack/…) gets a
// card showing its state, an enabled toggle, its required/optional env vars (entered
// as password fields), and a connectivity Test. Wired to the dashboard config plane
// via /dash/* (HERMES.messagingPlatforms / messagingUpdate / messagingTest), with an
// offline fallback to a small placeholder so the standalone preview stays rendered.
const { useState, useEffect, useCallback } = React;

// Per-platform header icon. Only "discord" is a real brand glyph in the icon set;
// everything else (telegram/slack/whatsapp/…) falls back to the generic "chat".
function platformIcon(id) {
  return String(id || "").toLowerCase() === "discord" ? "discord" : "chat";
}

// state badge derivation — enabled+configured -> active; configured -> configured;
// otherwise -> needs setup. Mirrors page-models' inline badge style.
function stateBadge(p) {
  if (p.enabled && p.configured) return { cls: "badge ok", label: "active" };
  if (p.configured) return { cls: "badge", label: "configured" };
  return { cls: "badge warn", label: "needs setup" };
}

// Stringify a messagingTest() result into a short toast line.
function testSummary(r) {
  if (r == null) return "Test complete";
  if (typeof r === "string") return r;
  if (r.message) return String(r.message);
  if (r.ok === true) return "Test passed";
  if (r.ok === false) return r.error || r.detail || "Test failed";
  try { return JSON.stringify(r); } catch { return "Test complete"; }
}

// Offline placeholder so the preview shows the shape of the page when the dashboard
// config plane is unreachable.
const PREVIEW_PLATFORMS = [
  {
    id: "telegram", name: "Telegram", description: "Chat with Hermes from a Telegram bot.",
    docs_url: "", enabled: false, configured: false, state: "disabled",
    env_vars: [{ key: "TELEGRAM_BOT_TOKEN", required: true, is_set: false, redacted_value: "", description: "Bot token from @BotFather." }],
  },
  {
    id: "discord", name: "Discord", description: "Run Hermes as a Discord bot in your server.",
    docs_url: "", enabled: false, configured: false, state: "disabled",
    env_vars: [{ key: "DISCORD_BOT_TOKEN", required: true, is_set: false, redacted_value: "", description: "Bot token from the Discord developer portal." }],
  },
];

function PageMessaging({ toast }) {
  const [platforms, setPlatforms] = useState([]); // [{id,name,…,env_vars:[…]}]
  const [live, setLive] = useState(null);         // null=loading, true=backend, false=offline
  const [inputs, setInputs] = useState({});       // { "<platformId>::<KEY>": typedValue }
  const [busy, setBusy] = useState("");           // platform id currently mutating

  const load = useCallback(async () => {
    try {
      const r = await HERMES.messagingPlatforms();
      setPlatforms(Array.isArray(r && r.platforms) ? r.platforms : []);
      setLive(true);
    } catch {
      setPlatforms(PREVIEW_PLATFORMS);
      setLive(false);
    }
  }, []);

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

  // local input key per platform+env var; cleared on every reload so saved fields
  // fall back to their redacted placeholders again.
  const inKey = (id, key) => id + "::" + key;
  const setInput = (id, key, v) => setInputs((s) => ({ ...s, [inKey(id, key)]: v }));

  // toggle enabled -> messagingUpdate -> reload + toast.
  const toggleEnabled = useCallback(async (p) => {
    setBusy(p.id);
    try {
      await HERMES.messagingUpdate(p.id, { enabled: !p.enabled });
      toast(`${p.name} ${p.enabled ? "disabled" : "enabled"}`);
      setInputs({});
      await load();
    } catch (e) { toast(e.message || "Could not update platform"); }
    setBusy("");
  }, [load, toast]);

  // collect only the env vars the user actually typed into -> messagingUpdate({env}).
  const saveEnv = useCallback(async (p) => {
    const env = {};
    for (const ev of (p.env_vars || [])) {
      const v = inputs[inKey(p.id, ev.key)];
      if (v != null && v !== "") env[ev.key] = v;
    }
    if (!Object.keys(env).length) { toast("Enter a value before saving"); return; }
    setBusy(p.id);
    try {
      await HERMES.messagingUpdate(p.id, { env });
      toast(`${p.name} credentials saved`);
      setInputs({});
      await load();
    } catch (e) { toast(e.message || "Could not save credentials"); }
    setBusy("");
  }, [inputs, load, toast]);

  // connectivity check -> toast the stringified result.
  const test = useCallback(async (p) => {
    setBusy(p.id);
    try {
      const r = await HERMES.messagingTest(p.id);
      toast(`${p.name}: ${testSummary(r)}`);
    } catch (e) { toast(e.message || "Test failed"); }
    setBusy("");
  }, [toast]);

  const activeCount = platforms.filter((p) => p.enabled && p.configured).length;

  return (
    <div className="page">
      <PageHead eyebrow="Workspace" title="Channels" sub="Connect Hermes to chat platforms — Telegram, Discord, Slack and more.">
        {live === true && <span className="badge ok"><span className="d" />live</span>}
        {live === false && <span className="badge warn"><span className="d" />preview data</span>}
        {live === null && <span className="badge"><span className="d" />loading…</span>}
        <button className="btn btn-ghost" onClick={load}><Icon name="refresh" size={16} />Refresh</button>
      </PageHead>

      {/* ---- Platform cards ---- */}
      {live !== null && !platforms.length ? (
        <div className="card"><div className="empty">No messaging platforms reported by the dashboard.</div></div>
      ) : (
        <div className="grid cols-2">
          {platforms.map((p) => {
            const badge = stateBadge(p);
            const isBusy = busy === p.id;
            const envVars = p.env_vars || [];
            return (
              <div className="card" key={p.id}>
                {/* header: icon + name + state badge + actions */}
                <div className="card-head">
                  <div className="flex" style={{ gap: 12, alignItems: "flex-start" }}>
                    <span className="glyph" style={{ background: "var(--primary-soft)", color: "var(--primary)" }}>
                      <Icon name={platformIcon(p.id)} size={18} />
                    </span>
                    <div>
                      <div className="flex" style={{ gap: 8, alignItems: "center", flexWrap: "wrap" }}>
                        <h2 style={{ margin: 0 }}>{p.name || p.id}</h2>
                        <span className={badge.cls}><span className="d" />{badge.label}</span>
                        {p.error_message && <span className="badge bad"><span className="d" />{p.error_message}</span>}
                      </div>
                      {p.description && <p style={{ margin: "4px 0 0" }}>{p.description}</p>}
                    </div>
                  </div>
                  <div className="flex" style={{ gap: 8, alignItems: "center" }}>
                    {p.docs_url && (
                      <a className="icon-btn" href={p.docs_url} target="_blank" rel="noreferrer" title="Open docs">
                        <Icon name="external" size={15} />
                      </a>
                    )}
                    <Toggle on={!!p.enabled} onChange={() => !isBusy && toggleEnabled(p)} />
                  </div>
                </div>

                {/* env var inputs */}
                {!envVars.length ? (
                  <div className="empty">No configuration required.</div>
                ) : (
                  <>
                    {envVars.map((ev) => (
                      <div className="field" key={ev.key}>
                        <label>
                          <span className="mono">{ev.key}</span>
                          {ev.required && <span className="faint"> · required</span>}
                          {ev.is_set && <span className="faint"> · set</span>}
                        </label>
                        <input
                          className="input mono"
                          type="password"
                          value={inputs[inKey(p.id, ev.key)] || ""}
                          onChange={(e) => setInput(p.id, ev.key, e.target.value)}
                          placeholder={ev.redacted_value || "not set"}
                          autoComplete="new-password"
                        />
                        {ev.description && <div className="faint" style={{ fontSize: 12, marginTop: 4 }}>{ev.description}</div>}
                      </div>
                    ))}
                  </>
                )}

                {/* actions */}
                <div className="flex" style={{ gap: 8, marginTop: 14 }}>
                  {!!envVars.length && (
                    <button className="btn btn-primary btn-sm" disabled={isBusy} onClick={() => saveEnv(p)}>
                      <Icon name="check" size={14} />{isBusy ? "Saving…" : "Save"}
                    </button>
                  )}
                  <button className="btn btn-ghost btn-sm" disabled={isBusy} onClick={() => test(p)}>
                    <Icon name="bolt" size={14} />Test
                  </button>
                  {p.updated_at != null && <span className="faint mono" style={{ fontSize: 11.5, alignSelf: "center" }}>updated {p.updated_at}</span>}
                </div>
              </div>
            );
          })}
        </div>
      )}
    </div>
  );
}
window.PageMessaging = PageMessaging;
