// Floating AI assistant — bubble at bottom-right, expands to a slide-in chat panel.
// Used everywhere in the CRM except the full /#/ai screen.
// Talks to /api/ai/chat (same endpoint as the main AI asistent).

function FloatingAiAssistant() {
  const [open, setOpen] = React.useState(false);
  const [messages, setMessages] = React.useState(() => {
    try { return JSON.parse(localStorage.getItem('dd_ai_floater_msgs') || '[]'); }
    catch { return []; }
  });
  const [input, setInput] = React.useState('');
  const [files, setFiles] = React.useState([]);
  const [dragging, setDragging] = React.useState(false);
  const [sending, setSending] = React.useState(false);
  const [sendingStartedAt, setSendingStartedAt] = React.useState(null);
  const [model, setModel] = React.useState('auto');
  const [convoId, setConvoId] = React.useState(() => {
    const v = localStorage.getItem('dd_ai_floater_convo');
    return v ? Number(v) : null;
  });
  const [context, setContext] = React.useState(null);
  const [route, setRoute] = React.useState(() => window.location.hash.replace(/^#\/?/, '').split('?')[0] || 'dashboard');
  const scrollRef = React.useRef(null);
  const textareaRef = React.useRef(null);

  // Follow hash changes so we hide on /#/ai, /#/login, etc.
  React.useEffect(() => {
    const onHash = () => setRoute(window.location.hash.replace(/^#\/?/, '').split('?')[0] || 'dashboard');
    window.addEventListener('hashchange', onHash);
    return () => window.removeEventListener('hashchange', onHash);
  }, []);

  // Persist messages + convo id so the quick chat survives page reloads / route changes
  React.useEffect(() => {
    try { localStorage.setItem('dd_ai_floater_msgs', JSON.stringify(messages.slice(-30))); } catch {}
  }, [messages]);
  React.useEffect(() => {
    if (convoId) localStorage.setItem('dd_ai_floater_convo', String(convoId));
  }, [convoId]);

  // Load AI context when panel first opens.
  React.useEffect(() => {
    if (open && !context) {
      fetch('/api/ai/context', { credentials: 'same-origin' })
        .then(r => r.json())
        .then(j => { if (j && j.ok) setContext(j); })
        .catch(() => {});
    }
  }, [open, context]);

  // Auto-scroll on new messages / sending state
  React.useEffect(() => {
    if (scrollRef.current) scrollRef.current.scrollTop = scrollRef.current.scrollHeight;
  }, [messages, sending, open]);

  // Focus textarea on open
  React.useEffect(() => {
    if (open) setTimeout(() => textareaRef.current && textareaRef.current.focus(), 50);
  }, [open]);

  // Esc closes the panel
  React.useEffect(() => {
    if (!open) return;
    const onKey = (e) => { if (e.key === 'Escape') setOpen(false); };
    window.addEventListener('keydown', onKey);
    return () => window.removeEventListener('keydown', onKey);
  }, [open]);

  // Gating — don't render at all when:
  const session = window.currentSession;
  if (!session) return null;                              // not logged in
  if (route === 'ai') return null;                        // already on full AI screen
  if (route === 'login' || route === '2fa') return null;  // auth flow
  if (window.hasPerm && !window.hasPerm('ai.view')) return null;

  async function send(text) {
    const t = (text ?? input).trim();
    const hasFiles = files.length > 0;
    if ((!t && !hasFiles) || sending) return;
    let blocks = [], uiFiles = [];
    if (hasFiles) {
      try { ({ blocks, uiFiles } = await filesToAnthropicBlocks(files)); }
      catch (e) { alert(e.message); return; }
    }
    const userMsg = { role: 'user', content: buildUserContent(t, blocks), _ui_files: uiFiles };
    const next = [...messages, userMsg];
    setMessages(next); setInput(''); setFiles([]); setSending(true); setSendingStartedAt(Date.now());

    try {
      const wire = next.map(m => ({ role: m.role, content: m.content }));
      const r = await fetch('/api/ai/chat', {
        method: 'POST', credentials: 'same-origin',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({ messages: wire, model, conversation_id: convoId }),
      });
      const b = await r.json().catch(() => ({}));
      setSending(false); setSendingStartedAt(null);
      if (r.ok && b.ok) {
        setMessages([...next, {
          role: 'assistant', content: b.text,
          _meta: {
            model: b.model, auto_picked: b.auto_picked,
            tools: b.tools_used || [],
            skills_loaded: b.skills_loaded || [],
            navigate_to: b.navigate_to || null,
            input_tokens: b.usage?.input_tokens, output_tokens: b.usage?.output_tokens,
            duration_ms: b.duration_ms,
          },
        }]);
        setConvoId(b.conversation_id);
        // If AI triggered a navigation tool, redirect after a short delay
        // so the user can see the assistant's reply first.
        if (b.navigate_to && b.navigate_to.href) {
          setTimeout(() => {
            window.location.hash = b.navigate_to.href.replace(/^#/, '');
            setOpen(false);
            // Tiny toast so the user knows AI caused the nav
            try {
              const el = document.createElement('div');
              el.className = 'ai-nav-toast';
              el.innerHTML = `<span>✨</span> Otvorené z AI asistenta: <b>${(b.navigate_to.label || '').replace(/</g,'&lt;')}</b>`;
              document.body.appendChild(el);
              setTimeout(() => el.classList.add('fade'), 2500);
              setTimeout(() => el.remove(), 3200);
            } catch {}
          }, 900);
        }
      } else {
        const msg = b.message || b.error || 'Chyba pri volaní AI.';
        setMessages([...next, { role: 'assistant', content: `⚠️ ${msg}`, _error: true }]);
      }
    } catch (e) {
      setSending(false); setSendingStartedAt(null);
      setMessages([...next, { role: 'assistant', content: '⚠️ Sieťová chyba.', _error: true }]);
    }
  }

  function newChat() {
    setMessages([]); setConvoId(null);
    localStorage.removeItem('dd_ai_floater_msgs');
    localStorage.removeItem('dd_ai_floater_convo');
  }

  function openFull() {
    setOpen(false);
    // If we have a live convo, open it in the full screen
    if (convoId) sessionStorage.setItem('ai_open_convo', String(convoId));
    window.location.hash = '#/ai';
  }

  const modelShort = (m) => {
    if (!m || m === 'auto') return 'Auto';
    if (/haiku/i.test(m))  return 'Haiku';
    if (/sonnet/i.test(m)) return 'Sonnet';
    if (/opus/i.test(m))   return 'Opus';
    return m;
  };

  return (
    <>
      {/* Floating launcher bubble — sun icon with animated rays */}
      {!open && (
        <button
          className="ai-fab"
          onClick={() => setOpen(true)}
          aria-label="Otvoriť AI asistenta"
          title="Rýchly AI asistent"
        >
          <span className="ai-fab-sun" aria-hidden="true">
            {/* Soft outer halo — breathes */}
            <span className="ai-fab-halo"/>
            {/* Long rays rotating clockwise */}
            <svg className="ai-fab-rays ai-fab-rays-long" viewBox="0 0 100 100" width="80" height="80">
              <g stroke="#fff5d8" strokeWidth="3.5" strokeLinecap="round" fill="none">
                <line x1="50" y1="2"  x2="50" y2="16"/>
                <line x1="50" y1="84" x2="50" y2="98"/>
                <line x1="2"  y1="50" x2="16" y2="50"/>
                <line x1="84" y1="50" x2="98" y2="50"/>
              </g>
            </svg>
            {/* Short rays rotating counter-clockwise — creates layered depth */}
            <svg className="ai-fab-rays ai-fab-rays-short" viewBox="0 0 100 100" width="80" height="80">
              <g stroke="#ffd878" strokeWidth="3" strokeLinecap="round" fill="none">
                <line x1="14" y1="14" x2="22" y2="22"/>
                <line x1="78" y1="78" x2="86" y2="86"/>
                <line x1="14" y1="86" x2="22" y2="78"/>
                <line x1="78" y1="22" x2="86" y2="14"/>
              </g>
            </svg>
            {/* Dark contrast ring for visibility on light backgrounds */}
            <span className="ai-fab-ring"/>
            {/* Core orb */}
            <span className="ai-fab-core">
              {/* AI sparkle-star inside the sun */}
              <svg className="ai-fab-spark" viewBox="0 0 24 24" width="18" height="18">
                <path d="M12 2 L13.5 10.5 L22 12 L13.5 13.5 L12 22 L10.5 13.5 L2 12 L10.5 10.5 Z"
                      fill="#fff" fillOpacity="0.95"/>
              </svg>
            </span>
          </span>
          {messages.length > 0 && <span className="ai-fab-dot" aria-label="má rozpísanú konverzáciu"/>}
        </button>
      )}

      {/* Chat panel */}
      {open && (
        <>
          <div className="ai-fab-backdrop" onClick={() => setOpen(false)}/>
          <div className="ai-fab-panel" role="dialog" aria-label="AI asistent">
            {/* Header */}
            <div className="ai-fab-head">
              <div className="ai-fab-head-title">
                <div className="ai-avatar ai-avatar-bot" style={{width:28, height:28}}><Ico.sparkles/></div>
                <div style={{minWidth:0, flex:1}}>
                  <div style={{fontSize:13, fontWeight:600, color:'var(--ink-900)'}}>Rýchly AI asistent</div>
                  <div className="small muted" style={{fontSize:10.5, lineHeight:1.2, marginTop:1}}>
                    {context
                      ? <>{context.skills.length > 0 ? `${context.skills.length} skillov · ` : ''}{context.tools_count} nástrojov · {Object.values(context.integrations).filter(Boolean).length}/{Object.keys(context.integrations).length} integrácií</>
                      : 'Načítavam…'}
                  </div>
                </div>
              </div>
              <div className="ai-fab-head-actions">
                <select
                  className="input ai-fab-model"
                  value={model}
                  onChange={e => setModel(e.target.value)}
                  title="Model"
                >
                  <option value="auto">Auto</option>
                  <option value="claude-haiku-4-5-20251001">Haiku · rýchly</option>
                  <option value="claude-sonnet-4-6">Sonnet · vyvážený</option>
                  <option value="claude-opus-4-7">Opus · najsilnejší</option>
                </select>
                <button className="ai-fab-icon-btn" onClick={newChat} title="Nová konverzácia">
                  <Ico.plus/>
                </button>
                <button className="ai-fab-icon-btn" onClick={openFull} title="Otvoriť v plnom AI asistentovi">
                  <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
                    <path d="M7 17 17 7"/><path d="M7 7h10v10"/>
                  </svg>
                </button>
                <button className="ai-fab-icon-btn" onClick={() => setOpen(false)} title="Zavrieť (Esc)">
                  <Ico.x/>
                </button>
              </div>
            </div>

            {/* Messages */}
            <div ref={scrollRef} className="ai-fab-scroll">
              {messages.length === 0 ? (
                <div className="ai-fab-empty">
                  <div className="ai-fab-empty-hint">
                    Opýtaj sa čokoľvek — napr. <i>„koľko nevybavených objednávok?"</i>, <i>„posledné faktúry zo SF"</i>, alebo <i>„ktoré produkty sú vypredané?"</i>
                  </div>
                  <div className="ai-fab-suggestions">
                    {[
                      'Dnešné objednávky',
                      'Vypredané produkty',
                      'Posledné 3 faktúry',
                      'Alarmy z GoodWe',
                    ].map(q => (
                      <button key={q} className="ai-fab-suggestion" onClick={() => send(q)}>{q}</button>
                    ))}
                  </div>
                </div>
              ) : (
                messages.map((m, i) => <FabMessage key={i} m={m}/>)
              )}
              {sending && (
                <div className="hstack" style={{gap:10, alignItems:'flex-start', marginTop:10}}>
                  <div className="ai-avatar ai-avatar-bot" style={{width:26, height:26}}><Ico.sparkles/></div>
                  <TypingIndicator startedAt={sendingStartedAt} variant="small"/>
                </div>
              )}
            </div>

            {/* Input */}
            <div
              className={`ai-fab-input-wrap${dragging ? ' is-dragging' : ''}`}
              onDragOver={e => { e.preventDefault(); setDragging(true); }}
              onDragLeave={e => { e.preventDefault(); setDragging(false); }}
              onDrop={e => {
                e.preventDefault(); setDragging(false);
                const dropped = Array.from(e.dataTransfer?.files || []);
                if (dropped.length) setFiles(prev => [...prev, ...dropped].slice(0, AI_MAX_FILES));
              }}
            >
              {files.length > 0 && (
                <AttachmentPreviewRow files={files} onRemove={i => setFiles(prev => prev.filter((_, j) => j !== i))}/>
              )}
              <textarea
                ref={textareaRef}
                className="ai-fab-textarea"
                placeholder={dragging ? 'Pustite súbor(y) sem…' : 'Napíšte otázku… (Enter = odoslať)'}
                value={input}
                onChange={e => setInput(e.target.value)}
                onKeyDown={e => { if (e.key === 'Enter' && !e.shiftKey) { e.preventDefault(); send(); } }}
                onPaste={e => {
                  const pasted = Array.from(e.clipboardData?.files || []);
                  if (pasted.length) { e.preventDefault(); setFiles(prev => [...prev, ...pasted].slice(0, AI_MAX_FILES)); }
                }}
                disabled={sending}
                rows={2}
              />
              <div className="ai-fab-input-foot">
                <label className="ai-attach-btn ai-attach-btn-sm" title="Pripojiť súbor">
                  <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"><path d="m21.44 11.05-9.19 9.19a6 6 0 0 1-8.49-8.49l8.57-8.57A4 4 0 1 1 17.99 8.84l-8.59 8.57a2 2 0 1 1-2.83-2.83l8.49-8.49"/></svg>
                  <input type="file" multiple hidden
                    accept="image/jpeg,image/png,image/webp,image/gif,application/pdf,text/plain,text/csv,text/markdown,application/json"
                    onChange={e => {
                      const picked = Array.from(e.target.files || []);
                      if (picked.length) setFiles(prev => [...prev, ...picked].slice(0, AI_MAX_FILES));
                      e.target.value = '';
                    }}/>
                </label>
                <span className="small muted" style={{marginLeft:4}}>Model: <b>{modelShort(model)}</b></span>
                <button className="btn btn-primary btn-sm ai-fab-send" onClick={() => send()} disabled={sending || (!input.trim() && files.length === 0)}>
                  <svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.5" strokeLinecap="round"><path d="M5 12h14"/><path d="m12 5 7 7-7 7"/></svg>
                  Odoslať
                </button>
              </div>
            </div>
          </div>
        </>
      )}
    </>
  );
}

function FabMessage({ m }) {
  const isUser = m.role === 'user';
  const text = typeof plainTextOfContent === 'function'
    ? plainTextOfContent(m.content)
    : (typeof m.content === 'string' ? m.content : (Array.isArray(m.content) ? m.content.filter(b => b.type === 'text').map(b => b.text).join('\n') : ''));
  const html = !isUser && !m._error && typeof renderMarkdown === 'function' ? renderMarkdown(text) : null;
  const meta = m._meta || {};
  const hasBubble = !!text;
  return (
    <div className="hstack" style={{alignItems:'flex-start', gap:10, marginBottom:10}}>
      <div className={`ai-avatar ${isUser ? 'ai-avatar-user' : 'ai-avatar-bot'}`} style={{width:26, height:26, fontSize:10}}>
        {isUser ? 'JA' : <Ico.sparkles/>}
      </div>
      <div style={{flex:1, minWidth:0}}>
        {isUser && m._ui_files?.length > 0 && <InlineAttachments files={m._ui_files}/>}
        {hasBubble && (
        <div
          className={isUser ? 'ai-bubble ai-bubble-user' : (m._error ? 'ai-bubble ai-bubble-err' : 'ai-bubble ai-md')}
          style={{fontSize:12.5, padding:'8px 10px'}}
        >
          {html
            ? <div dangerouslySetInnerHTML={{ __html: html }}/>
            : <div style={{whiteSpace:'pre-wrap'}}>{text}</div>}
        </div>
        )}
        {!isUser && meta.navigate_to && (
          <a
            href={meta.navigate_to.href}
            onClick={() => { /* Let default hash navigation happen */ }}
            className="ai-nav-action"
          >
            <svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.2" strokeLinecap="round" strokeLinejoin="round">
              <path d="M7 17 17 7"/><path d="M7 7h10v10"/>
            </svg>
            {meta.navigate_to.label || 'Otvoriť'}
          </a>
        )}
        {!isUser && (meta.model || meta.tools?.length) && (
          <div className="ai-meta" style={{marginTop:4, gap:3}}>
            {meta.model && <span className="ai-chip ai-chip-model" style={{fontSize:9.5, padding:'1px 5px'}}>{(/haiku/i.test(meta.model) ? 'Haiku' : /opus/i.test(meta.model) ? 'Opus' : 'Sonnet')}</span>}
            {meta.tools?.length > 0 && <span className="ai-chip ai-chip-tool" style={{fontSize:9.5, padding:'1px 5px'}} title={meta.tools.join(', ')}>🔧 {meta.tools.length}</span>}
            {meta.duration_ms && <span className="ai-chip" style={{fontSize:9.5, padding:'1px 5px'}}>⏱ {(meta.duration_ms/1000).toFixed(1)}s</span>}
          </div>
        )}
      </div>
    </div>
  );
}

Object.assign(window, { FloatingAiAssistant });
