/* mrwing — the live Mr. Wing chat surface. Talks to runWing (real Anthropic /
   window.claude / local NLU), confirms real actions, persists transcripts,
   and behaves as an accessible dialog. */

function TypingDots() {
  return (
    <div style={{ display: "flex", gap: 4, padding: "12px 16px" }} aria-label="typing">
      {[0, 1, 2].map(i => <span key={i} style={{ width: 7, height: 7, borderRadius: "50%", background: "var(--ink-3)", animation: "dot 1.2s infinite", animationDelay: i * 0.18 + "s" }} />)}
    </div>
  );
}

function ConfirmCard({ card, onConfirm, onCancel, done }) {
  const { t } = useLang();
  const isCancel = card.type === "cancel";
  const isEscalate = card.type === "escalate";
  const isModify = card.type === "book" && card.mode === "modify";
  if (isEscalate) {
    return (
      <div className="card" style={{ border: "1px solid var(--gold)", background: "var(--gold-wash)", padding: 16, marginTop: 4 }}>
        <div style={{ display: "flex", gap: 10, alignItems: "center" }}>
          <Icon name="phone" size={18} color="var(--gold-d)" />
          <div style={{ fontWeight: 700, fontSize: 13.5, color: "var(--gold-d)" }}>{t("wing.escTitle")}</div>
        </div>
        <p style={{ fontSize: 13, color: "var(--ink-2)", marginTop: 8 }}>{card.reason || t("wing.escBody")}</p>
      </div>
    );
  }
  const title = isCancel ? t("wing.confirmCancel") : isModify ? t("wing.confirmModify") : t("wing.confirmBooking");
  return (
    <div className="card" style={{ border: "1px solid " + (isCancel ? "var(--danger)" : "var(--emerald-tint)"), padding: 16, marginTop: 4, background: "#fff" }}>
      <div style={{ fontSize: 11, letterSpacing: ".14em", textTransform: "uppercase", color: isCancel ? "var(--danger)" : "var(--gold-d)", fontWeight: 700 }}>{title}</div>
      <div style={{ fontWeight: 700, fontSize: 15, marginTop: 8, color: "var(--ink)" }}>{card.title}</div>
      {card.detail && <div className="muted" style={{ fontSize: 13, marginTop: 3 }}>{card.detail}</div>}
      <div style={{ display: "flex", justifyContent: "space-between", alignItems: "center", marginTop: 12, padding: "10px 0", borderTop: "1px solid var(--line)" }}>
        <span style={{ fontSize: 13, color: "var(--ink-2)" }}>{isCancel ? t("wing.refundToCard") : (card.pay || t("wing.savedCard"))}</span>
        <span style={{ fontWeight: 700, fontSize: 16, color: isCancel ? "var(--danger)" : "var(--emerald)" }}>
          {isCancel ? "+" : ""}<Money value={card.refund || card.price || 0} />
        </span>
      </div>
      {done ? (
        <div style={{ display: "flex", gap: 8, alignItems: "center", color: done === "no" ? "var(--ink-3)" : "var(--emerald)", fontWeight: 600, fontSize: 13.5, marginTop: 6 }}>
          {done === "no" ? <><Icon name="x" size={15} /> {t("common.cancel")}</> : <><Icon name="check" size={16} stroke={2.2} /> {isCancel ? t("status.Cancelled") : isModify ? t("status.Modified") : t("status.Confirmed")}</>}
        </div>
      ) : (
        <div style={{ display: "flex", gap: 8, marginTop: 10 }}>
          <button className="btn btn-sm" onClick={onCancel} style={{ flex: 1, justifyContent: "center", background: "var(--paper-2)", color: "var(--ink-2)" }}>{t("wing.cancel")}</button>
          <button className={"btn btn-sm " + (isCancel ? "btn-dark" : "btn-primary")} onClick={onConfirm} style={{ flex: 2, justifyContent: "center" }}>
            <Icon name="check" size={15} /> {t("wing.confirm")}
          </button>
        </div>
      )}
    </div>
  );
}

function MrWing() {
  const { t, lang } = useLang();
  const store = useStore();
  const { wingOpen, setWingOpen, wingSeed, setWingSeed, isMobile, saveConversation } = store;
  const sessionId = React.useRef("wing_" + Date.now().toString(36) + Math.random().toString(36).slice(2, 6)).current;
  const [messages, setMessages] = React.useState([{ role: "assistant", content: t("wing.greeting") }]);
  const [input, setInput] = React.useState("");
  const [busy, setBusy] = React.useState(false);
  const [stream, setStream] = React.useState(null);
  const [confirmed, setConfirmed] = React.useState({});
  const scrollRef = React.useRef();
  const inputRef = React.useRef();
  const dialogRef = React.useRef(null);
  const prevOpen = React.useRef(wingOpen);
  const hasKey = (store.apiKeys || []).some(k => k.id === "ai" && k.value && /^sk-/.test(k.value));

  React.useEffect(() => { if (scrollRef.current) scrollRef.current.scrollTop = scrollRef.current.scrollHeight; }, [messages, busy, stream]);
  React.useEffect(() => { if (wingOpen && inputRef.current) setTimeout(() => inputRef.current && inputRef.current.focus(), 60); }, [wingOpen]);

  // Esc to close
  React.useEffect(() => {
    if (!wingOpen) return;
    const onKey = (e) => { if (e.key === "Escape") setWingOpen(false); };
    window.addEventListener("keydown", onKey);
    return () => window.removeEventListener("keydown", onKey);
  }, [wingOpen]);

  // restore focus to the launcher when the dialog closes (keyboard a11y)
  React.useEffect(() => {
    if (prevOpen.current && !wingOpen) { const b = document.querySelector(".wing-launcher"); if (b) b.focus(); }
    prevOpen.current = wingOpen;
  }, [wingOpen]);

  // trap Tab focus inside the open dialog (aria-modal contract)
  const trapTab = (e) => {
    if (e.key !== "Tab" || !dialogRef.current) return;
    const f = [...dialogRef.current.querySelectorAll('button, input, a[href], select, textarea, [tabindex]:not([tabindex="-1"])')].filter(el => !el.disabled && el.offsetParent !== null);
    if (!f.length) return;
    const first = f[0], last = f[f.length - 1];
    if (e.shiftKey && document.activeElement === first) { e.preventDefault(); last.focus(); }
    else if (!e.shiftKey && document.activeElement === last) { e.preventDefault(); first.focus(); }
  };

  // persist transcript whenever it grows past the greeting
  React.useEffect(() => {
    if (messages.length <= 1) return;
    const lastCard = [...messages].reverse().find(m => m.card);
    const outcome = lastCard ? (lastCard.card.type === "escalate" ? "Escalated" : confirmed[messages.indexOf(lastCard)] === true ? "Booked" : "Quoted") : "Chat";
    const firstUser = messages.find(m => m.role === "user");
    saveConversation(sessionId, messages.map(m => ({ role: m.role, content: m.content, card: m.card || null })), {
      who: (store.searchCtx && firstUser ? "Web visitor" : "Web visitor"), outcome, channel: hasKey ? "Anthropic" : "Mr. Wing",
      preview: firstUser ? firstUser.content : "",
    });
  }, [messages, confirmed]);

  const send = async (text) => {
    const content = (text || "").trim();
    if (!content || busy) return;
    const next = [...messages, { role: "user", content }];
    setMessages(next);
    setInput("");
    setBusy(true);
    setStream("");
    let acc = "";
    const onToken = (tok) => { acc += tok; setStream(acc.split("```action")[0].trim()); };
    try {
      const res = await window.runWing({ store, lang, messages: next, onToken });
      setMessages(m => [...m, { role: "assistant", content: res.clean || "…", card: res.card, source: res.source }]);
    } catch (e) {
      setMessages(m => [...m, { role: "assistant", content: t("wing.netError") }]);
    } finally {
      setBusy(false); setStream(null);
    }
  };

  React.useEffect(() => {
    if (wingSeed && wingOpen) { send(wingSeed); setWingSeed(null); }
    // eslint-disable-next-line
  }, [wingSeed, wingOpen]);

  const onConfirm = (idx, card) => {
    if (card.type === "cancel") {
      if (card.bookingId) store.cancelBooking(card.bookingId);
      setMessages(m => [...m, { role: "assistant", content: t("wing.cancelledMsg") }]);
    } else if (card.mode === "modify") {
      if (card.bookingId) store.modifyBooking(card.bookingId, { date: card.newDate || undefined, status: "Confirmed", note: "Rescheduled by Mr. Wing" });
      setMessages(m => [...m, { role: "assistant", content: t("wing.modifiedMsg") }]);
    } else {
      const rec = store.addBooking({ type: card.mode || "flight", title: card.title, who: "Mr. Wing booking", amount: card.price || 0, channel: "Mr. Wing", date: (store.searchCtx && store.searchCtx.depart) || "2026-06-08", paidWith: card.pay });
      setMessages(m => [...m, { role: "assistant", content: t("wing.bookedMsg", { id: rec.id }) }]);
    }
    setConfirmed(c => ({ ...c, [idx]: true }));
  };

  const quick = lang === "ar"
    ? ["رحلة السعودية إلى جدة غدًا", "فندق في الرياض، ليلتان", "ألغِ رحلتي", "جناح كبار شخصيات في الريتز"]
    : ["Saudia to Jeddah tomorrow AM", "Hotel in Riyadh, 2 nights", "Cancel my flight", "VVIP suite at the Ritz"];

  return (
    <>
      {!wingOpen && !isMobile && (
        <button onClick={() => setWingOpen(true)} aria-label={t("wing.name")} className="wing-launcher"
          style={{ position: "fixed", insetInlineEnd: 26, bottom: 26, zIndex: 200, width: 62, height: 62, borderRadius: "50%", border: "none", cursor: "pointer", background: "linear-gradient(150deg,var(--emerald),var(--emerald-d))", boxShadow: "0 12px 34px rgba(60,45,28,.42)", display: "grid", placeItems: "center" }}>
          <span className="wing-ping" style={{ position: "absolute", inset: 0, borderRadius: "50%", border: "2px solid var(--gold)" }}></span>
          <WingMark size={32} dark={true} />
        </button>
      )}

      {wingOpen && (
        <div role="dialog" aria-modal="true" aria-label={t("wing.name") + " — " + t("wing.role")} ref={dialogRef} onKeyDown={trapTab} style={isMobile
          ? { position: "fixed", inset: 0, zIndex: 300, width: "100vw", height: "100dvh", display: "flex", flexDirection: "column", background: "var(--card)", animation: "wingIn .3s cubic-bezier(.2,.8,.2,1)" }
          : { position: "fixed", insetInlineEnd: 26, bottom: 26, zIndex: 200, width: 396, maxWidth: "calc(100vw - 32px)", height: 620, maxHeight: "calc(100vh - 52px)", display: "flex", flexDirection: "column", background: "var(--card)", borderRadius: "var(--r-xl)", boxShadow: "var(--shadow-lg)", border: "1px solid var(--line)", overflow: "hidden", animation: "wingIn .35s cubic-bezier(.2,.8,.2,1)" }}>
          <div style={{ display: "flex", alignItems: "center", gap: 12, padding: isMobile ? "calc(14px + env(safe-area-inset-top,0px)) 18px 14px" : "16px 18px", background: "linear-gradient(120deg,var(--emerald),var(--emerald-d))", color: "#fff", flexShrink: 0 }}>
            <WingAvatar size={42} />
            <div style={{ flex: 1 }}>
              <div style={{ fontWeight: 700, fontSize: 15.5 }}>{t("wing.name")}</div>
              <div style={{ fontSize: 12, color: "rgba(255,255,255,.8)", display: "flex", alignItems: "center", gap: 6 }}><span className="badge-dot" style={{ background: "#86C36A" }}></span> {t("wing.role")}</div>
            </div>
            <button onClick={() => setWingOpen(false)} aria-label={t("common.close")} style={{ background: "rgba(255,255,255,.15)", border: "none", color: "#fff", width: 32, height: 32, borderRadius: "50%", cursor: "pointer", display: "grid", placeItems: "center" }}><Icon name="x" size={17} /></button>
          </div>

          <div ref={scrollRef} role="log" aria-live="polite" style={{ flex: 1, overflowY: "auto", padding: 16, background: "var(--paper)", display: "flex", flexDirection: "column", gap: 12 }}>
            {messages.map((m, i) => (
              <div key={i} style={{ display: "flex", flexDirection: "column", gap: 6, alignItems: m.role === "user" ? "flex-end" : "flex-start" }}>
                {m.content && (
                  <div style={{ maxWidth: "86%", background: m.role === "user" ? "var(--emerald)" : "#fff", color: m.role === "user" ? "#fff" : "var(--ink)", border: m.role === "user" ? "none" : "1px solid var(--line)", padding: "11px 14px", borderRadius: 16, borderBottomRightRadius: m.role === "user" ? 4 : 16, borderBottomLeftRadius: m.role === "user" ? 16 : 4, fontSize: 14, lineHeight: 1.5, boxShadow: "var(--shadow-sm)", animation: "bubbleIn .3s ease", whiteSpace: "pre-wrap" }}>
                    {m.content}
                  </div>
                )}
                {m.card && (
                  <div style={{ width: "92%" }}>
                    <ConfirmCard card={m.card} done={confirmed[i]} onConfirm={() => onConfirm(i, m.card)} onCancel={() => { setConfirmed(c => ({ ...c, [i]: "no" })); setMessages(mm => [...mm, { role: "assistant", content: t("wing.declinedMsg") }]); }} />
                  </div>
                )}
              </div>
            ))}
            {busy && (stream ? (
              <div style={{ alignSelf: "flex-start", maxWidth: "86%", background: "#fff", color: "var(--ink)", border: "1px solid var(--line)", padding: "11px 14px", borderRadius: 16, borderBottomLeftRadius: 4, fontSize: 14, lineHeight: 1.5, whiteSpace: "pre-wrap" }}>{stream}</div>
            ) : (
              <div style={{ alignSelf: "flex-start", background: "#fff", border: "1px solid var(--line)", borderRadius: 16, borderBottomLeftRadius: 4 }}><TypingDots /></div>
            ))}
          </div>

          {messages.length <= 1 && !busy && (
            <div style={{ display: "flex", gap: 7, padding: "0 14px 10px", flexWrap: "wrap", background: "var(--paper)" }}>
              {quick.map(q => (
                <button key={q} onClick={() => send(q)} style={{ fontSize: 12, padding: "7px 12px", borderRadius: 100, border: "1px solid var(--line-2)", background: "#fff", color: "var(--ink-2)", cursor: "pointer", fontFamily: "var(--sans)" }}>{q}</button>
              ))}
            </div>
          )}

          <form onSubmit={e => { e.preventDefault(); send(input); }} style={{ display: "flex", gap: 9, padding: isMobile ? "12px 14px calc(12px + env(safe-area-inset-bottom,0px))" : 14, borderTop: "1px solid var(--line)", background: "var(--card)", flexShrink: 0 }}>
            <input ref={inputRef} className="input" value={input} onChange={e => setInput(e.target.value)} placeholder={t("wing.placeholder")} aria-label={t("wing.placeholder")} style={{ borderRadius: 100 }} />
            <button type="submit" disabled={busy || !input.trim()} aria-label={t("wing.confirm")} className="btn btn-primary flip-rtl" style={{ borderRadius: "50%", width: 46, height: 46, padding: 0, justifyContent: "center", flexShrink: 0, opacity: (busy || !input.trim()) ? 0.5 : 1 }}>
              <Icon name="arrow" size={19} />
            </button>
          </form>
        </div>
      )}
    </>
  );
}

Object.assign(window, { MrWing, ConfirmCard, TypingDots });
