// AI Chat modal – Gemini-powered (real REST API, works on the deployed static site).
// NOTE: key embedded client-side = prototype-only. For prod, proxy via /v1/chat.
//
// IMPORTANT: Direct calls to generativelanguage.googleapis.com fail with
// "User location is not supported" from RU/BY IPs (Google geo-block). We route
// through our own nginx proxy on vectory-backend (us-central1-c) which is in
// a supported region. If the proxy is unreachable, we fall back to the direct
// URL so dev environments outside the block still work.
const GEMINI_API_KEY = 'AIzaSyABtomEtpNBNJTPp5gEOIKpxPBRBO7odig';
// gemini-2.0-flash was retired by Google (404 "no longer available", May 2026).
// Switched to gemini-2.5-flash, which is the current stable fast model.
const GEMINI_MODEL = 'gemini-2.5-flash';
// Relative same-origin path. On vectory.space/migronis2 it hits vectory's nginx
// proxy directly; on migronis.com the Cloudflare Worker forwards /gemini-proxy/*
// to vectory server-side (avoids the cross-origin CORS block on the new domain).
const GEMINI_PROXY_URL  = `/gemini-proxy/models/${GEMINI_MODEL}:generateContent?key=${GEMINI_API_KEY}`;
const GEMINI_DIRECT_URL = `https://generativelanguage.googleapis.com/v1beta/models/${GEMINI_MODEL}:generateContent?key=${GEMINI_API_KEY}`;

async function callGemini(systemContext, history, userText) {
  const contents = [];
  contents.push({ role: 'user', parts: [{ text: systemContext }] });
  contents.push({ role: 'model', parts: [{ text: 'Понял. Отвечаю по реальному портфелю Migronis, кратко и по делу, без юридических гарантий, в конце рекомендую бесплатную консультацию.' }] });
  for (const m of history) {
    contents.push({ role: m.role === 'user' ? 'user' : 'model', parts: [{ text: m.content }] });
  }
  contents.push({ role: 'user', parts: [{ text: userText }] });

  const body = JSON.stringify({
    contents,
    generationConfig: {
      temperature: 0.55, maxOutputTokens: 900, topP: 0.95,
      // gemini-2.5-flash "thinks" by default and can spend the whole output
      // budget on hidden reasoning, returning an empty answer. Disable it.
      thinkingConfig: { thinkingBudget: 0 },
    },
    safetySettings: [
      { category: 'HARM_CATEGORY_HARASSMENT', threshold: 'BLOCK_ONLY_HIGH' },
      { category: 'HARM_CATEGORY_HATE_SPEECH', threshold: 'BLOCK_ONLY_HIGH' },
    ],
  });

  // Primary: proxy (works from any region). Fallback: direct call.
  const tryFetch = async (url) => {
    const res = await fetch(url, {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body,
    });
    if (!res.ok) {
      const errText = await res.text().catch(() => '');
      throw new Error(`Gemini API ${res.status} ${errText.slice(0, 140)}`);
    }
    return res.json();
  };
  let data;
  try {
    data = await tryFetch(GEMINI_PROXY_URL);
  } catch (proxyErr) {
    console.warn('[AIChat] Proxy failed, trying direct call:', proxyErr.message);
    data = await tryFetch(GEMINI_DIRECT_URL);
  }
  const text = data && data.candidates && data.candidates[0] && data.candidates[0].content
    && data.candidates[0].content.parts && data.candidates[0].content.parts[0]
    && data.candidates[0].content.parts[0].text;
  if (!text) throw new Error('Empty Gemini response');
  return text.trim();
}

// Lightweight markdown renderer for AI replies – inline bold/italic/code,
// block-level bullets, numbered lists, headings, and paragraph breaks. No
// external library; replaces the previous whiteSpace:pre-wrap that printed
// literal `**` and `*` characters.
function renderMD(text) {
  if (!text) return null;
  const lines = text.split(/\r?\n/);

  // Group consecutive list lines into a single <ul>/<ol> block.
  const blocks = [];
  let buf = null;
  for (const raw of lines) {
    const trimmed = raw.trim();
    const ulMatch = trimmed.match(/^[\*\-•]\s+(.*)$/);
    const olMatch = trimmed.match(/^(\d+)[.)]\s+(.*)$/);
    if (ulMatch) {
      if (!buf || buf.type !== 'ul') { buf && blocks.push(buf); buf = { type: 'ul', items: [] }; }
      buf.items.push(ulMatch[1]);
    } else if (olMatch) {
      if (!buf || buf.type !== 'ol') { buf && blocks.push(buf); buf = { type: 'ol', items: [] }; }
      buf.items.push(olMatch[2]);
    } else {
      if (buf) { blocks.push(buf); buf = null; }
      if (/^#{1,6}\s+/.test(trimmed)) {
        const m = trimmed.match(/^(#{1,6})\s+(.*)$/);
        blocks.push({ type: 'h', level: m[1].length, text: m[2] });
      } else if (trimmed === '') {
        blocks.push({ type: 'br' });
      } else {
        blocks.push({ type: 'p', text: raw });
      }
    }
  }
  if (buf) blocks.push(buf);

  // Inline parser: **bold**, *italic*, `code`. Returns array of React nodes.
  const inline = (str, keyPrefix) => {
    const out = [];
    let i = 0, k = 0;
    while (i < str.length) {
      // **bold**
      if (str[i] === '*' && str[i + 1] === '*') {
        const end = str.indexOf('**', i + 2);
        if (end !== -1) {
          out.push(React.createElement('strong', { key: `${keyPrefix}-b${k++}` }, str.slice(i + 2, end)));
          i = end + 2; continue;
        }
      }
      // *italic* (but not **)
      if (str[i] === '*' && str[i + 1] !== '*') {
        const end = str.indexOf('*', i + 1);
        if (end !== -1 && end - i > 1) {
          out.push(React.createElement('em', { key: `${keyPrefix}-i${k++}`, style: { fontStyle: 'italic' } }, str.slice(i + 1, end)));
          i = end + 1; continue;
        }
      }
      // `code`
      if (str[i] === '`') {
        const end = str.indexOf('`', i + 1);
        if (end !== -1) {
          out.push(React.createElement('code', {
            key: `${keyPrefix}-c${k++}`,
            style: { fontFamily: 'var(--f-mono)', fontSize: '0.92em', background: 'var(--surface)', padding: '1px 5px' },
          }, str.slice(i + 1, end)));
          i = end + 1; continue;
        }
      }
      // Collect plain text up to next marker
      let next = i;
      while (next < str.length && !(str[next] === '*' && (str[next + 1] === '*' || (next + 1 < str.length))) && str[next] !== '`') {
        next++;
      }
      if (next === i) next = i + 1;
      out.push(str.slice(i, next));
      i = next;
    }
    return out;
  };

  return blocks.map((b, idx) => {
    if (b.type === 'p')  return React.createElement('p',  { key: idx, style: { margin: '0 0 8px' } }, inline(b.text, `p${idx}`));
    if (b.type === 'br') return React.createElement('div', { key: idx, style: { height: 4 } });
    if (b.type === 'h')  return React.createElement(`h${Math.min(b.level + 2, 6)}`, { key: idx, style: { margin: '8px 0 6px', fontSize: 15, fontWeight: 600 } }, inline(b.text, `h${idx}`));
    if (b.type === 'ul') return React.createElement('ul', { key: idx, style: { margin: '4px 0 8px', paddingLeft: 18 } },
      b.items.map((it, j) => React.createElement('li', { key: j, style: { marginBottom: 4 } }, inline(it, `l${idx}-${j}`))));
    if (b.type === 'ol') return React.createElement('ol', { key: idx, style: { margin: '4px 0 8px', paddingLeft: 22 } },
      b.items.map((it, j) => React.createElement('li', { key: j, style: { marginBottom: 4 } }, inline(it, `n${idx}-${j}`))));
    return null;
  });
}

// Build the live Migronis knowledge base from the data file (no drift from on-site content)
function migronisKB(lang) {
  const D = window.MIGRONIS_DATA || {};
  const cbi = (D.citizenship || []).map((p) =>
    `- ${window.cn(p, lang)} (${p.currency === 'USD' ? '$' : '€'}${((p.minInvest||0)/1000).toFixed(0)}k, ${p.term}${p.note && p.note[lang] ? '; ' + p.note[lang] : ''})`
  ).join('\n');
  const rbi = (D.residency || []).map((p) =>
    `- ${window.cn(p, lang)} (${p.currency === 'USD' ? '$' : '€'}${((p.minInvest||0)/1000).toFixed(0)}k, ${p.term}${p.note && p.note[lang] ? '; ' + p.note[lang] : ''})`
  ).join('\n');
  return { cbi, rbi };
}

function AIChatModal({ open, onClose, lang, initialQuery, openCallback }) {
  const [messages, setMessages] = React.useState([]);
  const [input, setInput] = React.useState('');
  const [busy, setBusy] = React.useState(false);
  const scrollRef = React.useRef(null);
  const sentInit = React.useRef(false);

  React.useEffect(() => {
    if (open && initialQuery && !sentInit.current) {
      sentInit.current = true;
      send(initialQuery);
    }
    if (!open) {
      sentInit.current = false;
    }
  }, [open, initialQuery]);

  React.useEffect(() => {
    if (scrollRef.current) scrollRef.current.scrollTop = scrollRef.current.scrollHeight;
  }, [messages, busy]);

  const send = async (text) => {
    if (!text.trim() || busy) return;
    const userMsg = { role: 'user', content: text };
    const newMessages = [...messages, userMsg];
    setMessages(newMessages);
    setInput('');
    setBusy(true);

    const kb = migronisKB(lang);
    const systemContext = lang === 'ru'
      ? `Ты – ИИ-ассистент Migronis. Эксперт по гражданству и резидентству за инвестиции. Основан в 2012 году Анатолием Летаевым. 2 400+ кейсов, 97% approval rate. Лицензированный агент: команда лично проверяет программы на месте. Офисы – Estoril (Португалия) и Csomád (Венгрия).

# CBI – гражданство за инвестиции (только паспорт и мобильность, не для жизни)
${kb.cbi}

# RBI – резидентство (страны, куда реально переезжают семьёй)
${kb.rbi}

# ПРАВИЛА
- Отвечай кратко (2-4 абзаца или список), профессионально, с цифрами, без воды
- Чётко разделяй CBI (паспорт/мобильность) и RBI (где живут: Португалия, Бразилия, Греция, Уругвай, Коста-Рика)
- São Tomé – новая программа 2026 (замена Vanuatu, от $90k)
- Не перечисляй ограничения по паспортам стран явно; если спрашивают доступность – предложи проверить на бесплатной консультации
- Не упоминай pay-on-delivery (Migronis больше так не работает) и имена партнёрских фондов
- Не давай юридических гарантий; в конце мягко рекомендуй бесплатную консультацию
- Если вопрос не по теме – мягко верни к теме`
      : `You are the Migronis AI assistant. Expert in citizenship and residency by investment. Founded in 2012 by Anatoliy Letaev. 2,400+ cases, 97% approval rate. A licensed agent: the team personally vets programs on the ground. Offices in Estoril (Portugal) and Csomád (Hungary).

# CBI – citizenship by investment (passport & mobility only, not for living)
${kb.cbi}

# RBI – residency (countries families actually move to)
${kb.rbi}

# RULES
- Answer concisely (2-4 paragraphs or a list), professional, with numbers, no fluff
- Sharply separate CBI (passport/mobility) from RBI (places to live: Portugal, Brazil, Greece, Uruguay, Costa Rica)
- São Tomé is a new 2026 program (replacing Vanuatu, from $90k)
- Do not enumerate country passport restrictions; if asked about eligibility, suggest verifying it in a free consultation
- Never mention pay-on-delivery (Migronis no longer uses it) or partner fund names
- No legal guarantees; end by gently recommending a free consultation
- If off-topic, gently bring it back`;

    try {
      const reply = await callGemini(systemContext, messages.map(m => ({
        role: m.role === 'ai' ? 'model' : 'user', content: m.content,
      })), text);
      setMessages([...newMessages, { role: 'ai', content: reply }]);
    } catch (e) {
      console.error('[AIChat] Gemini error:', e);
      setMessages([...newMessages, { role: 'ai', content: lang === 'ru'
        ? 'Извините, не удалось ответить прямо сейчас. Запишитесь на бесплатную консультацию – наш консультант ответит в течение 24 часов.'
        : 'Sorry, I could not respond right now. Please book a free consultation – our advisor will get back within 24 hours.'
      }]);
    }
    setBusy(false);
  };

  if (!open) return null;

  const SAMPLES = lang === 'ru' ? [
    'Сравни Гренаду и Türkiye',
    'Что лучше для семьи 4 человека с бюджетом $400k?',
    'Какой паспорт даёт самый большой безвиз?',
    'Можно ли потерять гражданство после получения?',
  ] : [
    'Compare Grenada vs Türkiye',
    'Best for a family of 4 with $400k budget?',
    'Which passport offers the most visa-free access?',
    'Can citizenship be revoked after issuance?',
  ];

  return (
    <div
      onClick={onClose}
      style={{
        position: 'fixed', inset: 0, zIndex: 100,
        background: 'rgba(0,0,0,0.5)',
        backdropFilter: 'blur(12px)', WebkitBackdropFilter: 'blur(12px)',
        display: 'grid', placeItems: 'center',
        padding: 24, animation: 'fade-up .2s var(--ease-out)',
      }}>
      <div onClick={(e) => e.stopPropagation()}
           className="glass"
           style={{
             width: 'min(680px, 100%)', height: 'min(720px, 90vh)',
             background: 'var(--bg-elev)',
             border: '1px solid var(--border-strong)',
             display: 'flex', flexDirection: 'column',
             borderRadius: 'var(--r-xl)', overflow: 'hidden',
           }}>
        {/* Header */}
        <div style={{ display: 'flex', alignItems: 'center', gap: 12, padding: '16px 20px', borderBottom: '1px solid var(--border)' }}>
          <span style={{
            width: 36, height: 36,
            background: 'var(--accent)',
            display: 'grid', placeItems: 'center', color: '#FFFFFF',
            fontFamily: 'var(--f-sans)', fontSize: 18, fontWeight: 700,
            letterSpacing: '-0.02em',
          }}>M</span>
          <div style={{ flex: 1 }}>
            <div style={{ fontWeight: 500 }}>Migronis AI</div>
            <div style={{ fontSize: 12, color: 'var(--fg-muted)' }}>
              <span style={{ display: 'inline-block', width: 6, height: 6, borderRadius: 999, background: 'var(--ok)', marginRight: 6 }} />
              {lang === 'ru' ? 'онлайн · отвечает за 5 секунд' : 'online · replies in 5 seconds'}
            </div>
          </div>
          <button onClick={onClose} className="btn btn-ghost btn-sm" style={{ width: 36, padding: 0 }}>×</button>
        </div>

        {/* Messages */}
        <div ref={scrollRef} style={{ flex: 1, overflowY: 'auto', padding: 20, display: 'flex', flexDirection: 'column', gap: 12 }}>
          {messages.length === 0 && !busy && (
            <div style={{ animation: 'fade-up .4s var(--ease-out)' }}>
              <div className="display" style={{ fontSize: 26, marginBottom: 8 }}>
                {lang === 'ru' ? <>Чем могу быть <em>полезен</em>?</> : <>How can I <em>help</em>?</>}
              </div>
              <div style={{ color: 'var(--fg-muted)', fontSize: 14, marginBottom: 20 }}>
                {lang === 'ru'
                  ? 'Спросите про любую из 20 программ или вашу ситуацию. Я отвечу, опираясь на актуальные правила и наши кейсы.'
                  : 'Ask about any of the 20 programs or your specific situation. I will answer based on current rules and our case files.'}
              </div>

              {/* Guided navigator – quick-pick chips, monospace markers (no emoji) */}
              <div style={{ marginBottom: 18 }}>
                <div className="eyebrow" style={{ fontSize: 10, marginBottom: 10 }}>
                  {lang === 'ru' ? 'Быстрый запрос' : 'Quick prompt'}
                </div>
                <div style={{ display: 'grid', gridTemplateColumns: 'repeat(2, 1fr)', gap: 8 }}>
                  {[
                    { k: 'BUDGET',  q: lang === 'ru' ? 'Бюджет до $250k' : 'Budget up to $250k' },
                    { k: 'BUDGET',  q: lang === 'ru' ? 'Бюджет $400k+' : 'Budget $400k+' },
                    { k: 'GOAL',    q: lang === 'ru' ? 'Доступ в США (E-2)' : 'US access (E-2 treaty)' },
                    { k: 'REGION',  q: lang === 'ru' ? 'Гражданство ЕС' : 'EU citizenship' },
                    { k: 'TIMING',  q: lang === 'ru' ? 'Получить за 3 мес.' : 'Get in 3 months' },
                    { k: 'FAMILY',  q: lang === 'ru' ? 'Семья 4 человека' : 'Family of 4' },
                  ].map((opt, i) => (
                    <button key={i}
                      onClick={() => send(opt.q + (lang === 'ru' ? '. Какие программы подойдут?' : '. Which programs fit?'))}
                      className="lift"
                      style={{
                        textAlign: 'left', padding: '12px 14px',
                        background: 'var(--bg-elev-2)', border: '1px solid var(--border)',
                        color: 'var(--fg)', fontSize: 13,
                        display: 'flex', alignItems: 'center', gap: 12,
                      }}>
                      <span className="mono" style={{
                        fontSize: 9, letterSpacing: '0.12em',
                        color: 'var(--accent)', minWidth: 52,
                      }}>{opt.k}</span>
                      <span style={{ borderLeft: '1px solid var(--border)', height: 14 }} />
                      <span style={{ flex: 1 }}>{opt.q}</span>
                    </button>
                  ))}
                </div>
              </div>

              <div className="eyebrow" style={{ fontSize: 10, marginBottom: 10 }}>
                {lang === 'ru' ? 'Или свободный вопрос' : 'Or a free-text question'}
              </div>
              <div style={{ display: 'flex', flexDirection: 'column', gap: 8 }}>
                {SAMPLES.map((s, i) => (
                  <button key={i}
                    onClick={() => send(s)}
                    className="lift"
                    style={{
                      textAlign: 'left', padding: '12px 14px',
                      background: 'var(--surface)', border: '1px solid var(--border)',
                      borderRadius: 'var(--r-md)', color: 'var(--fg)', fontSize: 14,
                    }}>
                    {s}
                  </button>
                ))}
              </div>
            </div>
          )}

          {messages.map((m, i) => {
            const isAI = m.role === 'ai';
            // Last AI message → render handover CTA underneath.
            const lastAIIndex = (() => {
              for (let k = messages.length - 1; k >= 0; k--) {
                if (messages[k].role === 'ai') return k;
              }
              return -1;
            })();
            const showHandoff = isAI && i === lastAIIndex && !busy;
            return (
              <div key={i} style={{
                alignSelf: m.role === 'user' ? 'flex-end' : 'flex-start',
                maxWidth: '85%',
                animation: 'fade-up .3s var(--ease-out)',
              }}>
                {isAI && (
                  <div style={{ display: 'flex', alignItems: 'center', gap: 8, marginBottom: 6 }}>
                    <span style={{
                      width: 18, height: 18,
                      background: 'var(--accent)',
                      color: '#FFFFFF', display: 'grid', placeItems: 'center',
                      fontSize: 11, fontFamily: 'var(--f-sans)', fontWeight: 700,
                    }}>M</span>
                    <span style={{ fontSize: 11, color: 'var(--fg-muted)' }}>Migronis AI</span>
                  </div>
                )}
                <div style={{
                  padding: '12px 16px',
                  background: m.role === 'user' ? 'var(--accent-soft)' : 'var(--bg-elev-2)',
                  border: '1px solid', borderColor: m.role === 'user' ? 'var(--accent)' : 'var(--border)',
                  lineHeight: 1.55, fontSize: 14,
                  ...(isAI ? {} : { whiteSpace: 'pre-wrap' }),
                }}>
                  {isAI ? renderMD(m.content) : m.content}
                </div>
                {showHandoff && openCallback && (
                  <div style={{ marginTop: 10, display: 'flex', gap: 8, flexWrap: 'wrap' }}>
                    <button onClick={() => { onClose(); openCallback(); }}
                      className="lift"
                      style={{
                        background: 'var(--accent)', color: '#FFFFFF',
                        border: '1px solid var(--accent)',
                        padding: '10px 14px', fontSize: 13, fontWeight: 600,
                        fontFamily: 'var(--f-sans)', letterSpacing: '0.02em',
                        cursor: 'pointer',
                      }}>
                      {lang === 'ru' ? 'Обсудить с менеджером →' : 'Discuss with an advisor →'}
                    </button>
                    <span style={{ fontSize: 11, color: 'var(--fg-dim)', alignSelf: 'center' }}>
                      {lang === 'ru' ? '30-минутный звонок · бесплатно' : '30-min call · free'}
                    </span>
                  </div>
                )}
              </div>
            );
          })}

          {busy && (
            <div style={{ alignSelf: 'flex-start', display: 'flex', gap: 6, padding: '14px 16px', background: 'var(--surface)', border: '1px solid var(--border)', borderRadius: '18px 18px 18px 4px' }}>
              {[0,1,2].map((i) => (
                <span key={i} style={{
                  width: 6, height: 6, borderRadius: 999, background: 'var(--fg-muted)',
                  animation: `pulse-dot 1.2s ${i * .15}s infinite ease-in-out`,
                }} />
              ))}
            </div>
          )}
        </div>

        {/* Input */}
        <form onSubmit={(e) => { e.preventDefault(); send(input); }}
              style={{ borderTop: '1px solid var(--border)', padding: 16 }}>
          <div style={{
            display: 'flex', alignItems: 'stretch', gap: 0,
            height: 52,
            background: 'var(--bg-elev-2)',
            border: '1px solid var(--border-strong)',
          }}>
            <input value={input} onChange={(e) => setInput(e.target.value)}
                   placeholder={lang === 'ru' ? 'Напишите вопрос...' : 'Ask anything...'}
                   disabled={busy}
                   style={{
                     flex: 1, border: 0, background: 'transparent', outline: 'none',
                     padding: '0 18px', fontSize: 14, fontFamily: 'var(--f-sans)', color: 'var(--fg)',
                   }} />
            <button type="submit" className="btn btn-primary"
                    style={{ height: 'auto', padding: '0 22px', opacity: busy || !input.trim() ? .4 : 1 }}
                    disabled={busy || !input.trim()}>
              {lang === 'ru' ? 'Спросить' : 'Ask'} ↑
            </button>
          </div>
          <div style={{ marginTop: 10, fontSize: 11, color: 'var(--fg-dim)', textAlign: 'center' }}>
            {lang === 'ru'
              ? 'AI даёт ориентиры. Для финального плана нужна консультация с лицензированным агентом.'
              : 'AI provides directional advice. Final plans require a licensed-agent consultation.'}
          </div>
        </form>
      </div>

      <style dangerouslySetInnerHTML={{ __html: `
        @keyframes pulse-dot { 0%,80%,100% { opacity: .3; transform: scale(1); } 40% { opacity: 1; transform: scale(1.4); } }
      `}} />
    </div>
  );
}

window.AIChatModal = AIChatModal;
