/* global React, I, UI, SSSData */
// ═══ รวมแชทลูกค้า — Facebook Messenger + LINE OA ในหน้าเดียว ═══
// ข้อความไหลเข้า Supabase (ตาราง omni_messages) ผ่าน Edge Function omnichat
// หน้าเว็บอ่านผ่าน anon key + realtime · ตอบกลับผ่าน /functions/v1/omnichat/send
const { useState: useStateOC, useEffect: useEffectOC, useRef: useRefOC, useMemo: useMemoOC } = React;

const OC_READ_KEY = "sss-omni-read";   // ต่อเครื่อง: เวลาอ่านล่าสุดต่อห้อง
function ocReadMap() { try { return JSON.parse(localStorage.getItem(OC_READ_KEY) || "{}"); } catch { return {}; } }
function ocMarkRead(key) { const m = ocReadMap(); m[key] = Date.now(); try { localStorage.setItem(OC_READ_KEY, JSON.stringify(m)); } catch {} }

const OC_CH = {
  facebook: { label: "Facebook", emoji: "💙", color: "#1877f2" },
  line: { label: "LINE", emoji: "💚", color: "#06c755" },
};

function ocTime(ts) {
  const d = new Date(ts);
  if (isNaN(d)) return "";
  const months = ["ม.ค.", "ก.พ.", "มี.ค.", "เม.ย.", "พ.ค.", "มิ.ย.", "ก.ค.", "ส.ค.", "ก.ย.", "ต.ค.", "พ.ย.", "ธ.ค."];
  const today = new Date();
  const sameDay = d.toDateString() === today.toDateString();
  const hm = `${String(d.getHours()).padStart(2, "0")}:${String(d.getMinutes()).padStart(2, "0")}`;
  return sameDay ? hm : `${d.getDate()} ${months[d.getMonth()]} ${hm}`;
}

function OmniChatPage() {
  const { Btn, Badge, Card, PageHead } = window.UI;
  const [msgs, setMsgs] = useStateOC([]);
  const [sel, setSel] = useStateOC(null);            // "channel|conv_id"
  const [text, setText] = useStateOC("");
  const [sending, setSending] = useStateOC(false);
  const [state, setState] = useStateOC("loading");   // loading | ready | nosetup | error
  const [errMsg, setErrMsg] = useStateOC("");
  const [, force] = useStateOC(0);
  const bottomRef = useRefOC(null);
  const selRef = useRefOC(null);
  selRef.current = sel;

  const load = async () => {
    const c = window.SSSDB && window.SSSDB.client && window.SSSDB.client();
    if (!c) { setState("error"); setErrMsg("ยังเชื่อมต่อฐานข้อมูลไม่ได้"); return; }
    const { data, error } = await c.from("omni_messages").select("*").order("ts", { ascending: false }).limit(3000);
    if (error) {
      if (/omni_messages/.test(error.message || "") || error.code === "42P01") setState("nosetup");
      else { setState("error"); setErrMsg(error.message || String(error)); }
      return;
    }
    setMsgs((data || []).slice().reverse());
    setState("ready");
  };

  useEffectOC(() => {
    load();
    const t = setInterval(load, 10000);   // fallback poll
    // realtime — ข้อความใหม่เด้งทันที
    let ch = null;
    try {
      const c = window.SSSDB && window.SSSDB.client && window.SSSDB.client();
      if (c) {
        ch = c.channel("omni-live")
          .on("postgres_changes", { event: "INSERT", schema: "public", table: "omni_messages" }, (payload) => {
            const m = payload.new;
            if (!m) return;
            setMsgs((prev) => prev.some((x) => x.id === m.id) ? prev : [...prev, m]);
            const key = m.channel + "|" + m.conv_id;
            if (selRef.current === key) ocMarkRead(key);
          })
          .subscribe();
      }
    } catch {}
    return () => { clearInterval(t); try { ch && ch.unsubscribe(); } catch {} };
  }, []);

  // จัดกลุ่มเป็นห้องสนทนา
  const convs = useMemoOC(() => {
    const map = new Map();
    msgs.forEach((m) => {
      const key = m.channel + "|" + m.conv_id;
      const cur = map.get(key) || { key, channel: m.channel, convId: m.conv_id, name: "", last: null, unread: 0 };
      if (m.name && m.direction === "in") cur.name = m.name;
      cur.last = m;
      map.set(key, cur);
    });
    const read = ocReadMap();
    map.forEach((cv) => {
      const lastRead = read[cv.key] || 0;
      cv.unread = msgs.filter((m) => m.channel === cv.channel && m.conv_id === cv.convId && m.direction === "in" && new Date(m.ts).getTime() > lastRead).length;
    });
    return [...map.values()].sort((a, b) => new Date(b.last?.ts || 0) - new Date(a.last?.ts || 0));
  }, [msgs]);

  const selConv = convs.find((c) => c.key === sel) || null;
  const thread = selConv ? msgs.filter((m) => m.channel === selConv.channel && m.conv_id === selConv.convId) : [];

  useEffectOC(() => { bottomRef.current && bottomRef.current.scrollIntoView({ block: "end" }); }, [sel, thread.length]);

  const openConv = (key) => { setSel(key); ocMarkRead(key); force((n) => n + 1); };

  const send = async () => {
    const t = text.trim();
    if (!t || !selConv || sending) return;
    setSending(true);
    try {
      const me = (window.Session && window.Session.get() && window.Session.get().name) || "SSS";
      const r = await fetch(window.SSSDB.url + "/functions/v1/omnichat/send", {
        method: "POST",
        headers: { "content-type": "application/json", apikey: window.SSSDB.key, Authorization: "Bearer " + window.SSSDB.key },
        body: JSON.stringify({ channel: selConv.channel, conv_id: selConv.convId, text: t, sender: me }),
      });
      const j = await r.json().catch(() => ({}));
      if (!r.ok || !j.ok) throw new Error(j.error || ("ส่งไม่สำเร็จ (" + r.status + ")"));
      setText("");
      load();
    } catch (e) {
      window.toast && window.toast("❌ " + (e.message || e));
    } finally { setSending(false); }
  };

  const totalUnread = convs.reduce((s, c) => s + c.unread, 0);

  if (state === "nosetup" || state === "error") {
    return (
      <>
        <PageHead title="รวมแชทลูกค้า · FB + LINE" sub="ตอบแชท Facebook Messenger และ LINE OA จากหน้าเดียว"/>
        <Card title={state === "nosetup" ? "ยังไม่ได้ติดตั้งระบบรวมแชท" : "เชื่อมต่อไม่ได้"}>
          <div style={{fontSize: 13, lineHeight: 1.9, color: "var(--ink-2)"}}>
            {state === "error" && <div style={{color: "var(--danger)", marginBottom: 8}}>{errMsg}</div>}
            <div style={{fontWeight: 600, marginBottom: 4}}>ขั้นตอนติดตั้ง (ทำครั้งเดียวบนเครื่อง Mac ที่รัน Supabase):</div>
            <ol style={{margin: 0, paddingLeft: 20}}>
              <li>รัน SQL สร้างตาราง: <span className="mono">supabase-functions/omnichat/schema.sql</span> (ใน Supabase Studio → SQL Editor)</li>
              <li>ตั้งค่า secrets + deploy ฟังก์ชัน <span className="mono">omnichat</span> ตามคู่มือ <span className="mono">supabase-functions/omnichat/README.md</span></li>
              <li>ผูก webhook ในหน้า Meta Developers และ LINE Developers ตามคู่มือ</li>
            </ol>
            <div style={{marginTop: 10}}>ติดตั้งเสร็จแล้วกลับมารีเฟรชหน้านี้ได้เลย</div>
          </div>
          <div style={{marginTop: 12}}><Btn size="sm" onClick={() => { setState("loading"); load(); }}>ลองเชื่อมต่ออีกครั้ง</Btn></div>
        </Card>
      </>
    );
  }

  return (
    <>
      <PageHead title="รวมแชทลูกค้า · FB + LINE" sub={`${convs.length} บทสนทนา${totalUnread ? ` · ยังไม่อ่าน ${totalUnread}` : ""}`}
        right={<Btn size="sm" kind="ghost" onClick={load}>รีเฟรช</Btn>}/>
      <div style={{display: "grid", gridTemplateColumns: "300px 1fr", gap: 0, border: "1px solid var(--line)", borderRadius: 10, overflow: "hidden", background: "var(--surface)", minHeight: "70vh"}}>
        {/* รายชื่อบทสนทนา */}
        <div style={{borderRight: "1px solid var(--line)", overflowY: "auto", maxHeight: "78vh"}}>
          {state === "loading" && <div style={{padding: 20, textAlign: "center", color: "var(--ink-3)", fontSize: 13}}>กำลังโหลด…</div>}
          {state === "ready" && convs.length === 0 && (
            <div style={{padding: 20, textAlign: "center", color: "var(--ink-3)", fontSize: 12.5, lineHeight: 1.8}}>
              ยังไม่มีข้อความเข้า —<br/>ลองทักเพจ FB หรือ LINE OA ของบริษัทดู<br/>ข้อความจะเด้งขึ้นที่นี่
            </div>
          )}
          {convs.map((cv) => {
            const ch = OC_CH[cv.channel] || { emoji: "💬", color: "var(--ink-3)", label: cv.channel };
            const on = sel === cv.key;
            return (
              <div key={cv.key} onClick={() => openConv(cv.key)}
                style={{padding: "10px 12px", cursor: "pointer", borderBottom: "1px solid var(--line)", background: on ? "var(--surface-2)" : "transparent", display: "flex", gap: 9, alignItems: "flex-start"}}>
                <div style={{fontSize: 20, lineHeight: 1}}>{ch.emoji}</div>
                <div style={{flex: 1, minWidth: 0}}>
                  <div style={{display: "flex", justifyContent: "space-between", gap: 6, alignItems: "center"}}>
                    <b style={{fontSize: 13, overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap"}}>{cv.name || cv.convId.slice(0, 10) + "…"}</b>
                    <span style={{fontSize: 10, color: "var(--ink-4)", flexShrink: 0}}>{cv.last ? ocTime(cv.last.ts) : ""}</span>
                  </div>
                  <div style={{display: "flex", justifyContent: "space-between", gap: 6, marginTop: 2}}>
                    <span style={{fontSize: 11.5, color: "var(--ink-3)", overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap"}}>
                      {cv.last ? (cv.last.direction === "out" ? "คุณ: " : "") + (cv.last.text || "") : ""}
                    </span>
                    {cv.unread > 0 && <span style={{background: ch.color, color: "white", fontSize: 10, fontWeight: 700, borderRadius: 99, padding: "1px 7px", flexShrink: 0}}>{cv.unread}</span>}
                  </div>
                </div>
              </div>
            );
          })}
        </div>

        {/* กล่องสนทนา */}
        <div style={{display: "flex", flexDirection: "column", maxHeight: "78vh"}}>
          {!selConv ? (
            <div style={{flex: 1, display: "grid", placeItems: "center", color: "var(--ink-3)", fontSize: 13}}>เลือกบทสนทนาทางซ้ายเพื่อดู/ตอบแชท</div>
          ) : (
            <>
              <div style={{padding: "10px 14px", borderBottom: "1px solid var(--line)", display: "flex", alignItems: "center", gap: 8}}>
                <span style={{fontSize: 18}}>{(OC_CH[selConv.channel] || {}).emoji}</span>
                <b style={{fontSize: 14}}>{selConv.name || selConv.convId}</b>
                <Badge tone="outline">{(OC_CH[selConv.channel] || {}).label}</Badge>
              </div>
              <div style={{flex: 1, overflowY: "auto", padding: 14, display: "flex", flexDirection: "column", gap: 8, background: "var(--surface-2)"}}>
                {thread.map((m) => {
                  const out = m.direction === "out";
                  return (
                    <div key={m.id} style={{alignSelf: out ? "flex-end" : "flex-start", maxWidth: "72%"}}>
                      <div style={{padding: "8px 12px", borderRadius: out ? "12px 12px 3px 12px" : "12px 12px 12px 3px", background: out ? "var(--ink-1)" : "var(--surface)", color: out ? "var(--surface)" : "var(--ink-1)", border: out ? 0 : "1px solid var(--line)", fontSize: 13, lineHeight: 1.55, whiteSpace: "pre-wrap", wordBreak: "break-word"}}>
                        {m.text}
                        {Array.isArray(m.attachments) && m.attachments.map((a, i) => a.url
                          ? (a.type === "image"
                            ? <img key={i} src={a.url} alt="" style={{display: "block", maxWidth: 220, borderRadius: 8, marginTop: 6, cursor: "pointer"}} onClick={() => window.open(a.url, "_blank")}/>
                            : <a key={i} href={a.url} target="_blank" rel="noreferrer" style={{display: "block", marginTop: 4, fontSize: 12}}>📎 {a.type}</a>)
                          : null)}
                      </div>
                      <div style={{fontSize: 10, color: "var(--ink-4)", marginTop: 2, textAlign: out ? "right" : "left"}}>
                        {out && m.name ? m.name + " · " : ""}{ocTime(m.ts)}
                      </div>
                    </div>
                  );
                })}
                <div ref={bottomRef}/>
              </div>
              <div style={{padding: 10, borderTop: "1px solid var(--line)", display: "flex", gap: 8}}>
                <textarea value={text} onChange={(e) => setText(e.target.value)} rows={2} placeholder={`ตอบกลับทาง ${(OC_CH[selConv.channel] || {}).label}…`}
                  onKeyDown={(e) => { if (e.key === "Enter" && !e.shiftKey) { e.preventDefault(); send(); } }}
                  style={{flex: 1, padding: "8px 10px", borderRadius: 8, border: "1px solid var(--line-strong)", fontSize: 13, fontFamily: "inherit", resize: "none", background: "var(--surface)", color: "var(--ink-1)"}}/>
                <Btn kind="primary" onClick={send} disabled={sending || !text.trim()}>{sending ? "กำลังส่ง…" : "ส่ง"}</Btn>
              </div>
            </>
          )}
        </div>
      </div>
    </>
  );
}

window.OmniChatPage = OmniChatPage;
