/* ============================================================
   Beacon CS — WIDGET (customer-facing chat)
   Customer-facing L1 support chat, handoff, and attachments.
   ============================================================ */
function WidgetApp({ onClose }) {
  const Icons = window.Icons;
  const ANNA_WELCOME = "你好，我是 Anna。你可以先问充值、提现、身份认证、账户安全、Google Authenticator 或费用问题。";
  const initialMessages = () => ([
    { who: "ai", layer: null, t: ANNA_WELCOME, done: true },
  ]);
  const [view, setView] = useState("home");   // home = Zendesk launcher | chat = self-built Beacon chat
  const [lang, setLang] = useState("中文");
  const [msgs, setMsgs] = useState(initialMessages);
  const [streaming, setStreaming] = useState(false);
  const [sessionState, setSessionState] = useState("active"); // active | waiting | human | ended
  const [agentName, setAgentName] = useState(null);
  const [surveyScore, setSurveyScore] = useState(null);
  const [surveyState, setSurveyState] = useState("pending"); // pending | submitted | skipped
  const [uploadState, setUploadState] = useState("idle");
  const [uploadAttempt, setUploadAttempt] = useState(0);
  const [dragActive, setDragActive] = useState(false);
  const [previewOpen, setPreviewOpen] = useState(false);
  const bodyRef = useRef(null);
  const waitingForAgent = sessionState === "waiting";

  const LANGS = ["中文", "英语", "俄语", "越南语", "西班牙语", "葡萄牙语"];
  const NOTICES = [
    "关于 TSLAX、NVDAX、AAPLX、AMZNX 等下架的公告",
    "关于 LION 下架及相关功能关闭的公告",
    "关于 KRWIN 下架及相关功能关闭的公告",
    "BitMart 即将上线 XMAQUINA（DEUS）",
    "关于 DOGUSDT 永续合约下架的公告",
  ];
  const ZENDESK_FAQ = [
    "如何充值？",
    "如何提现？",
  ];
  const QUICK_TOPICS = [
    "如何充值？",
    "充值还没到账",
    "如何提现？",
    "提现还没到账",
    "账户被冻结",
    "身份认证流程",
    "忘记登录密码",
    "找回 Google Authenticator",
    "查看交易费率",
    "不支持的资产可以退款吗？",
    "订单 RMA-48231 的退款申请现在什么状态？",
    "平台会赔偿我的损失吗？",
    "转人工",
  ];
  useEffect(() => { if (bodyRef.current) bodyRef.current.scrollTop = bodyRef.current.scrollHeight; }, [msgs, streaming]);

  // streaming typewriter
  function streamReply(full, layer, after) {
    setMsgs(m => [...m, { who: "ai", layer, t: "", done: false }]);
    setStreaming(true);
    let i = 0;
    const tick = () => {
      i += Math.max(2, Math.round(full.length / 36));
      const slice = full.slice(0, i);
      setMsgs(m => { const c = [...m]; c[c.length - 1] = { who: "ai", layer, t: slice, done: i >= full.length }; return c; });
      if (i < full.length) setTimeout(tick, 32);
      else { setStreaming(false); if (after) setTimeout(after, 350); }
    };
    setTimeout(tick, 260);
  }

  function startHandoff(trigger, reason = "") {
    setSessionState("waiting");
    const handoffText = trigger === "user"
      ? "已为你转人工。"
      : `已转人工处理。原因：${reason || "当前无法继续处理"}。`;
    setMsgs(m => [...m, { who: "ai", t: handoffText, done: true }]);
    setTimeout(() => {
      setSessionState("human");
      setAgentName("Sophia Chen");
      setMsgs(m => [...m, { who: "agent", agent: "Sophia Chen", t: "你好，我是 Sophia。我来继续处理。" }]);
    }, 1800);
    setTimeout(() => {
      setMsgs(m => [...m, {
        who: "agent",
        agent: "Sophia Chen",
        t: "我把相关参考文件发在这里。",
        attachments: [
          { kind: "image", name: "充值凭证.jpg", meta: "图片 · 可展开预览", action: "预览" },
          { kind: "file", name: "处理说明.pdf", meta: "PDF · 可打开或下载", action: "下载" },
          { kind: "text", name: "人工说明.txt", meta: "文本 · 可打开或下载", action: "打开" },
          { kind: "video", name: "屏幕录制.mp4", meta: "视频格式暂不可内联播放 · 下载查看", action: "下载" },
        ],
      }]);
    }, 2800);
    setTimeout(() => {
      setAgentName("Jia Ying");
      setMsgs(m => [...m, { who: "status", t: "Jia Ying 已接手本次服务。" }]);
    }, 3800);
    setTimeout(() => {
      setMsgs(m => [...m, { who: "agent", agent: "Jia Ying", t: "你好，我是 Jia Ying。我会继续跟进。" }]);
    }, 4300);
    setTimeout(() => {
      setSessionState("ended");
      setAgentName(null);
      setMsgs(m => [...m, { who: "ended", t: "本次人工会话已结束。你可以评价服务，或开始新对话。" }]);
    }, 6900);
  }

  function ask(q) {
    if (sessionState === "ended" || sessionState === "waiting") return;
    if (view !== "chat") setView("chat");
    setMsgs(m => [...m, { who: "user", t: q, done: true }]);
    if (sessionState !== "active") return;
    const lc = q.toLowerCase();
    const asksRefundStatus = (q.includes("退款申请") || q.includes("退款进度")) && (q.includes("现在") || q.includes("状态"));
    const hasOrderRef = /(?:订单(?:编号)?|order(?:\s*id)?)[：:\s#-]*[A-Za-z0-9-]{4,}/i.test(q);
    if (q.includes("转人工") || q.includes("人工客服") || lc.includes("human") || lc.includes("agent")) {
      setTimeout(() => startHandoff("user"), 300);
      return;
    }
    if (q.includes("不支持的资产") && q.includes("退款")) {
      setTimeout(() => streamReply("当前不支持的资产充值不能人工入账、恢复、找回或退款。请不要继续向该地址充值。", "官方回答"), 400);
    } else if (asksRefundStatus && !hasOrderRef) {
      setTimeout(() => streamReply("请提供需要核对的订单编号。我只能查询并说明该订单的当前状态，不能根据其它订单推断结果。", "必要澄清"), 400);
    } else if (asksRefundStatus) {
      setTimeout(() => streamReply("这笔退款申请当前仍在处理中。现有结果没有显示已批准，我不能承诺一定会退款；你可以稍后再查看状态。", "实时信息"), 400);
    } else if (q.includes("退款") && (q.includes("结果") || q.includes("申请"))) {
      setTimeout(() => streamReply("请提供需要核对的订单编号。我只能查询并说明该订单的当前状态，不能根据其它订单推断结果。", "必要澄清"), 400);
    } else if ((q.includes("平台") || q.includes("客服")) && (q.includes("赔偿") || q.includes("责任") || q.includes("补偿"))) {
      setTimeout(() => streamReply("我目前没有足够依据确认平台责任或赔偿结果。这需要人工继续核对，我会把已知信息一并转交。", "当前无法确认", () => {
        startHandoff("system", "当前无法确认责任或赔偿结果");
      }), 400);
    } else if (q.includes("充值还没到账") || q.includes("提现还没到账") || q.includes("未到账") || lc.includes("not arrived") || lc.includes("arriv")) {
      setTimeout(() => streamReply("请先核对网络、地址、充值附加说明或标签、链上确认数和站内外转账类型。仍未到账时，可转人工核对。", "帮助中心文章"), 400);
    } else if (lc.includes("withdraw") || q.includes("提现")) {
      setTimeout(() => streamReply("提现前请确认币种、网络和收款地址一致。提交后可在资产记录里查看进度。需要核对时，可转人工处理。", "官方回答"), 400);
    } else if (lc.includes("deposit") || q.includes("充值")) {
      setTimeout(() => streamReply("充值前请确认币种、网络和地址；部分币种还需要填写充值附加说明或标签。转账后等待链上确认。未到账时，可转人工核对。", "帮助中心文章"), 400);
    } else if (lc.includes("2fa") || lc.includes("lost") || q.includes("Google Authenticator") || q.includes("验证码")) {
      setTimeout(() => streamReply("找回 Google Authenticator 前，请准备身份证明和账户信息。涉及账户变更时，请转人工处理。", "官方回答"), 400);
    } else if (lc.includes("kyc") || q.includes("KYC")) {
      setTimeout(() => streamReply("你的认证可能因证件照片质量问题被退回。重提时请使用光线充足的照片，确保证件四角完整、无反光。需要我带你走一遍重提步骤吗？", "官方回答"), 400);
    } else if (lc.includes("wrong address") || lc.includes("address") || q.includes("错地址")) {
      setTimeout(() => streamReply("链上转账一旦广播，通常不可撤销。请准备链上交易编号、币种、网络和收款地址，提交给人工核对。", "官方回答"), 400);
    } else {
      setTimeout(() => streamReply("当前没有可用于回答的依据，我无法继续确认。我会把当前问题一并转交人工客服。", "当前无法确认", () => {
        startHandoff("system", "缺少可用于回答的依据");
      }), 400);
    }
  }

  function startNewConversation() {
    setView("chat");
    setStreaming(false);
    setSessionState("active");
    setAgentName(null);
    setSurveyScore(null);
    setSurveyState("pending");
    setUploadState("idle");
    setUploadAttempt(0);
    setDragActive(false);
    setPreviewOpen(false);
    setMsgs(initialMessages());
  }

  function simulateUpload(e) {
    if (e) e.preventDefault();
    if (sessionState !== "human" || uploadState === "checking" || uploadState === "uploading") return;
    setUploadState("checking");
    if (uploadAttempt === 0) {
      setUploadAttempt(1);
      setTimeout(() => setUploadState("failed"), 650);
      return;
    }
    setTimeout(() => setUploadState("uploading"), 450);
    setTimeout(() => {
      setUploadState("sent");
      setMsgs(m => [...m, { who: "user", t: "已上传附件：补充材料.pdf", done: true }]);
    }, 1050);
  }

  return (
    <div className="wg-scrim" onClick={onClose}>
      <div className="wg-frame" onClick={e => e.stopPropagation()}>
        {/* header */}
        <div className="wg-head">
          <div className="row" style={{ gap: 10 }}>
            <div className="wg-logo">B</div>
            <div>
              <div className="wg-title">BitMart 在线客服</div>
              <div className="wg-sub"><span className="wg-online"></span> {sessionState === "ended" ? "会话已结束" : sessionState === "waiting" ? "正在联系人工客服" : agentName ? `${agentName} 正在服务` : "Anna 在线"}</div>
            </div>
          </div>
          <div className="row" style={{ gap: 6 }}>
            <div className="wg-lang">
              <Icons.globe s={13} />
              <select aria-label="选择语言" value={lang} onChange={e => setLang(e.target.value)}>{LANGS.map(l => <option key={l}>{l}</option>)}</select>
            </div>
            <button className="wg-x" aria-label="关闭客服窗口" onClick={onClose}><Icons.x s={16} /></button>
          </div>
        </div>

        {view === "home" ? (
          <div className="wg-home-wrap">
            <div className="wg-home">
              {/* Zendesk-owned launcher. Anna starts only after the consult button opens the self-built chat. */}
              <div className="wg-ext-card">
                <div className="wg-ext-brand">
                  <div className="wg-logo">B</div>
                  <div>
                    <div className="wg-ext-title">联系我们</div>
                    <div className="wg-ext-sub">BitMart 官方客服入口</div>
                  </div>
                </div>
              </div>

              <div className="wg-sec">
                <div className="wg-sec-h"><span>重要公告</span><button className="wg-sec-all">查看全部 <Icons.chevR s={12} /></button></div>
                <div className="wg-faq">
                  {NOTICES.map((q, i) => (
                    <button key={i} className="wg-faq-row passive" aria-label={`查看公告：${q}`}>
                      <span>{q}</span>
                    </button>
                  ))}
                </div>
              </div>

              <div className="wg-sec">
                <div className="wg-sec-h"><span>推荐问题</span><button className="wg-sec-all">查看全部 <Icons.chevR s={12} /></button></div>
                <div className="wg-zd-faq">
                  {ZENDESK_FAQ.map((q, i) => (
                    <button key={i} className="wg-faq-row passive" aria-label={`查看推荐问题：${q}`}>
                      <span>{q}</span>
                    </button>
                  ))}
                </div>
              </div>
            </div>
            <div className="wg-home-foot">
              <button className="wg-start" onClick={() => setView("chat")}><Icons.msg s={15} /> 咨询客服</button>
              <div className="wg-foot-note">Anna 先回答，必要时转人工。</div>
            </div>
          </div>
        ) : (
          <>
            <div className="wg-body" ref={bodyRef}>
              {msgs.map((m, i) => {
                if (m.who === "handoff") return <div key={i} className="wg-sysline amber"><Icons.user s={13} /> {m.t}</div>;
                if (m.who === "status") return <div key={i} className="wg-sysline info"><Icons.refresh s={13} /> {m.t}</div>;
                if (m.who === "ended") return (
                  <div key={i} className="wg-ended-card">
                    <div className="wg-ended-text"><Icons.checkCircle s={15} /> {m.t}</div>
                    <div className="wg-survey">
                      <div className="wg-survey-h">评价本次服务</div>
                      <div className="wg-score-row">
                        {[1, 2, 3, 4, 5].map(score => (
                          <button key={score} aria-label={`选择 ${score} 分`} className={"wg-score" + (surveyScore === score ? " active" : "")} disabled={surveyState !== "pending"} onClick={() => setSurveyScore(score)}>{score}</button>
                        ))}
                      </div>
                      <div className="wg-survey-actions">
                        <button className="wg-survey-btn primary" disabled={!surveyScore || surveyState !== "pending"} onClick={() => setSurveyState("submitted")}>提交评分</button>
                        <button className="wg-survey-btn" disabled={surveyState !== "pending"} onClick={() => setSurveyState("skipped")}>跳过评价</button>
                      </div>
                      <div className="wg-survey-note">
                        {surveyState === "submitted" ? "反馈已提交。"
                          : surveyState === "skipped" ? "已跳过评价。"
                          : surveyScore ? `已选择 ${surveyScore} 分。`
                          : "评分可选。"}
                      </div>
                    </div>
                  </div>
                );
                const isUser = m.who === "user";
                return (
                  <div key={i} className={"wg-msg " + (isUser ? "user" : "ai")}>
                    {!isUser ? <div className="wg-av">{m.who === "agent" ? (m.agent || "CS").slice(0, 1) : "A"}</div> : null}
                    <div className="wg-bub-wrap">
                      {m.agent ? <div className="wg-agent-name">{m.agent} · 人工客服</div> : null}
                      {m.layer ? <div className="wg-layer"><Icons.layers s={10} /> {m.layer}</div> : null}
                      <div className="wg-bub">{m.t}{!m.done ? <span className="wg-caret"></span> : null}</div>
                      {m.attachments ? (
                        <div className="wg-attach-list">
                          {m.attachments.map(att => (
                            <AttachmentCard key={att.name} att={att} onPreview={() => setPreviewOpen(true)} />
                          ))}
                        </div>
                      ) : null}
                    </div>
                  </div>
                );
              })}
              {msgs.length === 1 && !streaming ? (
                <div className="wg-sysline info"><Icons.lock s={13} /> 仅提供公开说明 · 不处理资产操作</div>
              ) : null}
              {sessionState === "waiting" ? (
                <div className="wg-service-status">
                  <div className="wg-status-spinner"></div>
                  <div>
                    <b>正在联系人工客服</b>
                    <span>坐席接入后会继续处理。</span>
                  </div>
                </div>
              ) : null}
              {streaming && msgs[msgs.length - 1]?.t === "" ? <div className="wg-typing"><span></span><span></span><span></span></div> : null}
            </div>

            {sessionState === "ended" ? (
              <div className="wg-ended-foot">
                <button className="wg-start-new wide" onClick={startNewConversation}><Icons.msg s={15} /> 开始新对话</button>
                <div className="wg-foot-note">继续咨询请开始新对话。</div>
              </div>
            ) : (
              <>
                {sessionState === "active" ? (
                  <div className="wg-suggest">
                    {QUICK_TOPICS.map((q, i) => (
                      <button key={i} className="wg-chip" onClick={() => ask(q)}>{q}</button>
                    ))}
                  </div>
                ) : null}
                {sessionState === "human" ? (
                  <div
                    className={"wg-dropzone " + uploadState + (dragActive ? " drag" : "")}
                    onDragEnter={e => { e.preventDefault(); setDragActive(true); }}
                    onDragOver={e => { e.preventDefault(); setDragActive(true); }}
                    onDragLeave={e => { e.preventDefault(); setDragActive(false); }}
                    onDrop={e => { setDragActive(false); simulateUpload(e); }}
                    onClick={simulateUpload}
                  >
	                    <Icons.doc s={15} />
	                    <div>
	                      <div className="wg-drop-main">
	                        {uploadState === "idle" ? "拖拽文件到当前对话"
	                          : uploadState === "checking" ? "正在校验文件类型和大小"
	                          : uploadState === "uploading" ? "正在上传 · 68%"
                          : uploadState === "failed" ? "文件类型不支持 · 点击重试"
	                          : "已上传"}
	                      </div>
                        <div className="wg-drop-sub">{uploadState === "failed" ? "请换成图片、PDF 或文本文件后重试。" : uploadState === "sent" ? "附件已发送到当前对话。" : "文件会发送到当前对话。"}</div>
	                    </div>
	                  </div>
                ) : null}
                <div className="wg-input">
                  <input placeholder={waitingForAgent ? "等待坐席接入" : sessionState === "human" ? "输入回复..." : "输入消息..."} disabled={streaming || waitingForAgent} onKeyDown={e => { if (e.key === "Enter" && e.target.value.trim() && !streaming && !waitingForAgent) { ask(e.target.value.trim()); e.target.value = ""; } }} />
                  <button className="wg-send" aria-label="发送消息" disabled={streaming || waitingForAgent} onClick={e => { const inp = e.currentTarget.previousSibling; if (!inp.disabled && inp.value.trim()) { ask(inp.value.trim()); inp.value = ""; } }}><Icons.send s={16} /></button>
                </div>
              </>
            )}
          </>
        )}

        {previewOpen ? <AttachmentPreview onClose={() => setPreviewOpen(false)} /> : null}
      </div>
    </div>
  );
}

function AttachmentCard({ att, onPreview }) {
  const Icons = window.Icons;
  const Icon = att.kind === "image" ? Icons.eye : att.kind === "video" ? Icons.play : Icons.doc;
  return (
    <div className={"wg-attach " + att.kind}>
      <div className="wg-attach-ico">{att.kind === "image" ? <span className="wg-thumb">图片</span> : <Icon s={15} />}</div>
      <div className="wg-attach-copy">
        <div className="wg-attach-name">{att.name}</div>
        <div className="wg-attach-meta">{att.meta}</div>
      </div>
      <button className="wg-attach-action" aria-label={`${att.action}${att.name}`} onClick={att.kind === "image" ? onPreview : undefined}>{att.action}</button>
    </div>
  );
}

function AttachmentPreview({ onClose }) {
  const Icons = window.Icons;
  return (
    <div className="wg-preview-scrim" onClick={onClose}>
      <div className="wg-preview" onClick={e => e.stopPropagation()}>
        <div className="wg-preview-head">
          <span>充值凭证.jpg</span>
          <button className="wg-x dark" aria-label="关闭附件预览" onClick={onClose}><Icons.x s={16} /></button>
        </div>
        <div className="wg-preview-img">
          <div className="wg-preview-mark">图片预览</div>
        </div>
      </div>
    </div>
  );
}

window.WidgetApp = WidgetApp;
