/* Ava Solutions — web chat (Toros lead capture) + analytics hooks.
   Extracted from app.jsx so index.html and products.html can both mount the
   floating CTA + chat drawer. avaTrack calls are preserved from the analytics work. */

const PUBLIC_AGENT_URL = 'https://t.me/Toros_AvaSol_bot';
const AVA_LEAD_STORAGE_KEY = 'avasolutions_lead_id';

function createLeadId() {
  const date = new Date().toISOString().slice(0, 10).replace(/-/g, '');
  const bytes = new Uint8Array(4);
  if (window.crypto && window.crypto.getRandomValues) {
    window.crypto.getRandomValues(bytes);
  } else {
    for (let i = 0; i < bytes.length; i += 1) bytes[i] = Math.floor(Math.random() * 256);
  }
  const suffix = Array.from(bytes, (byte) => byte.toString(16).padStart(2, '0')).join('');
  return `lead_${date}_${suffix}`;
}

function getOrCreateLeadId() {
  try {
    const existing = window.localStorage.getItem(AVA_LEAD_STORAGE_KEY);
    if (existing && /^lead_\d{8}_[a-f0-9]{8}$/i.test(existing)) return existing;
    const leadId = createLeadId();
    window.localStorage.setItem(AVA_LEAD_STORAGE_KEY, leadId);
    return leadId;
  } catch (error) {
    return createLeadId();
  }
}

function getTelegramDeepLink(leadId = getOrCreateLeadId()) {
  return `${PUBLIC_AGENT_URL}?start=${encodeURIComponent(leadId)}`;
}

window.avaGetLeadId = getOrCreateLeadId;
window.avaGetTelegramDeepLink = getTelegramDeepLink;
window.avaOpenTelegram = function avaOpenTelegram(entrypoint = 'global_helper') {
  const leadId = getOrCreateLeadId();
  window.avaTrack?.('telegram_open', { entrypoint, lead_id: leadId });
  window.open(getTelegramDeepLink(leadId), '_blank', 'noopener,noreferrer');
};

const WEB_CHAT_API_URL = window.location.hostname === 'localhost' || window.location.hostname === '127.0.0.1'
  ? 'http://localhost:8080/web-chat/api/message'
  : 'https://toros-avasol-public-agent-production.up.railway.app/web-chat/api/message';
const AVA_CHAT_STORAGE_KEY = 'avasolutions_web_chat_messages';
// Rotating fallback "thinking" states, shuffled with no immediate repeat.
const TOROS_THINKING_PHRASES = [
  'Toros is thinking…',
  'Toros is walking…',
  'Toros is purring…',
  'Toros is meowing…',
  'Toros is pondering…'
];
const pickThinkingPhrase = (phrases, prev) => {
  const pool = Array.isArray(phrases) && phrases.length ? phrases : TOROS_THINKING_PHRASES;
  if (pool.length < 2) return pool[0];
  let next = prev;
  while (next === prev) {
    next = pool[Math.floor(Math.random() * pool.length)];
  }
  return next;
};
const CHAT_COPY = {
  en: {
    initialMessage: 'Hello. I’m Toros, the AVASOLUTIONS AI architect. Briefly describe the system or automation you want to discuss, and I’ll help shape the first step.',
    starterPrompts: [
      'I want to automate sales and incoming leads. Where should we start?',
      'We need an AI agent for our team. Help us define the first workflow.',
      'We need a CRM / ERP platform architecture. What should we map first?'
    ],
    closeChat: 'Close AI architect chat',
    eyebrow: 'Toros · AI architect',
    title: 'Chat with Toros on the site',
    close: 'Close',
    startersLabel: 'Suggested prompts',
    quickTitle: 'Good starting points',
    typing: 'Toros is thinking…',
    dateToday: 'Today',
    replyCaption: 'Reply ~5 sec · Private',
    thinkingPhrases: TOROS_THINKING_PHRASES,
    unavailable: 'Toros is temporarily unavailable on the website. You can continue in Telegram — the context is already attached to the link.',
    unavailableMessage: 'I cannot answer directly on the website right now. Tap “Continue in Telegram” — this conversation context is already included in the link.',
    placeholder: 'Describe the process, system, or AI agent you want to build…',
    sending: 'Sending message',
    send: 'Send message',
    continueTelegram: 'Continue in Telegram',
    privacySummary: 'Privacy & context',
    privacyText: 'This website chat sends only your message, page, locale and an internal lead ID to the AVASOLUTIONS backend. LLM and Telegram secrets stay server-side. Please do not share sensitive personal data unless needed for your project request.',
    floatingAria: 'Open AVASOLUTIONS AI architect web chat',
    floatingEyebrow: 'AI',
    floatingLabel: 'TOROS'
  },
  ru: {
    initialMessage: 'Здравствуйте. Я Toros, AI-архитектор AVASOLUTIONS. Можете коротко описать, какую систему или автоматизацию вы хотите обсудить?',
    starterPrompts: [
      'Хочу автоматизировать продажи и входящие заявки. С чего начать?',
      'Нам нужен AI-агент для команды. Помогите определить первый процесс.',
      'Нужна архитектура CRM / ERP платформы. Что сначала описать?'
    ],
    closeChat: 'Закрыть чат с AI-архитектором',
    eyebrow: 'Toros · AI-архитектор',
    title: 'Чат с Toros на сайте',
    close: 'Закрыть',
    startersLabel: 'Подсказки для начала',
    quickTitle: 'С чего можно начать',
    typing: 'Toros думает…',
    dateToday: 'Сегодня',
    replyCaption: 'Ответ ~5 сек · Приватно',
    thinkingPhrases: [
      'Toros думает…',
      'Toros идёт…',
      'Toros мурчит…',
      'Toros мяукает…',
      'Toros размышляет…'
    ],
    unavailable: 'Toros временно недоступен на сайте. Можно продолжить в Telegram — контекст уже прикреплён к ссылке.',
    unavailableMessage: 'Сейчас я не могу ответить прямо на сайте. Нажмите «Продолжить в Telegram» — контекст этой беседы уже включён в ссылку.',
    placeholder: 'Опишите процесс, систему или AI-агента, которого хотите построить…',
    sending: 'Отправка сообщения',
    send: 'Отправить сообщение',
    continueTelegram: 'Продолжить в Telegram',
    privacySummary: 'Приватность и контекст',
    privacyText: 'Этот чат на сайте отправляет в backend AVASOLUTIONS только ваше сообщение, страницу, язык и внутренний lead ID. LLM- и Telegram-секреты остаются на сервере. Пожалуйста, не отправляйте чувствительные персональные данные, если они не нужны для проектного запроса.',
    floatingAria: 'Открыть web-chat AI-архитектора AVASOLUTIONS',
    floatingEyebrow: 'AI',
    floatingLabel: 'TOROS'
  }
};
const CHAT_LOCALES = {
  ...CHAT_COPY,
  ...((typeof window !== 'undefined' && window.AVA_CHAT_COPY_EXTRA) || {})
};

function getChatCopy(lang) {
  const normalized = window.avaNormalizeLangCode ? window.avaNormalizeLangCode(lang) : lang;
  return CHAT_LOCALES[normalized] || CHAT_COPY.en;
}

function getSelectedChatLang() {
  try {
    const raw = window.localStorage.getItem('ava_lang') || document.documentElement.lang || 'en';
    return window.avaNormalizeLangCode ? (window.avaNormalizeLangCode(raw) || 'en') : raw;
  } catch (error) {
    return 'en';
  }
}

function createInitialChatMessage(lang) {
  return { role: 'assistant', content: getChatCopy(lang).initialMessage, initial: true, lang };
}

function loadStoredMessages(lang = getSelectedChatLang()) {
  try {
    const raw = window.localStorage.getItem(AVA_CHAT_STORAGE_KEY);
    const parsed = raw ? JSON.parse(raw) : null;
    if (Array.isArray(parsed) && parsed.length) return parsed.slice(-30);
  } catch (error) {}
  return [createInitialChatMessage(lang)];
}

function saveStoredMessages(messages) {
  try {
    window.localStorage.setItem(AVA_CHAT_STORAGE_KEY, JSON.stringify(messages.slice(-30)));
  } catch (error) {}
}

function isSafeChatLink(href) {
  try {
    const url = new URL(href, window.location.origin);
    if (url.protocol === 'mailto:') return /^mailto:hello@avasolutions\.studio$/i.test(url.href);
    if (url.protocol !== 'https:') return false;
    if (url.hostname === 't.me' && url.pathname === '/Toros_AvaSol_bot') return true;
    return ['avasolutions.studio', 'www.avasolutions.studio'].includes(url.hostname);
  } catch (error) {
    return false;
  }
}

function renderChatMessage(text) {
  const source = String(text || '');
  const nodes = [];
  const pattern = /\[([^\]\n]{1,100})\]\(([^)\s]{1,300})\)|(https:\/\/[^\s<>()]+)|\bhello@avasolutions\.studio\b/gi;
  let lastIndex = 0;
  let match;

  while ((match = pattern.exec(source)) !== null) {
    const raw = match[0];
    const label = match[1] || match[3] || raw;
    const href = match[2] || match[3] || `mailto:${raw}`;
    if (match.index > lastIndex) nodes.push(source.slice(lastIndex, match.index));
    if (isSafeChatLink(href)) {
      nodes.push(
        <a key={`link-${match.index}`} href={href} target={href.startsWith('mailto:') ? undefined : '_blank'} rel={href.startsWith('mailto:') ? undefined : 'noopener noreferrer'}>
          {label}
        </a>
      );
    } else {
      nodes.push(raw);
    }
    lastIndex = match.index + raw.length;
  }

  if (lastIndex < source.length) nodes.push(source.slice(lastIndex));
  return nodes.length ? nodes : source;
}

function WebChatDrawer({ isOpen, onClose }) {
  const { lang } = useLang();
  const chatCopy = getChatCopy(lang);
  const [leadId, setLeadId] = React.useState('');
  const [messages, setMessages] = React.useState(() => loadStoredMessages(lang));
  const [input, setInput] = React.useState('');
  const [isSending, setIsSending] = React.useState(false);
  const [error, setError] = React.useState('');
  const [thinkingPhrase, setThinkingPhrase] = React.useState((chatCopy.thinkingPhrases || TOROS_THINKING_PHRASES)[0]);
  const messagesRef = React.useRef(null);
  const textareaRef = React.useRef(null);

  React.useEffect(() => {
    if (!isSending) return;
    setThinkingPhrase((prev) => pickThinkingPhrase(chatCopy.thinkingPhrases, prev));
    let timer;
    const schedule = () => {
      const delay = 3000 + Math.random() * 1000; // 3–4s
      timer = window.setTimeout(() => {
        setThinkingPhrase((prev) => pickThinkingPhrase(chatCopy.thinkingPhrases, prev));
        schedule();
      }, delay);
    };
    schedule();
    return () => window.clearTimeout(timer);
  }, [isSending, chatCopy.thinkingPhrases]);

  React.useEffect(() => {
    if (!isOpen) return;
    const nextLeadId = getOrCreateLeadId();
    setLeadId(nextLeadId);
    const onKeyDown = (event) => { if (event.key === 'Escape') onClose(); };
    window.addEventListener('keydown', onKeyDown);
    const prevOverflow = document.body.style.overflow;
    document.body.style.overflow = 'hidden';
    return () => {
      window.removeEventListener('keydown', onKeyDown);
      document.body.style.overflow = prevOverflow;
    };
  }, [isOpen, onClose]);

  React.useEffect(() => {
    saveStoredMessages(messages);
    if (messagesRef.current) messagesRef.current.scrollTop = messagesRef.current.scrollHeight;
  }, [messages, isSending, isOpen]);

  React.useEffect(() => {
    const textarea = textareaRef.current;
    if (!textarea) return;
    textarea.style.height = 'auto';
    textarea.style.height = `${Math.min(textarea.scrollHeight, 150)}px`;
  }, [input]);

  React.useEffect(() => {
    setMessages((current) => {
      const hasUserMessages = current.some((message) => message.role === 'user');
      if (hasUserMessages) return current;
      const onlyInitialAssistant = current.length === 1 && current[0].role === 'assistant';
      if (!onlyInitialAssistant) return current;
      if (current[0].content === chatCopy.initialMessage && current[0].lang === lang) return current;
      return [createInitialChatMessage(lang)];
    });
    setError('');
  }, [lang, chatCopy.initialMessage]);

  const telegramHref = leadId ? getTelegramDeepLink(leadId) : PUBLIC_AGENT_URL;
  const hasUserMessages = messages.some((message) => message.role === 'user');
  const starterPrompts = chatCopy.starterPrompts;

  async function sendMessage(textOverride) {
    const text = (textOverride || input).trim();
    if (!text || isSending) return;
    const currentLeadId = leadId || getOrCreateLeadId();
    setLeadId(currentLeadId);
    window.avaTrack?.('chat_message_send_attempt', {
      lead_id: currentLeadId,
      text_length: text.length,
      source: textOverride ? 'starter_prompt' : 'typed_message'
    });
    setInput('');
    setError('');
    const nextMessages = [...messages, { role: 'user', content: text }];
    setMessages(nextMessages);
    setIsSending(true);

    try {
      const response = await fetch(WEB_CHAT_API_URL, {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({
          lead_id: currentLeadId,
          message: text,
          locale: lang,
          browser_locale: navigator.language || 'unknown',
          page: window.location.href,
          source: 'avasolutions_site_drawer',
          attribution: window.avaGetAttribution?.() || null
        })
      });
      const payload = await response.json().catch(() => ({}));
      if (!response.ok || !payload.ok || !payload.reply) {
        throw new Error(payload.error || 'assistant_unavailable');
      }
      window.avaTrack?.('chat_message_success', { lead_id: currentLeadId });
      setMessages((current) => [...current, { role: 'assistant', content: payload.reply }]);
    } catch (err) {
      window.avaTrack?.('chat_message_error', { lead_id: currentLeadId, error: String(err && err.message || 'unknown').slice(0, 120) });
      setError(chatCopy.unavailable);
      setMessages((current) => [...current, {
        role: 'assistant',
        content: chatCopy.unavailableMessage
      }]);
    } finally {
      setIsSending(false);
    }
  }

  function onSubmit(event) {
    event.preventDefault();
    sendMessage();
  }

  return (
    <div className={`web-chat ${isOpen ? 'is-open' : ''}`} aria-hidden={!isOpen}>
      <button className="web-chat__backdrop" type="button" aria-label={chatCopy.closeChat} onClick={onClose} />
      <aside className="web-chat__panel" role="dialog" aria-modal="true" aria-labelledby="web-chat-title">
        <div className="web-chat__header">
          <div className="web-chat__heading">
            <img className="web-chat__avatar" src="assets/toros-avatar.png" alt="Toros" width="46" height="46" loading="lazy" />
            <div style={{ minWidth: 0 }}>
              <div className="web-chat__eyebrow"><span className="web-chat__status-dot" aria-hidden="true" />{chatCopy.eyebrow}</div>
              <h2 id="web-chat-title">{chatCopy.title}</h2>
            </div>
          </div>
          <button className="web-chat__close" type="button" aria-label={chatCopy.close} onClick={onClose}>×</button>
        </div>

        <div className="web-chat__body">
          {!hasUserMessages && (
            <div className="web-chat__starters" aria-label={chatCopy.startersLabel}>
              <div className="web-chat__quick-title">{chatCopy.quickTitle}</div>
              <div className="web-chat__quick-list">
                {starterPrompts.map((prompt) => (
                  <button className="web-chat__chip" type="button" key={prompt} onClick={() => { window.avaTrack?.('starter_prompt_click', { prompt }); sendMessage(prompt); }} disabled={isSending}>{prompt}</button>
                ))}
              </div>
            </div>
          )}

          <div className="web-chat__messages" aria-live="polite" ref={messagesRef}>
            <div className="web-chat__date mono" aria-hidden="true">{chatCopy.dateToday} · {new Date().toTimeString().slice(0, 5)}</div>
            {messages.map((message, index) => (
              <div className={`web-chat__message web-chat__message--${message.role === 'user' ? 'user' : 'agent'}`} key={`${message.role}-${index}`}>
                {message.role === 'assistant' ? renderChatMessage(message.content) : message.content}
              </div>
            ))}
            {isSending && (
              <div className="web-chat__message web-chat__message--agent web-chat__thinking" aria-label={chatCopy.typing}>
                <span className="toros-paws" aria-hidden="true">
                  {[0, 1, 2].map((paw) => (
                    <span className="toros-paw" key={paw}>
                      <span className="toros-paw__ripple" />
                      <span className="toros-paw__pad" />
                      <span className="toros-paw__toe toros-paw__toe--1" />
                      <span className="toros-paw__toe toros-paw__toe--2" />
                      <span className="toros-paw__toe toros-paw__toe--3" />
                    </span>
                  ))}
                </span>
                <span className="web-chat__thinking-label" key={thinkingPhrase}>{thinkingPhrase}</span>
              </div>
            )}
          </div>
        </div>

        <div className="web-chat__footer">
          {error && <div className="web-chat__message web-chat__message--note">{error}</div>}

          <form className="web-chat__form" onSubmit={onSubmit}>
            <textarea
              ref={textareaRef}
              className="web-chat__input"
              value={input}
              onChange={(event) => setInput(event.target.value)}
              placeholder={chatCopy.placeholder}
              rows="2"
              maxLength="1200"
              disabled={isSending}
              onKeyDown={(event) => {
                if (event.key === 'Enter' && !event.shiftKey) { event.preventDefault(); sendMessage(); }
              }}
            />
            <button className="web-chat__send" type="submit" aria-label={isSending ? chatCopy.sending : chatCopy.send} disabled={isSending || !input.trim()}>
              <span className="web-chat__send-icon" aria-hidden="true">{isSending ? '…' : '↑'}</span>
            </button>
          </form>

          <div className="web-chat__footer-actions">
            <a className="web-chat__telegram" href={telegramHref} target="_blank" rel="noopener noreferrer" onClick={() => window.avaTrack?.('telegram_continue_click', { entrypoint: 'web_chat_footer', lead_id: leadId || getOrCreateLeadId() })}>
              {chatCopy.continueTelegram} →
            </a>
            <span className="web-chat__caption">{chatCopy.replyCaption}</span>
          </div>
          <details className="web-chat__privacy">
            <summary>{chatCopy.privacySummary}</summary>
            <p>{chatCopy.privacyText}</p>
          </details>
        </div>
      </aside>
    </div>
  );
}

/* WebGL "water ripple" that sits behind the floating Toros button — slow,
   self-damping concentric waves with soft 3D highlights (the same water motif as
   the hero). Purely decorative. Reduced motion runs it slowed down instead of
   freezing (owner call 2026-07-06 — iPhones must keep a minimal animation);
   without WebGL (iOS Lockdown Mode) it reports up so a CSS ripple takes over. */
function TorosWaterCanvas({ onUnavailable }) {
  const ref = React.useRef(null);
  React.useEffect(() => {
    const canvas = ref.current;
    if (!canvas || !canvas.getContext) { if (onUnavailable) onUnavailable(); return; }
    let gl = null;
    try { gl = canvas.getContext('webgl', { alpha: true, premultipliedAlpha: true }); } catch (e) { gl = null; }
    if (!gl) { if (onUnavailable) onUnavailable(); return; }
    /* highp guard — same reason as the hero water: the Toros ripple's light
       is a derivative of the height field, which collapses to flat under real
       mediump on iOS Apple GPUs (desktop WebKit aliases mediump→highp). */
    const FS = [
      '#ifdef GL_FRAGMENT_PRECISION_HIGH',
      'precision highp float;',
      '#else',
      'precision mediump float;',
      '#endif',
      'uniform float uT;',
      'uniform vec2 uRes;',
      'void main(){',
      '  vec2 uv=(gl_FragCoord.xy-uRes*.5)/(uRes*.5);',
      '  float r=length(uv);',
      '  float k1=24.0,k2=16.0;',
      '  float damp=exp(-r*2.4)*smoothstep(1.0,.3,r)*smoothstep(.16,.38,r);',
      '  float breathe=.72+.28*sin(uT*.35);',
      '  float p1=k1*r-uT*2.0, p2=k2*r-uT*1.35+1.7;',
      '  float h=(sin(p1)*.68+sin(p2)*.32)*damp*breathe;',
      '  float dh=(cos(p1)*k1*.68+cos(p2)*k2*.32)*damp*breathe;',
      '  float light=clamp(dh*.05,-1.,1.);',
      '  vec3 hi=vec3(1.,.985,.9);',
      '  vec3 sh=vec3(.58,.545,.44);',
      '  vec3 col=mix(sh,hi,step(0.,light));',
      '  float a=abs(light)*.55+max(h,0.)*.10;',
      '  a=clamp(a,0.,.85);',
      '  gl_FragColor=vec4(col*a,a);',
      '}',
    ].join('\n');
    const mk = (t, src) => { const s = gl.createShader(t); gl.shaderSource(s, src); gl.compileShader(s); return s; };
    const prog = gl.createProgram();
    gl.attachShader(prog, mk(gl.VERTEX_SHADER, 'attribute vec2 p;void main(){gl_Position=vec4(p,0.,1.);}'));
    gl.attachShader(prog, mk(gl.FRAGMENT_SHADER, FS));
    gl.linkProgram(prog);
    if (!gl.getProgramParameter(prog, gl.LINK_STATUS)) { if (onUnavailable) onUnavailable(); return; }
    gl.useProgram(prog);
    const buf = gl.createBuffer();
    gl.bindBuffer(gl.ARRAY_BUFFER, buf);
    gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([-1, -1, 3, -1, -1, 3]), gl.STATIC_DRAW);
    const loc = gl.getAttribLocation(prog, 'p');
    gl.enableVertexAttribArray(loc);
    gl.vertexAttribPointer(loc, 2, gl.FLOAT, false, 0, 0);
    const uT = gl.getUniformLocation(prog, 'uT');
    gl.uniform2f(gl.getUniformLocation(prog, 'uRes'), canvas.width, canvas.height);
    gl.viewport(0, 0, canvas.width, canvas.height);
    gl.enable(gl.BLEND);
    gl.blendFunc(gl.ONE, gl.ONE_MINUS_SRC_ALPHA);
    gl.clearColor(0, 0, 0, 0);
    const reduce = window.matchMedia && window.matchMedia('(prefers-reduced-motion: reduce)').matches;
    const speed = reduce ? 0.35 : 1;
    const t0 = performance.now();
    let raf, dead = false;
    const frame = () => {
      if (dead) return;
      gl.clear(gl.COLOR_BUFFER_BIT);
      gl.uniform1f(uT, ((performance.now() - t0) / 1000) * speed);
      gl.drawArrays(gl.TRIANGLES, 0, 3);
      raf = requestAnimationFrame(frame);
    };
    frame();
    return () => { dead = true; cancelAnimationFrame(raf); };
  }, []);
  return <canvas ref={ref} className="floating-chat-water" width="300" height="300" aria-hidden="true" />;
}

function FloatingChatCta({ onOpen }) {
  const { lang } = useLang();
  const chatCopy = getChatCopy(lang);
  const [waterless, setWaterless] = React.useState(false);
  const markWaterless = React.useCallback(() => setWaterless(true), []);
  return (
    <>
      <TorosWaterCanvas onUnavailable={markWaterless} />
      {waterless && <span className="floating-chat-ripple" aria-hidden="true" />}
      <button
        className="floating-chat-cta"
        type="button"
        onClick={onOpen}
        aria-label={chatCopy.floatingAria}
        data-chat-entrypoint="web-chat-drawer"
      >
        <span className="floating-chat-cta__eyebrow">{chatCopy.floatingEyebrow}</span>
        <span className="floating-chat-cta__label">{chatCopy.floatingLabel}</span>
      </button>
    </>
  );
}

window.WebChatDrawer = WebChatDrawer;
window.FloatingChatCta = FloatingChatCta;
