// support-widget.jsx — floating, glowing launcher with the Delz logo that opens
// a live iPhone-16 WhatsApp-style chat with your support agent.
//
// ╔══════════════════════════════════════════════════════════════════════╗
// ║  STEP 1 — PASTE YOUR SUPPORT-AGENT WEBHOOK URL BETWEEN THE QUOTES.      ║
// ║  Leave it empty ("") to run in demo mode (the agent echoes a reply).   ║
// ╚══════════════════════════════════════════════════════════════════════╝
const SUPPORT_WEBHOOK_URL = "https://oswald.app.n8n.cloud/webhook/37829724-c0e1-47db-97fd-4571678c230c";
//
// ✅ This is your n8n PRODUCTION URL. For it to reply in the browser, the n8n
//    Webhook node MUST have ALL of these (see chat for the full checklist):
//      • Workflow is ACTIVE (top-right toggle in n8n) — production URLs 404 otherwise
//      • HTTP Method = POST
//      • Respond = "Using Respond to Webhook node", and the flow ends in a
//        "Respond to Webhook" node that returns JSON like { "reply": "..." }
//      • Options → Allowed Origins (CORS) = *   (or your exact site domain)
//        — without this the browser blocks the response even when n8n runs fine
//
// What gets sent (HTTP POST, JSON body):
//   { "message": "<the user's text>", "sessionId": "<stable id>", "timestamp": 1700000000000 }
// What we read back (any ONE of these fields, or plain text):
//   { "reply": "..." }  ·  { "message": "..." }  ·  { "text": "..." }  ·  { "output": "..." }
//   (n8n "Respond to Webhook" arrays like [{ "reply": "..." }] also work.)

const SUPPORT_AGENT = {
  name: 'Customer Support',
  status: 'online',
  greeting: "Hi! 👋 I'm the Delz Ai Labs support agent. Ask me anything about our agents, channels or your service.",
};

function getSessionId() {
  try {
    let id = localStorage.getItem('delz_support_session');
    if (!id) { id = 'web-' + Math.random().toString(36).slice(2) + Date.now().toString(36); localStorage.setItem('delz_support_session', id); }
    return id;
  } catch (e) { return 'web-' + Date.now(); }
}

function extractReply(data) {
  if (data == null) return '';
  if (typeof data === 'string') return data;
  if (Array.isArray(data)) return extractReply(data[0]);
  if (data.json) return extractReply(data.json);
  return data.reply || data.message || data.text || data.output || data.answer || JSON.stringify(data);
}

async function callSupportAgent(text, sessionId) {
  if (!SUPPORT_WEBHOOK_URL) {
    await new Promise((r) => setTimeout(r, 650));
    return `You said: “${text}”.\n\n(Demo mode)`;
  }
  let res;
  try {
    res = await fetch(SUPPORT_WEBHOOK_URL, {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({ message: text, sessionId, timestamp: Date.now() }),
    });
  } catch (e) {
    const err = new Error('NETWORK');
    err.hint = "Couldn't reach the agent.is site's domain), Sorry .. we are working on it.";
    throw err;
  }
  if (!res.ok) {
    const err = new Error('HTTP ' + res.status);
    err.hint = res.status === 404
      ? 'The webhook returned 404 - activate the workflow in n8n (production URLs only work while the workflow is Active).'
      : 'The agent endpoint returned HTTP ' + res.status + '. Check the n8n execution log.';
    throw err;
  }
  const respBody = (await res.text()).trim();
  if (!respBody) {
    const err = new Error('EMPTY');
    err.hint = 'The agent accepted the message but sent no reply. Sorry .. we are working on it.';
    throw err;
  }
  try { return extractReply(JSON.parse(respBody)); } catch (e) { return respBody; }
}

function nowTime() {
  const d = new Date();
  return d.getHours().toString().padStart(2, '0') + ':' + d.getMinutes().toString().padStart(2, '0');
}

// Inline SVG icons — rendered by React directly so lucide.createIcons() never
// swaps a React-managed node (which would crash the widget on re-render).
function Ic({ name, size = 18, color = 'currentColor', sw = 1.9, style }) {
  const p = { width: size, height: size, viewBox: '0 0 24 24', fill: 'none', stroke: color, strokeWidth: sw, strokeLinecap: 'round', strokeLinejoin: 'round', 'aria-hidden': true, style };
  switch (name) {
    case 'chevron-left': return <svg {...p}><path d="M15 18l-6-6 6-6" /></svg>;
    case 'x': return <svg {...p}><path d="M18 6 6 18" /><path d="m6 6 12 12" /></svg>;
    case 'send': return <svg {...p}><path d="M14.536 21.686a.5.5 0 0 0 .937-.024l6.5-19a.496.496 0 0 0-.635-.635l-19 6.5a.5.5 0 0 0-.024.937l7.93 3.18a2 2 0 0 1 1.112 1.11z" /><path d="m21.854 2.147-10.94 10.939" /></svg>;
    case 'video': return <svg {...p}><path d="m22 8-6 4 6 4V8Z" /><rect width="14" height="12" x="2" y="6" rx="2" /></svg>;
    case 'phone': return <svg {...p}><path d="M22 16.92v3a2 2 0 0 1-2.18 2 19.79 19.79 0 0 1-8.63-3.07 19.5 19.5 0 0 1-6-6 19.79 19.79 0 0 1-3.07-8.67A2 2 0 0 1 4.11 2h3a2 2 0 0 1 2 1.72 12.84 12.84 0 0 0 .7 2.81 2 2 0 0 1-.45 2.11L8.09 9.91a16 16 0 0 0 6 6l1.27-1.27a2 2 0 0 1 2.11-.45 12.84 12.84 0 0 0 2.81.7A2 2 0 0 1 22 16.92Z" /></svg>;
    case 'lock': return <svg {...p}><rect width="18" height="11" x="3" y="11" rx="2" /><path d="M7 11V7a5 5 0 0 1 10 0v4" /></svg>;
    case 'check-check': return <svg {...p}><path d="M18 6 7 17l-5-5" /><path d="m22 10-7.5 7.5L13 16" /></svg>;
    default: return null;
  }
}

// — Reused iPhone chrome bits —
function WStatusIcons() {
  return (
    <span style={{ display: 'inline-flex', alignItems: 'center', gap: 6 }}>
      <svg width="17" height="11" viewBox="0 0 18 12" fill="#111" aria-hidden="true"><rect x="0" y="7.5" width="3" height="4.5" rx="1" /><rect x="5" y="5" width="3" height="7" rx="1" /><rect x="10" y="2.5" width="3" height="9.5" rx="1" /><rect x="15" y="0" width="3" height="12" rx="1" /></svg>
      <svg width="16" height="11" viewBox="0 0 16 12" fill="#111" aria-hidden="true"><path d="M8 2.3c2.35 0 4.5.92 6.1 2.42l-1.45 1.5A6.6 6.6 0 0 0 8 4.3a6.6 6.6 0 0 0-4.65 1.92L1.9 4.72A8.85 8.85 0 0 1 8 2.3zm0 3.8c1.2 0 2.3.47 3.13 1.24L8 10.6 4.87 7.34A4.55 4.55 0 0 1 8 6.1z" /></svg>
      <span style={{ display: 'inline-flex', alignItems: 'center', gap: 1.5 }}>
        <span style={{ width: 22, height: 11, borderRadius: 3, border: '1px solid rgba(0,0,0,0.4)', padding: 1.5, display: 'inline-flex' }}><span style={{ width: '82%', background: '#111', borderRadius: 1.5 }} /></span>
        <span style={{ width: 1.5, height: 4, background: 'rgba(0,0,0,0.4)', borderRadius: 1 }} />
      </span>
    </span>
  );
}

function ChatMsg({ side, text, time, read, pending }) {
  const out = side === 'out';
  return (
    <div style={{ alignSelf: out ? 'flex-end' : 'flex-start', maxWidth: '82%', background: out ? '#D9FDD3' : '#fff', color: '#111B21', fontSize: 13.5, lineHeight: 1.42, padding: '6px 9px', borderRadius: 8, borderTopRightRadius: out ? 2 : 8, borderTopLeftRadius: out ? 8 : 2, boxShadow: '0 1px 0.5px rgba(0,0,0,0.13)', whiteSpace: 'pre-wrap', wordBreak: 'break-word' }}>
      <span>{text}</span>
      {!pending && (
        <span style={{ float: 'right', display: 'inline-flex', alignItems: 'center', gap: 3, margin: '6px 0 -2px 10px' }}>
          <span style={{ fontSize: 10.5, color: '#667781' }}>{time}</span>
          {out && <Ic name="check-check" size={15} color={read ? '#53BDEB' : '#8696a0'} />}
        </span>
      )}
    </div>
  );
}

function TypingDots() {
  return (
    <div style={{ alignSelf: 'flex-start', background: '#fff', borderRadius: 8, borderTopLeftRadius: 2, padding: '9px 12px', boxShadow: '0 1px 0.5px rgba(0,0,0,0.13)', display: 'inline-flex', gap: 4 }}>
      {[0, 1, 2].map((i) => (
        <span key={i} style={{ width: 7, height: 7, borderRadius: '50%', background: '#9aa3ab', animation: 'dzTyping 1.2s ' + (i * 0.18) + 's infinite ease-in-out' }} />
      ))}
    </div>
  );
}

// iPhone side buttons (silent switch + volume on the left, power on the right)
function PhoneSideBtns() {
  const base = { position: 'absolute', background: 'linear-gradient(180deg,#42454c,#25272d)', boxShadow: 'inset 0 1px 1px rgba(255,255,255,0.18)', zIndex: 0 };
  return (
    <React.Fragment>
      <span aria-hidden="true" style={{ ...base, left: -2.5, top: '15%', width: 3, height: 22, borderRadius: '2px 0 0 2px' }} />
      <span aria-hidden="true" style={{ ...base, left: -2.5, top: '23%', width: 3, height: 46, borderRadius: '2px 0 0 2px' }} />
      <span aria-hidden="true" style={{ ...base, left: -2.5, top: '34%', width: 3, height: 46, borderRadius: '2px 0 0 2px' }} />
      <span aria-hidden="true" style={{ ...base, right: -2.5, top: '25%', width: 3, height: 60, borderRadius: '0 2px 2px 0' }} />
    </React.Fragment>
  );
}

function SupportWidget() {
  const [open, setOpen] = React.useState(false);
  const sessionId = React.useRef(getSessionId());
  const [messages, setMessages] = React.useState([
    { side: 'in', text: SUPPORT_AGENT.greeting, time: nowTime() },
  ]);
  const [draft, setDraft] = React.useState('');
  const [busy, setBusy] = React.useState(false);
  const scrollRef = React.useRef(null);
  const taRef = React.useRef(null);
  const panelRef = React.useRef(null);
  const fabRef = React.useRef(null);

  const autosize = () => {
    const el = taRef.current;
    if (!el) return;
    el.style.height = 'auto';
    el.style.height = Math.min(el.scrollHeight, 90) + 'px';
  };
  React.useEffect(autosize, [draft, open]);

  React.useEffect(() => {
    if (scrollRef.current) scrollRef.current.scrollTop = scrollRef.current.scrollHeight;
  }, [messages, busy, open]);

  // Click outside the chat (and not on the launcher) closes it; Esc also closes.
  React.useEffect(() => {
    if (!open) return;
    const onDoc = (e) => {
      if (panelRef.current && panelRef.current.contains(e.target)) return;
      if (fabRef.current && fabRef.current.contains(e.target)) return;
      setOpen(false);
    };
    const onEsc = (e) => { if (e.key === 'Escape') setOpen(false); };
    document.addEventListener('mousedown', onDoc);
    document.addEventListener('keydown', onEsc);
    return () => { document.removeEventListener('mousedown', onDoc); document.removeEventListener('keydown', onEsc); };
  }, [open]);

  const send = async () => {
    const text = draft.trim();
    if (!text || busy) return;
    setDraft('');
    setMessages((m) => [...m, { side: 'out', text, time: nowTime(), read: false }]);
    setBusy(true);
    try {
      const reply = await callSupportAgent(text, sessionId.current);
      setMessages((m) => m.map((x) => x.side === 'out' ? { ...x, read: true } : x).concat({ side: 'in', text: reply || '…', time: nowTime() }));
    } catch (e) {
      const hint = e && e.hint ? e.hint : "Couldn't reach the support agent just now. Please try again, or email hello@delzailabs.com.";
      setMessages((m) => m.concat({ side: 'in', text: hint, time: nowTime() }));
    } finally {
      setBusy(false);
    }
  };

  // Enter sends · Shift+Enter inserts a new line
  const onKey = (e) => { if (e.key === 'Enter' && !e.shiftKey) { e.preventDefault(); send(); } };

  return (
    <React.Fragment>
      {/* Chat panel */}
      <div ref={panelRef} style={{
        position: 'fixed', right: 'clamp(16px, 4vw, 26px)', bottom: 'calc(clamp(16px, 4vw, 26px) + 84px)', zIndex: 90,
        width: 'min(92vw, 312px)',
        transformOrigin: 'bottom right',
        transform: open ? 'translateY(0) scale(1)' : 'translateY(12px) scale(0.94)',
        opacity: open ? 1 : 0, pointerEvents: open ? 'auto' : 'none',
        transition: 'transform var(--dur-base) var(--ease-emphasis), opacity var(--dur-base) var(--ease-standard)',
      }}>
        <div style={{ position: 'relative', borderRadius: 56, padding: 6, background: 'linear-gradient(135deg,#5b5e66,#2c2e34 38%,#44464d 68%,#202227)', boxShadow: '0 30px 70px rgba(7,12,36,0.5), 0 4px 14px rgba(7,12,36,0.4), inset 0 0 0 1px rgba(255,255,255,0.16), 0 0 0 1.5px rgba(0,0,0,0.45)' }}>
          <PhoneSideBtns />
          <div style={{ position: 'relative', zIndex: 1, borderRadius: 50, overflow: 'hidden', height: 'min(600px, calc(100dvh - 120px))', display: 'flex', flexDirection: 'column', background: '#E4DDD4' }}>
            <div aria-hidden style={{ position: 'absolute', top: 10, left: '50%', transform: 'translateX(-50%)', width: 100, height: 28, background: '#000', borderRadius: 14, zIndex: 6, display: 'flex', alignItems: 'center', justifyContent: 'flex-end', paddingRight: 10 }}>
              <span style={{ width: 8, height: 8, borderRadius: '50%', background: 'radial-gradient(circle at 35% 35%, #2b3550, #05070d)' }} />
            </div>
            {/* status bar */}
            <div style={{ display: 'flex', alignItems: 'flex-end', justifyContent: 'space-between', padding: '0 22px 5px', height: 48, background: '#F7F7F7', zIndex: 2 }}>
              <span style={{ fontSize: 14.5, fontWeight: 600, color: '#111', letterSpacing: '0.3px' }}>{nowTime()}</span>
              <WStatusIcons />
            </div>
            {/* chat header */}
            <div style={{ display: 'flex', alignItems: 'center', gap: 6, padding: '6px 9px 9px', background: '#F7F7F7', borderBottom: '0.5px solid #d6d6d6' }}>
              <button onClick={() => setOpen(false)} aria-label="Close chat" style={{ border: 'none', outline: 'none', WebkitTapHighlightColor: 'transparent', background: 'transparent', padding: 0, cursor: 'pointer', display: 'inline-flex', marginRight: -2 }}>
                <Ic name="chevron-left" size={22} color="#007a6c" />
              </button>
              <span style={{ width: 38, height: 38, borderRadius: '50%', background: '#fff', border: '0.5px solid #e0e0e0', display: 'inline-flex', alignItems: 'center', justifyContent: 'center', flex: 'none', overflow: 'hidden' }}>
                <img src="assets/logo-mark.png" alt="" style={{ width: 34, height: 34, objectFit: 'contain' }} />
              </span>
              <div style={{ flex: 1, minWidth: 0 }}>
                <div style={{ fontSize: 14, fontWeight: 600, color: '#111', whiteSpace: 'nowrap', overflow: 'hidden', textOverflow: 'ellipsis' }}>{SUPPORT_AGENT.name}</div>
                <div style={{ fontSize: 11, color: '#8a8a8e' }}>{busy ? 'typing…' : SUPPORT_AGENT.status}</div>
              </div>
              <div style={{ display: 'flex', alignItems: 'center', gap: 13, color: '#007a6c', flex: 'none' }}>
                <Ic name="video" size={19} color="#007a6c" />
                <Ic name="phone" size={17} color="#007a6c" />
              </div>
            </div>
            {/* messages */}
            <div ref={scrollRef} style={{ flex: 1, overflowY: 'auto', overscrollBehavior: 'contain', WebkitOverflowScrolling: 'touch', touchAction: 'pan-y', display: 'flex', flexDirection: 'column', gap: 6, padding: '12px 9px', background: '#E4DDD4', backgroundImage: 'radial-gradient(rgba(0,0,0,0.03) 1px, transparent 1px)', backgroundSize: '18px 18px' }}>
              <div style={{ alignSelf: 'center', maxWidth: '92%', textAlign: 'center', background: '#FCF4CB', color: '#766f56', fontSize: 10.5, lineHeight: 1.45, padding: '5px 10px', borderRadius: 7, boxShadow: '0 1px 0.5px rgba(0,0,0,0.08)', marginBottom: 2 }}>
                <Ic name="lock" size={10} sw={2.4} color="#766f56" style={{ verticalAlign: 'middle', marginRight: 3, display: 'inline-block' }} />Messages and calls are end-to-end encrypted.Only people in this chat can read, listen to, or share them.
              </div>
              {messages.map((m, i) => <ChatMsg key={i} {...m} />)}
              {busy && <TypingDots />}
            </div>
            {/* input */}
            <div style={{ display: 'flex', alignItems: 'flex-end', gap: 7, padding: '7px 9px', background: '#F7F7F7' }}>
              <Ic name="plus" size={25} color="#007a6c" style={{ flex: 'none', marginBottom: 4 }} />
              <div style={{ flex: 1, display: 'flex', alignItems: 'flex-end', gap: 6, background: '#fff', borderRadius: 18, padding: '7px 12px', border: '0.5px solid #e2e2e2' }}>
                <textarea ref={taRef} value={draft} onChange={(e) => setDraft(e.target.value)} onKeyDown={onKey} placeholder="Message" aria-label="Message" rows={1}
                  style={{ flex: 1, border: 'none', outline: 'none', boxShadow: 'none', WebkitTapHighlightColor: 'transparent', background: 'transparent', fontFamily: 'var(--font-body)', fontSize: 13.5, lineHeight: 1.38, color: '#111', resize: 'none', overflowY: 'auto', overscrollBehavior: 'contain', maxHeight: 84, padding: 0, margin: 0, display: 'block' }} />
                {!draft.trim() && <Ic name="camera" size={18} color="#8696a0" style={{ flex: 'none', marginBottom: 1 }} />}
              </div>
              <button onClick={send} aria-label={draft.trim() ? 'Send' : 'Voice message'} disabled={busy}
                style={{ width: 34, height: 34, borderRadius: '50%', border: 'none', outline: 'none', WebkitTapHighlightColor: 'transparent', background: '#00A884', display: 'inline-flex', alignItems: 'center', justifyContent: 'center', color: '#fff', flex: 'none', cursor: (draft.trim() && !busy) ? 'pointer' : 'default', opacity: busy ? 0.55 : 1, transition: 'opacity var(--dur-fast) var(--ease-standard)' }}>
                <Ic name={draft.trim() ? 'send' : 'mic'} size={17} color="#fff" />
              </button>
            </div>
            {/* home indicator */}
            <div style={{ display: 'flex', justifyContent: 'center', padding: '5px 0 8px', background: '#F7F7F7' }}><span style={{ width: 128, height: 5, borderRadius: 3, background: '#111' }} /></div>
          </div>
        </div>
      </div>

      {/* Floating launcher */}
      <button ref={fabRef} onClick={() => setOpen((v) => !v)} aria-label={open ? 'Close support chat' : 'Chat with Delz support'} className="dz-fab"
        style={{ position: 'fixed', right: 'clamp(16px, 4vw, 26px)', bottom: 'clamp(16px, 4vw, 26px)', zIndex: 91,
          width: 66, height: 66, borderRadius: '50%', border: 'none', outline: 'none', WebkitTapHighlightColor: 'transparent', cursor: 'pointer', padding: 0,
          background: 'var(--gradient-brand, linear-gradient(140deg,#F26A1F,#1B3FC4))',
          display: 'inline-flex', alignItems: 'center', justifyContent: 'center' }}>
        <span className="dz-fab-glow" aria-hidden="true" />
        <span style={{ position: 'relative', width: 58, height: 58, borderRadius: '50%', background: 'rgba(255,255,255,0.96)', display: 'inline-flex', alignItems: 'center', justifyContent: 'center', boxShadow: 'inset 0 1px 2px rgba(0,0,0,0.12)' }}>
          {open
            ? <Ic name="x" size={26} sw={2.2} color="var(--navy-ink)" />
            : <img src="assets/logo-mark.png" alt="" style={{ width: 70, height: 70, objectFit: 'contain' }} />}
        </span>
        {!open && <span className="dz-fab-badge" aria-hidden="true">1</span>}
      </button>
    </React.Fragment>
  );
}

(function mountSupport() {
  if (!window.React || !window.ReactDOM || !document.getElementById('support-root')) {
    return setTimeout(mountSupport, 40);
  }
  ReactDOM.createRoot(document.getElementById('support-root')).render(<SupportWidget />);
})();
