/* global React, Icon, useToast, Modal, fmtDate */
// ============================================================
// viewer-admin.jsx — จัดการ PIN สำหรับหน้าดูข้อมูลบนมือถือ (/m)
// + ดูประวัติว่า PIN ไหนเปิดอะไรเมื่อไร
// แสดงในหน้า "ตั้งค่า" ของระบบหลัก (แอดมินเท่านั้น)
// ============================================================
const { useState: useStateVA, useEffect: useEffectVA } = React;

const VIEWER_URL = "https://erp.jselectrichdy.com/m";

const VA_ACTIONS = {
  login: "เข้าสู่ระบบ",
  open_project: "เปิดโครงการ",
  open_contract: "เปิดสัญญา",
  open_house: "เปิดหน่วย/บ้าน",
  open_doc: "เปิดเอกสาร",
};
function vaAction(a) { return VA_ACTIONS[a] || a || "-"; }

function vaTime(ts) {
  if (!ts) return "-";
  const d = ts.toDate ? ts.toDate() : new Date(ts);
  const p = (n) => String(n).padStart(2, "0");
  return `${d.getFullYear()}-${p(d.getMonth() + 1)}-${p(d.getDate())} ${p(d.getHours())}:${p(d.getMinutes())}`;
}
function vaRandomPin() {
  const a = new Uint32Array(1);
  crypto.getRandomValues(a);
  return String(a[0] % 1000000).padStart(6, "0");
}

// ============================================================
// การ์ดจัดการ PIN
// ============================================================
function ViewerPinCard() {
  const [pins, setPins] = useStateVA(null);     // null = กำลังโหลด
  const [label, setLabel] = useStateVA("");
  const [pin, setPin] = useStateVA("");
  const [busy, setBusy] = useStateVA(false);
  const [showLogs, setShowLogs] = useStateVA(false);
  const [reveal, setReveal] = useStateVA({});
  const toast = useToast();

  const load = () => {
    window.FB.listViewerPins()
      .then(setPins)
      .catch((e) => { setPins([]); toast({ t: "โหลดรายการ PIN ไม่สำเร็จ", s: e.message }); });
  };
  useEffectVA(load, []);

  const valid = /^\d{6}$/.test(pin) && label.trim().length > 0;

  const create = async () => {
    if (!valid || busy) return;
    setBusy(true);
    try {
      await window.FB.createViewerPin(pin, label.trim());
      toast({ t: "สร้าง PIN สำเร็จ", s: `${label.trim()} — รหัส ${pin}` });
      setLabel(""); setPin("");
      load();
    } catch (e) {
      toast({ t: "สร้าง PIN ไม่สำเร็จ", s: e.message });
    }
    setBusy(false);
  };

  const toggle = async (p) => {
    try {
      await window.FB.setViewerPinActive(p.uid, !p.active);
      toast({ t: p.active ? "ระงับ PIN แล้ว" : "เปิดใช้ PIN แล้ว", s: p.label });
      load();
    } catch (e) { toast({ t: "ไม่สำเร็จ", s: e.message }); }
  };

  const remove = async (p) => {
    if (!window.confirm(`ลบ PIN ของ "${p.label}" ถาวร?\n\nรหัสนี้จะใช้เปิดดูข้อมูลใหม่ไม่ได้ทันที\nแต่ถ้าเครื่องนั้นเปิดหน้าค้างไว้อยู่ จะยังเห็นข้อมูลที่โหลดไปแล้วจนกว่าจะรีเฟรช`)) return;
    try {
      await window.FB.deleteViewerPin(p.uid);
      toast({ t: "ลบ PIN แล้ว", s: p.label });
      load();
    } catch (e) { toast({ t: "ลบไม่สำเร็จ", s: e.message }); }
  };

  const copyLink = () => {
    navigator.clipboard.writeText(VIEWER_URL)
      .then(() => toast({ t: "คัดลอกลิงก์แล้ว", s: VIEWER_URL }))
      .catch(() => toast({ t: "คัดลอกไม่สำเร็จ", s: VIEWER_URL }));
  };

  return (
    <>
      <div className="card" style={{ marginBottom: 14 }}>
        <div className="card-head">
          <h3>PIN สำหรับดูข้อมูลบนมือถือ</h3>
          <div style={{ flex: 1 }}></div>
          <button className="btn sm" onClick={() => setShowLogs(true)}>
            <Icon name="history" size={12} /> ประวัติการเข้าดู
          </button>
        </div>
        <div className="card-body vstack" style={{ gap: 12 }}>

          <div className="hstack" style={{ gap: 10, background: "var(--surface-2)", borderRadius: 8, padding: "9px 12px" }}>
            <Icon name="info" size={14} className="dim" />
            <div style={{ flex: 1, fontSize: 12.5, color: "var(--text-2)" }}>
              เปิดที่มือถือ: <b className="mono" style={{ color: "var(--brand-700)" }}>{VIEWER_URL.replace(/^https?:\/\//, "")}</b>
              <div style={{ marginTop: 2 }}>ดูข้อมูลและเปิดเอกสารได้อย่างเดียว — แก้ไขหรือลบอะไรไม่ได้</div>
            </div>
            <button className="btn sm" onClick={copyLink}>คัดลอกลิงก์</button>
          </div>

          {/* สร้าง PIN ใหม่ */}
          <div style={{ border: "1px solid var(--border)", borderRadius: 8, padding: 12 }}>
            <div style={{ fontWeight: 500, fontSize: 13, marginBottom: 8 }}>สร้าง PIN ใหม่</div>
            <div className="hstack" style={{ gap: 10, alignItems: "flex-end", flexWrap: "wrap" }}>
              <div className="field" style={{ flex: 2, minWidth: 160 }}>
                <label>ชื่อผู้ใช้ / หน่วยงาน *</label>
                <input className="input" value={label} placeholder="เช่น คุณสมชาย (หน้างาน)"
                  onChange={(e) => setLabel(e.target.value)} />
              </div>
              <div className="field" style={{ flex: 1, minWidth: 130 }}>
                <label>PIN 6 หลัก *</label>
                <input className="input mono" value={pin} inputMode="numeric" maxLength={6}
                  placeholder="000000" style={{ letterSpacing: 3, fontSize: 15 }}
                  onChange={(e) => setPin(e.target.value.replace(/\D/g, "").slice(0, 6))} />
              </div>
              <button className="btn" onClick={() => setPin(vaRandomPin())}>สุ่ม</button>
              <button className="btn primary" disabled={!valid || busy} onClick={create}>
                {busy ? <><span className="spinner" /> กำลังสร้าง...</> : <><Icon name="plus" size={13} /> สร้าง</>}
              </button>
            </div>
            {pin && !/^\d{6}$/.test(pin) && (
              <div style={{ color: "var(--danger)", fontSize: 12, marginTop: 5 }}>PIN ต้องเป็นตัวเลข 6 หลัก</div>
            )}
          </div>

          {/* รายการ PIN */}
          {pins === null ? (
            <div className="dim" style={{ fontSize: 13, padding: "10px 0" }}>
              <span className="spinner" style={{ width: 12, height: 12 }}></span> กำลังโหลด...
            </div>
          ) : pins.length === 0 ? (
            <div className="dim" style={{ fontSize: 13, textAlign: "center", padding: "18px 0" }}>
              ยังไม่มี PIN — สร้างอันแรกด้านบนได้เลย
            </div>
          ) : (
            <div className="tbl-wrap" style={{ border: "1px solid var(--border)", borderRadius: 8 }}>
              <table className="tbl">
                <thead><tr>
                  <th>ชื่อผู้ใช้</th>
                  <th style={{ width: 130 }}>PIN</th>
                  <th style={{ width: 120 }}>สร้างเมื่อ</th>
                  <th className="c" style={{ width: 90 }}>สถานะ</th>
                  <th className="c" style={{ width: 110 }}>จัดการ</th>
                </tr></thead>
                <tbody>
                  {pins.map((p) => (
                    <tr key={p.uid} style={{ cursor: "default", opacity: p.active ? 1 : 0.55 }}>
                      <td className="strong">{p.label || "—"}</td>
                      <td>
                        <span className="mono" style={{ letterSpacing: 2, fontSize: 14 }}>
                          {reveal[p.uid] ? p.pin : "••••••"}
                        </span>
                        <button className="ico-btn" title="แสดง / ซ่อน" style={{ marginLeft: 4, width: 22, height: 22 }}
                          onClick={() => setReveal({ ...reveal, [p.uid]: !reveal[p.uid] })}>
                          <Icon name="eye" size={11} />
                        </button>
                      </td>
                      <td className="dim mono" style={{ fontSize: 11.5 }}>{vaTime(p.created_at)}</td>
                      <td className="c">
                        <span className={`pill ${p.active ? "success" : "warn"}`} style={{ fontSize: 11 }}>
                          <span className="dot"></span>{p.active ? "ใช้งาน" : "ระงับ"}
                        </span>
                      </td>
                      <td className="c">
                        <button className="btn sm" onClick={() => toggle(p)} style={{ marginRight: 4 }}>
                          {p.active ? "ระงับ" : "เปิด"}
                        </button>
                        <button className="ico-btn danger" title="ลบถาวร" onClick={() => remove(p)}>
                          <Icon name="trash" size={12} />
                        </button>
                      </td>
                    </tr>
                  ))}
                </tbody>
              </table>
            </div>
          )}
        </div>
      </div>
      {showLogs && <ViewerLogModal onClose={() => setShowLogs(false)} pins={pins || []} />}
    </>
  );
}

// ============================================================
// ประวัติการเข้าดู
// ============================================================
function ViewerLogModal({ onClose, pins }) {
  const [logs, setLogs] = useStateVA(null);
  const [who, setWho] = useStateVA("");
  const toast = useToast();

  useEffectVA(() => {
    window.FB.listViewerLogs(300)
      .then(setLogs)
      .catch((e) => { setLogs([]); toast({ t: "โหลดประวัติไม่สำเร็จ", s: e.message }); });
  }, []);

  const rows = (logs || []).filter((l) => !who || l.uid === who);

  // ชื่อผู้ใช้เอาจากทะเบียน PIN ตาม uid ไม่ใช่ค่าที่ client ส่งมา
  // (ผู้ดูเขียน log เองได้ จึงใส่ชื่อคนอื่นมาได้ — uid ปลอมไม่ได้เพราะกฎบังคับ)
  const labelOf = (l) => {
    const p = pins.find((x) => x.uid === l.uid);
    return p ? (p.label || p.pin) : (l.pin_label ? l.pin_label + " (ไม่พบทะเบียน)" : "—");
  };

  const exportCsv = () => {
    if (!rows.length) return;
    // กัน CSV formula injection: ข้อความจากผู้ดูที่ขึ้นต้นด้วย = + - @ Excel จะรันเป็นสูตร
    const safe = (v) => {
      const s = String(v == null ? "" : v);
      return /^[=+\-@\t\r]/.test(s) ? "'" + s : s;
    };
    const head = ["วันเวลา", "ผู้ใช้", "การกระทำ", "รายการ", "รายละเอียด"];
    const body = rows.map((l) => [vaTime(l.at), labelOf(l), vaAction(l.action), l.target || "", l.extra || ""]);
    const csv = [head, ...body]
      .map((r) => r.map((c) => `"${safe(c).replace(/"/g, '""')}"`).join(",")).join("\n");
    const blob = new Blob(["﻿" + csv], { type: "text/csv;charset=utf-8" });
    const a = document.createElement("a");
    a.href = URL.createObjectURL(blob);
    a.download = "ประวัติการเข้าดู.csv";
    a.click();
    URL.revokeObjectURL(a.href);
    toast({ t: "ส่งออก CSV สำเร็จ", s: `${rows.length} รายการ` });
  };

  return (
    <Modal title="ประวัติการเข้าดูจากมือถือ" icon="history" size="xl" onClose={onClose} foot={
      <>
        <button className="btn" onClick={exportCsv} disabled={!rows.length}>
          <Icon name="excel" size={13} /> ส่งออก CSV
        </button>
        <div style={{ flex: 1 }}></div>
        <button className="btn primary" onClick={onClose}>ปิด</button>
      </>
    }>
      <div className="hstack" style={{ gap: 10, marginBottom: 10 }}>
        <div className="field" style={{ maxWidth: 260, flex: 1 }}>
          <label>กรองตามผู้ใช้</label>
          <select className="select" value={who} onChange={(e) => setWho(e.target.value)}>
            <option value="">— ทุกคน —</option>
            {pins.map((p) => <option key={p.uid} value={p.uid}>{p.label || p.pin}</option>)}
          </select>
        </div>
        <div style={{ flex: 1 }}></div>
        <div className="dim" style={{ fontSize: 12.5, paddingTop: 20 }}>
          แสดง {rows.length} รายการล่าสุด
        </div>
      </div>

      {logs === null ? (
        <div style={{ textAlign: "center", padding: 40, color: "var(--text-2)" }}>
          <span className="spinner" style={{ width: 24, height: 24 }}></span>
          <div style={{ fontSize: 13, marginTop: 10 }}>กำลังโหลดประวัติ...</div>
        </div>
      ) : rows.length === 0 ? (
        <div className="detail-empty" style={{ padding: 40 }}>
          <div className="ico"><Icon name="history" size={30} /></div>
          <div style={{ fontWeight: 500, color: "var(--text-2)" }}>ยังไม่มีการเข้าดูจากมือถือ</div>
        </div>
      ) : (
        <div className="tbl-wrap" style={{ border: "1px solid var(--border)", borderRadius: 8, maxHeight: 460, overflow: "auto" }}>
          <table className="tbl">
            <thead><tr>
              <th style={{ width: 140 }}>วันเวลา</th>
              <th style={{ width: 150 }}>ผู้ใช้</th>
              <th style={{ width: 120 }}>การกระทำ</th>
              <th>รายการ</th>
            </tr></thead>
            <tbody>
              {rows.map((l) => (
                <tr key={l.id} style={{ cursor: "default" }}>
                  <td className="mono dim" style={{ fontSize: 11.5 }}>{vaTime(l.at)}</td>
                  <td className="strong">{labelOf(l)}</td>
                  <td>{vaAction(l.action)}</td>
                  <td>
                    <span className="strong">{l.target || "—"}</span>
                    {l.extra && !String(l.extra).startsWith("http") && (
                      <span className="dim" style={{ fontSize: 12 }}> · {l.extra}</span>
                    )}
                  </td>
                </tr>
              ))}
            </tbody>
          </table>
        </div>
      )}
    </Modal>
  );
}

Object.assign(window, { ViewerPinCard, ViewerLogModal, VIEWER_URL });
