// ╔══════════════════════════════════════════════════════════════════╗
// ║  chat-widget.jsx — Sweepify live-chat support widget               ║
// ║  Floating launcher + panel. Talks to the dashboard-api chat routes ║
// ║  (/api/chat/session|message|poll|event), which proxy Replicate     ║
// ║  (anthropic/claude-4-sonnet) and log to dash_chat_*.               ║
// ║  The persona + conversation are built HERE (client-side).          ║
// ╚══════════════════════════════════════════════════════════════════╝
(function () {
  const { useState, useRef, useEffect } = React;

  // ── Deep, whole-dashboard knowledge. Edit freely. ──
  const SYSTEM_PROMPT = `You are Sweepify's friendly support assistant, embedded in the customer dashboard at dashboard.sweepify.io. You help logged-in customers with their reports, scans, tokens, billing questions, and privacy. Be warm, concise and clear — short paragraphs or bullet points. Never invent facts; if unsure, say so and point them to email support (the address is on the Support page).

ABOUT SWEEPIFY
Sweepify is a people-search and online-investigation platform. Customers run scans on a person (or a photo) to uncover identity, location, social profiles, dating activity and more — and can protect their own data with Privacy Shield. All searches are 100% anonymous: the person searched never sees who searched them; only publicly available sources are used.

PRODUCTS & TOKEN COSTS (scans are paid for with tokens)
- Person Check — 5,000 tokens. Find anyone: identity, location, employer, social profiles, dating activity and more. (Most popular.)
- Face Scan — 7,500 tokens. Upload a photo; match a face across social and image-indexed platforms.
- Dating App Scan — 5,000 tokens. Full sweep across dating apps, hidden profiles and recent activity.
- Tinder Sonar — COMING SOON (not available yet; never charged).
- Relationship Status — COMING SOON (not available yet; never charged).

TIMING
Most scans finish in under 2 minutes; Face Scan can take up to 5 minutes. The customer is notified when a report is ready. A report shows "Processing" until done, then "Completed".

TOKENS & TOP-UP (USD; tokens credited instantly, cashback included). Customers top up on the "Top Up" page.
- Starter — $4.99 → 5,500 tokens
- Popular — $9.99 → 13,440 tokens (most popular)
- Best Value — $19.99 → 31,625 tokens
- High Roller — $49.99 → 90,000 tokens

PRIVACY SHIELD (available now)
Suppresses the customer's own profile across 100+ people-search sites, so searches for them by name, phone or email return nothing. Tiers: Shield 30 — 25,000 tokens / 30 days; Shield+ — 100,000 tokens / 1 year (recommended); Lifetime Shield — 250,000 tokens / forever. Activated instantly after a one-time identity verification. Shield purchases are non-refundable (protection is active immediately). Manage/pause/cancel in Settings.

POLICIES
- Failed scans, and scans that return zero matches, are automatically refunded in tokens within 24 hours (a notification confirms it).
- Spent tokens are otherwise non-refundable. Unused token balances bought in the last 14 days can be refunded — but for that the customer must email support.
- Reports can be deleted from "My Searches" and are purged within 24 hours.
- Login is via a magic sign-in link sent to the email used at checkout — tell them to check spam/junk if they don't see it.

"WHERE'S MY REPORT?"
Use the customer's account context below if provided. If a report is "Processing", reassure them it usually completes within a couple of minutes and they'll be notified. If it's been much longer, or they say a report never arrived or looks wrong, treat it as an issue (see ESCALATION).

ESCALATION — IMPORTANT
For refund requests, billing problems, complaints, "my report never arrived / is wrong", or account/identity issues you can't resolve: tell the customer to email our support team and that they can find the email address on the Support page (in the dashboard menu → Support). NEVER write out or guess an email address yourself — the address can change, so always direct them to the Support page. You MAY still explain the relevant policy (e.g. the automatic refund for failed scans).

STYLE & SCOPE
- Be helpful and lightly proactive: if a customer is low on tokens you may mention Top Up; where relevant you may mention Privacy Shield — but never pushy.
- Stay on topic: Sweepify's product, the customer's account, and how-to. Politely decline unrelated requests.
- Refuse to help locate, stalk, harass or harm anyone; Sweepify is for legitimate, lawful checks only.
- Keep replies short unless the customer asks for detail.`;

  // Build the live per-user context block from the dashboard's already-loaded data.
  function buildUserContext(user) {
    if (!user) return '';
    const lines = ['CUSTOMER ACCOUNT CONTEXT (live data for THIS signed-in customer — use it to answer specifically):'];
    if (user.email) lines.push('Email: ' + user.email);
    if (typeof user.balance === 'number') lines.push('Token balance: ' + user.balance.toLocaleString('en-US'));
    const reports = Array.isArray(user.reports) ? user.reports : [];
    if (reports.length) {
      lines.push('Reports (' + reports.length + ', newest first):');
      reports.slice(0, 25).forEach((r) => {
        const product = (r.scans && r.scans[0]) || 'Report';
        const subj = r.name && r.name !== 'Identity Report' ? ' · subject: ' + r.name : '';
        lines.push('- ' + product + ' · ' + (r.status || '') + ' · ' + (r.date || '') + subj);
      });
    } else {
      lines.push('Reports: none yet.');
    }
    return lines.join('\n');
  }

  const GREETING = "Hi! 👋 I'm the Sweepify assistant. Ask me anything about your reports, scans, tokens, or Privacy Shield.";

  function SendIcon() {
    return (
      <svg width="18" height="18" viewBox="0 0 24 24" fill="none"><path d="M3.4 20.4 21 12 3.4 3.6 3 10l12 2-12 2 .4 6.4Z" fill="currentColor"/></svg>
    );
  }
  function ChatIcon() {
    return (
      <svg width="24" height="24" viewBox="0 0 24 24" fill="none"><path d="M4 5h16a1 1 0 0 1 1 1v10a1 1 0 0 1-1 1H9l-4 3.5V17H4a1 1 0 0 1-1-1V6a1 1 0 0 1 1-1Z" fill="currentColor"/></svg>
    );
  }

  function ChatWidget({ open, onOpen, onClose, user }) {
    const [messages, setMessages] = useState([{ role: 'assistant', content: GREETING }]);
    const [input, setInput] = useState('');
    const [sending, setSending] = useState(false);
    const sessionRef = useRef(null);
    const scrollRef = useRef(null);
    const startedRef = useRef(false);

    // Create the session once, the first time the panel opens.
    useEffect(() => {
      if (!open || startedRef.current) return;
      startedRef.current = true;
      (async () => {
        try {
          const r = await window.api.chatSession({
            referrer_url: location.href,
            metadata: { product: 'sweepify-dashboard' },
          });
          sessionRef.current = (r && r.session_id) || null;
        } catch (e) { /* chat still works without a logged session */ }
      })();
    }, [open]);

    // Auto-scroll to the newest message.
    useEffect(() => {
      const el = scrollRef.current;
      if (el) el.scrollTop = el.scrollHeight;
    }, [messages, sending]);

    const send = async () => {
      const text = input.trim();
      if (!text || sending) return;
      const history = [...messages, { role: 'user', content: text }];
      setMessages(history);
      setInput('');
      setSending(true);

      // Build the prompt (full transcript) + system prompt (persona + live user context).
      const convo = history
        .filter((m) => m.role === 'user' || m.role === 'assistant')
        .map((m) => (m.role === 'user' ? 'Human: ' : 'Assistant: ') + m.content)
        .join('\n\n');
      const prompt = convo + '\n\nAssistant:';
      const systemPrompt = SYSTEM_PROMPT + '\n\n' + buildUserContext(user);

      try {
        const created = await window.api.chatMessage({
          session_id: sessionRef.current,
          user_message: text,
          prompt,
          system_prompt: systemPrompt,
          source: 'dashboard',
        });
        const id = created && created.id;
        if (!id) throw new Error('no prediction id');

        // Poll until the model finishes.
        let out = null, status = created.status;
        for (let i = 0; i < 40 && status !== 'succeeded' && status !== 'failed' && status !== 'canceled'; i++) {
          await new Promise((res) => setTimeout(res, 1200));
          const p = await window.api.chatPoll(id, sessionRef.current);
          status = p.status;
          if (status === 'succeeded') out = (p.text || '').trim();
        }
        if (out) {
          setMessages((m) => [...m, { role: 'assistant', content: out }]);
        } else {
          setMessages((m) => [...m, { role: 'assistant', content: "Sorry — I couldn't reach our assistant just now. Please try again, or email our team (you'll find the address on the Support page)." }]);
        }
      } catch (e) {
        setMessages((m) => [...m, { role: 'assistant', content: "Sorry — something went wrong. Please try again in a moment, or email our team (the address is on the Support page)." }]);
      } finally {
        setSending(false);
      }
    };

    const onKey = (e) => {
      if (e.key === 'Enter' && !e.shiftKey) { e.preventDefault(); send(); }
    };

    return (
      <>
        {/* Launcher bubble — always visible */}
        <button
          className={'swchat-fab' + (open ? ' is-hidden' : '')}
          aria-label="Open support chat"
          onClick={onOpen}
        >
          <ChatIcon />
        </button>

        {open && (
          <div className="swchat-panel" role="dialog" aria-label="Sweepify support chat">
            <div className="swchat-head">
              <div className="swchat-head__id">
                <span className="swchat-head__dot" />
                <div>
                  <div className="swchat-head__title">Sweepify Support</div>
                  <div className="swchat-head__sub">Typically replies in a moment</div>
                </div>
              </div>
              <button className="swchat-x" aria-label="Close chat" onClick={onClose}>
                <IconX size={18} />
              </button>
            </div>

            <div className="swchat-body" ref={scrollRef}>
              {messages.map((m, i) => (
                <div key={i} className={'swchat-msg swchat-msg--' + m.role}>
                  <div className="swchat-bubble">{m.content}</div>
                </div>
              ))}
              {sending && (
                <div className="swchat-msg swchat-msg--assistant">
                  <div className="swchat-bubble swchat-typing"><span/><span/><span/></div>
                </div>
              )}
            </div>

            <div className="swchat-input">
              <textarea
                rows={1}
                placeholder="Type your message…"
                value={input}
                onChange={(e) => setInput(e.target.value)}
                onKeyDown={onKey}
                aria-label="Message"
              />
              <button className="swchat-send" disabled={!input.trim() || sending} onClick={send} aria-label="Send">
                <SendIcon />
              </button>
            </div>
            <div className="swchat-foot">AI assistant · for refunds or account issues, email us (see Support)</div>
          </div>
        )}
      </>
    );
  }

  // ── one-time styles ──
  if (!document.getElementById('swchat-styles')) {
    const s = document.createElement('style');
    s.id = 'swchat-styles';
    s.textContent = `
      .swchat-fab{position:fixed;right:22px;bottom:22px;z-index:120;width:58px;height:58px;border:0;border-radius:999px;background:var(--sw-blue-primary,#2563EB);color:#fff;box-shadow:0 12px 30px rgba(37,99,235,.42);cursor:pointer;display:inline-flex;align-items:center;justify-content:center;transition:transform 160ms ease,box-shadow 160ms ease;}
      .swchat-fab:hover{transform:translateY(-2px);box-shadow:0 16px 38px rgba(37,99,235,.5);}
      .swchat-fab.is-hidden{display:none;}
      .swchat-panel{position:fixed;right:22px;bottom:22px;z-index:121;width:374px;max-width:calc(100vw - 32px);height:560px;max-height:calc(100vh - 40px);background:#fff;border-radius:20px;box-shadow:0 30px 80px rgba(15,23,42,.34);display:flex;flex-direction:column;overflow:hidden;animation:swchat-in 200ms ease;}
      @keyframes swchat-in{from{opacity:0;transform:translateY(12px) scale(.98);}to{opacity:1;transform:none;}}
      .swchat-head{display:flex;align-items:center;justify-content:space-between;padding:14px 14px 14px 16px;background:var(--sw-blue-primary,#2563EB);color:#fff;}
      .swchat-head__id{display:flex;align-items:center;gap:10px;}
      .swchat-head__dot{width:9px;height:9px;border-radius:999px;background:#34D399;box-shadow:0 0 0 3px rgba(52,211,153,.3);flex:none;}
      .swchat-head__title{font-weight:800;font-size:15px;letter-spacing:-.01em;}
      .swchat-head__sub{font-size:12px;opacity:.85;}
      .swchat-x{width:32px;height:32px;border:0;border-radius:999px;background:rgba(255,255,255,.16);color:#fff;display:inline-flex;align-items:center;justify-content:center;cursor:pointer;transition:background 160ms ease;}
      .swchat-x:hover{background:rgba(255,255,255,.28);}
      .swchat-body{flex:1;overflow-y:auto;padding:16px;background:#F6F8FC;display:flex;flex-direction:column;gap:10px;}
      .swchat-msg{display:flex;}
      .swchat-msg--user{justify-content:flex-end;}
      .swchat-bubble{max-width:84%;padding:10px 13px;border-radius:14px;font-size:14px;line-height:1.45;white-space:pre-wrap;word-wrap:break-word;}
      .swchat-msg--assistant .swchat-bubble{background:#fff;color:#0F172A;border:1px solid #E2E8F0;border-bottom-left-radius:5px;}
      .swchat-msg--user .swchat-bubble{background:var(--sw-blue-primary,#2563EB);color:#fff;border-bottom-right-radius:5px;}
      .swchat-typing{display:inline-flex;gap:4px;align-items:center;}
      .swchat-typing span{width:7px;height:7px;border-radius:999px;background:#94A3B8;animation:swchat-bounce 1.2s infinite ease-in-out;}
      .swchat-typing span:nth-child(2){animation-delay:.15s;}
      .swchat-typing span:nth-child(3){animation-delay:.3s;}
      @keyframes swchat-bounce{0%,80%,100%{transform:scale(.6);opacity:.5;}40%{transform:scale(1);opacity:1;}}
      .swchat-input{display:flex;align-items:flex-end;gap:8px;padding:10px;border-top:1px solid #E2E8F0;background:#fff;}
      .swchat-input textarea{flex:1;border:1px solid #E2E8F0;border-radius:12px;padding:10px 12px;font:inherit;font-size:14px;resize:none;max-height:120px;outline:none;}
      .swchat-input textarea:focus{border-color:var(--sw-blue-primary,#2563EB);box-shadow:0 0 0 3px rgba(37,99,235,.12);}
      .swchat-send{flex:none;width:40px;height:40px;border:0;border-radius:12px;background:var(--sw-blue-primary,#2563EB);color:#fff;display:inline-flex;align-items:center;justify-content:center;cursor:pointer;transition:opacity 160ms ease;}
      .swchat-send:disabled{opacity:.45;cursor:not-allowed;}
      .swchat-foot{padding:8px 12px;font-size:11px;color:#94A3B8;text-align:center;background:#fff;border-top:1px solid #F1F5F9;}
      @media (max-width:640px){
        .swchat-panel{right:10px;left:10px;bottom:10px;width:auto;height:calc(100vh - 84px);}
        .swchat-fab{right:16px;bottom:84px;}
      }
    `;
    document.head.appendChild(s);
  }

  Object.assign(window, { ChatWidget });
})();
