/* ============================================================
   右下フローティング AIアシスタント（全認証画面に常駐）
   モードのタブは持たない。何を調べるか（社内ナレッジ／案件・顧客の横断／
   案件・顧客の詳細）は、質問の内容からサーバー側でAI自身が決める（API.assistantAsk）。
   いま開いている案件・顧客は毎回サーバーへ渡すので「この案件の懸念は？」もそのまま通る。
   ヘッダーのAIボタンで開くチャットパネル（挨拶・おすすめ質問・入力）。
   ============================================================ */
const FAQCHAT_SUGGEST_KEYS = ['faqchat.sug1', 'faqchat.sug2', 'faqchat.sug3', 'faqchat.sug4'];
const CASE_SUGGEST_KEYS = ['faqchat.caseSuggest1', 'faqchat.caseSuggest2', 'faqchat.caseSuggest3', 'faqchat.caseSuggest4'];
const CUST_SUGGEST_KEYS = ['faqchat.custSuggest1', 'faqchat.custSuggest2', 'faqchat.custSuggest3', 'faqchat.custSuggest4'];

/* 「考え中」の点が動く＝AIが処理中であることが一目で分かる。
   静止テキストだけだと、記録を読みに行く質問で10〜20秒かかった時に「固まった」と受け取られる。 */
function TypingDots() {
  return (
    <span style={{ display: 'inline-flex', gap: 4, alignItems: 'center', marginLeft: 4 }}>
      {[0, 1, 2].map(i => (
        <span key={i} style={{ width: 5, height: 5, borderRadius: '50%', background: '#7b828d',
          animation: 'dotBlink 1.3s infinite ease-in-out', animationDelay: (i * 0.18) + 's' }} />
      ))}
    </span>
  );
}

function FaqChat() {
  const { navigate, route, cases, customers, chatOpen: open, setChatOpen: setOpen, workspaceId } = useStore();
  const [msgs, setMsgs] = React.useState([]); // {role:'user'|'ai', text, sources?, refs?, err?}
  const [input, setInput] = React.useState('');
  const [busy, setBusy] = React.useState(false);
  const bodyRef = React.useRef(null);
  React.useEffect(() => { const el = bodyRef.current; if (el) el.scrollTop = el.scrollHeight; }, [msgs, busy, open]);
  /* 待ち時間に応じて文言を進める。記録を読みに行く質問はサーバーが毎回コンテキストを
     組み直すので10〜20秒かかる。進み具合が出ていないと止まったように見える。 */
  const [waited, setWaited] = React.useState(0);
  React.useEffect(() => {
    if (!busy) { setWaited(0); return; }
    const id = setInterval(() => setWaited(w => w + 1), 1000);
    return () => clearInterval(id);
  }, [busy]);

  /* いま画面で開いている相手。「この案件」の指し先としてサーバーへ渡すのと、
     おすすめ質問をその相手向けに差し替えるのに使う。 */
  const ctx = React.useMemo(() => {
    const D = window.APP_DATA || {};
    if (!route || !route.id) return null;
    if (route.screen === 'case') {
      const k = (cases || []).find(x => x.id === route.id) || (D.caseById && D.caseById(route.id));
      if (!k) return null;
      const cu = (D.customer && D.customer(k.customerId)) || null;
      return { type: 'case', id: k.id, label: [(cu && cu.company) || '', k.title || ''].filter(Boolean).join('／') || k.id };
    }
    if (route.screen === 'customer') {
      const cu = (customers || []).find(x => x.id === route.id) || (D.customer && D.customer(route.id));
      return cu ? { type: 'customer', id: cu.id, label: cu.company || cu.id } : null;
    }
    return null;
  }, [route.screen, route.id, cases, customers]);

  const ask = async (qRaw) => {
    const q = String(qRaw != null ? qRaw : input).trim();
    if (!q || busy) return;
    setInput('');
    const prev = msgs;
    setMsgs(m => [...m, { role: 'user', text: q }]);
    setBusy(true);
    try {
      // 直近の往復だけを渡す（サーバー側でも8件・1件1000字に切り詰められる）
      const history = prev.slice(-8).map(m => ({ role: m.role === 'ai' ? 'assistant' : 'user', content: m.text }));
      const r = await API.assistantAsk(q, history, ctx && ctx.type, ctx && ctx.id, workspaceId);
      setMsgs(m => [...m, { role: 'ai', text: (r && r.answer) || t('faqchat.noAnswer'), sources: (r && r.sources) || [], refs: (r && r.refs) || [] }]);
    }
    catch (e) { setMsgs(m => [...m, { role: 'ai', text: (e && e.message) || t('faqchat.error'), sources: [], refs: [], err: true }]); }
    setBusy(false);
  };
  // refs（案件/顧客）をクリック→該当画面へ遷移してチャットを閉じる
  const goRef = (rf) => {
    if (!rf || !rf.id) return;
    navigate(rf.type === 'customer' ? 'customer' : 'case', rf.id); setOpen(false);
  };

  if (!open) return null;

  const bubble = (role, children, err) => (
    <div style={{ display: 'flex', justifyContent: role === 'user' ? 'flex-end' : 'flex-start', marginBottom: 10 }}>
      <div style={{ maxWidth: '84%', padding: '9px 12px', borderRadius: 12, fontSize: 13, lineHeight: 1.7, whiteSpace: 'pre-wrap', wordBreak: 'break-word',
        background: role === 'user' ? '#4a5af0' : (err ? '#fdecec' : '#f1f2f6'), color: role === 'user' ? '#fff' : (err ? '#b91c1c' : '#2b2f38') }}>{children}</div>
    </div>
  );
  // 開いている相手がいれば、おすすめ質問をその相手向けに差し替える
  const suggests = (ctx ? (ctx.type === 'case' ? CASE_SUGGEST_KEYS : CUST_SUGGEST_KEYS) : FAQCHAT_SUGGEST_KEYS).map(k => t(k));
  const greeting = ctx ? t(ctx.type === 'case' ? 'faqchat.greeting.ctxCase' : 'faqchat.greeting.ctxCustomer', { name: ctx.label }) : t('faqchat.greeting');
  return (
    <div style={{ position: 'fixed', right: 22, bottom: 22, zIndex: 400, width: 'min(380px, calc(100vw - 32px))', height: 'min(560px, calc(100vh - 100px))', background: '#fff', borderRadius: 16, boxShadow: '0 20px 60px rgba(20,22,40,.3)', display: 'flex', flexDirection: 'column', overflow: 'hidden', border: '1px solid #e6e8ec' }}>
      <div style={{ display: 'flex', alignItems: 'center', gap: 11, padding: '13px 16px', background: '#1d2129', flex: '0 0 auto' }}>
        <div style={{ width: 38, height: 38, borderRadius: '50%', background: '#4a5af0', display: 'flex', alignItems: 'center', justifyContent: 'center', flex: '0 0 auto' }}>
          <Icon name="spark" size={19} fill="#fff" style={{ color: '#fff' }} />
        </div>
        <div style={{ flex: 1, minWidth: 0 }}>
          <div style={{ fontSize: 14, fontWeight: 700, color: '#fff' }}>{t('faqchat.title')}</div>
          <div style={{ fontSize: 11.5, color: '#9aa1ab', display: 'flex', alignItems: 'center', gap: 5, overflow: 'hidden' }}>
            <span style={{ width: 7, height: 7, borderRadius: '50%', background: '#16a34a', flex: '0 0 auto' }} />
            {/* 相手の画面にいる時は、誰の話として聞かれるかを出す＝取り違え防止 */}
            <span style={{ overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' }}>{ctx ? ctx.label : t('faqchat.online')}</span>
          </div>
        </div>
        {msgs.length > 0 && (
          <span onClick={() => setMsgs([])} title={t('faqchat.clear')} style={{ cursor: 'pointer', color: '#9aa1ab', display: 'flex' }}><Icon name="refresh" size={16} stroke={2} /></span>
        )}
        <span onClick={() => setOpen(false)} style={{ cursor: 'pointer', color: '#9aa1ab', display: 'flex' }}><Icon name="x" size={18} stroke={2} /></span>
      </div>
      <div ref={bodyRef} style={{ flex: 1, overflowY: 'auto', padding: 16, background: '#fafbfc' }}>
        {bubble('ai', greeting)}
        {msgs.map((m, i) => (
          <React.Fragment key={i}>
            {bubble(m.role, m.text, m.err)}
            {m.role === 'ai' && m.sources && m.sources.length > 0 && (
              <div style={{ display: 'flex', flexWrap: 'wrap', gap: 5, margin: '-4px 0 12px 0' }}>
                {m.sources.slice(0, 4).map((s, j) => <span key={j} style={{ fontSize: 10.5, color: '#7b828d', background: '#eef0f3', borderRadius: 6, padding: '2px 7px' }}>{(s && (s.title || s.name)) || String(s)}</span>)}
              </div>
            )}
            {m.role === 'ai' && m.refs && m.refs.length > 0 && (
              <div style={{ display: 'flex', flexWrap: 'wrap', gap: 6, margin: '-2px 0 12px 0' }}>
                {m.refs.map((rf, j) => (
                  <button key={j} onClick={() => goRef(rf)} title={rf.label || rf.id}
                    style={{ fontSize: 11, color: '#4a5af0', background: '#eef0fe', border: '1px solid #dcdcfa', borderRadius: 7, padding: '3px 9px', cursor: 'pointer', fontFamily: 'inherit', fontWeight: 600, display: 'inline-flex', alignItems: 'center', gap: 4, maxWidth: '100%' }}>
                    <Icon name={rf.type === 'customer' ? 'customers' : 'cases'} size={11} stroke={2} style={{ flex: '0 0 auto' }} />
                    <span style={{ overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' }}>{rf.label || rf.id}</span>
                  </button>
                ))}
              </div>
            )}
          </React.Fragment>
        ))}
        {busy && bubble('ai', (
          <span style={{ display: 'inline-flex', alignItems: 'center' }}>
            {waited < 6 ? t('faqchat.thinking') : waited < 15 ? t('faqchat.thinkingCtx2') : t('faqchat.thinkingCtx3')}
            <TypingDots />
          </span>
        ))}
        {msgs.length === 0 && (
          <div style={{ display: 'flex', flexWrap: 'wrap', gap: 7, marginTop: 4 }}>
            {suggests.map((s, i) => <button key={i} onClick={() => ask(s)} style={{ border: '1px solid #d9d8f7', background: '#fff', color: '#4a5af0', borderRadius: 999, padding: '6px 12px', fontSize: 12, fontWeight: 600, cursor: 'pointer', fontFamily: 'inherit' }}>{s}</button>)}
          </div>
        )}
      </div>
      <div style={{ display: 'flex', alignItems: 'flex-end', gap: 8, padding: 12, borderTop: '1px solid #eef0f3', background: '#fff', flex: '0 0 auto' }}>
        <textarea value={input} onChange={(e) => setInput(e.target.value)} onKeyDown={(e) => { if (enterSubmits(e) && !e.shiftKey) { e.preventDefault(); ask(); } }} rows={1} placeholder={t('faqchat.placeholder')}
          style={{ flex: 1, border: '1px solid #e2e5ea', borderRadius: 10, padding: '9px 11px', fontSize: 13, fontFamily: 'inherit', resize: 'none', outline: 'none', lineHeight: 1.5, maxHeight: 100 }} />
        <button onClick={() => ask()} disabled={busy || !input.trim()}
          style={{ width: 38, height: 38, borderRadius: '50%', background: (input.trim() && !busy) ? '#4a5af0' : '#cdd2da', border: 'none', cursor: (input.trim() && !busy) ? 'pointer' : 'default', display: 'flex', alignItems: 'center', justifyContent: 'center', flex: '0 0 auto' }}>
          <Icon name="arrowRight" size={18} stroke={2.2} style={{ color: '#fff' }} />
        </button>
      </div>
      <div style={{ fontSize: 10.5, color: '#b4bac3', textAlign: 'center', padding: '0 0 8px', background: '#fff', flex: '0 0 auto' }}>{t('faqchat.poweredBy')}</div>
    </div>
  );
}
Object.assign(window, { FaqChat });
