// ROBOCASH chat — state machine + Hermes backend integration
// Loaded after messages.jsx

const RC2 = window.ROBOCASH;
const T = window.RCT;
const HERMES = window.HERMES || {};

// ─── State machine ─────────────────────────────────────────
// steps: welcome -> amount -> term -> purpose -> credit -> phone -> processing -> results -> free
const STEPS = ['welcome', 'amount', 'term', 'purpose', 'credit', 'phone', 'processing', 'results', 'free'];

function Chat() {
  const [messages, setMessages] = useState([]);
  const [step, setStep] = useState('welcome');
  const [typing, setTyping] = useState(false);
  const [profile, setProfile] = useState({});
  const [inputValue, setInputValue] = useState('');
  const [inputDisabled, setInputDisabled] = useState(true);
  const [aiBusy, setAiBusy] = useState(false);
  const [sessionId, setSessionId] = useState(null);
  const [decision, setDecision] = useState({});
  const [offerFocusId, setOfferFocusId] = useState(null);
  const scrollRef = useRef(null);
  const offerFocusRef = useRef(null);
  const soundRef = useRef({ ctx: null, unlocked: false });

  // Always scroll to bottom on new messages or typing change
  useEffect(() => {
    const el = scrollRef.current; if (!el) return;
    requestAnimationFrame(() => {
      el.scrollTo({ top: el.scrollHeight, behavior: 'smooth' });
    });
  }, [messages, typing]);

  useEffect(() => {
    if (!offerFocusId || !scrollRef.current || !offerFocusRef.current) return;
    requestAnimationFrame(() => {
      scrollRef.current.scrollTo({
        top: Math.max(offerFocusRef.current.offsetTop - 88, 0),
        behavior: 'smooth',
      });
      setOfferFocusId(null);
    });
  }, [messages, offerFocusId]);

  useEffect(() => {
    const unlockSound = () => {
      const AudioContext = window.AudioContext || window.webkitAudioContext;
      if (!AudioContext) return;
      const state = soundRef.current;
      if (!state.ctx) state.ctx = new AudioContext();
      state.unlocked = true;
      if (state.ctx.resume) Promise.resolve(state.ctx.resume()).catch(() => {});
    };
    window.addEventListener('pointerdown', unlockSound, { passive: true });
    window.addEventListener('keydown', unlockSound);
    return () => {
      window.removeEventListener('pointerdown', unlockSound);
      window.removeEventListener('keydown', unlockSound);
    };
  }, []);

  function playSolomiyaSound() {
    const AudioContext = window.AudioContext || window.webkitAudioContext;
    const state = soundRef.current;
    if (!AudioContext || !state.unlocked) return;
    const ctx = state.ctx || new AudioContext();
    state.ctx = ctx;
    if (ctx.state === 'suspended' && ctx.resume) Promise.resolve(ctx.resume()).catch(() => {});

    const now = ctx.currentTime + 0.015;
    const master = ctx.createGain();
    master.gain.setValueAtTime(0.0001, now);
    master.gain.exponentialRampToValueAtTime(0.045, now + 0.018);
    master.gain.exponentialRampToValueAtTime(0.0001, now + 0.48);
    master.connect(ctx.destination);

    [
      { freq: 659.25, start: 0, duration: 0.18 },
      { freq: 880, start: 0.11, duration: 0.18 },
      { freq: 1174.66, start: 0.23, duration: 0.22 },
    ].forEach(tone => {
      const osc = ctx.createOscillator();
      const gain = ctx.createGain();
      osc.type = 'sine';
      osc.frequency.setValueAtTime(tone.freq, now + tone.start);
      gain.gain.setValueAtTime(0.0001, now + tone.start);
      gain.gain.exponentialRampToValueAtTime(0.75, now + tone.start + 0.018);
      gain.gain.exponentialRampToValueAtTime(0.0001, now + tone.start + tone.duration);
      osc.connect(gain);
      gain.connect(master);
      osc.start(now + tone.start);
      osc.stop(now + tone.start + tone.duration + 0.03);
    });
  }

  // Welcome bootstrap
  useEffect(() => {
    let alive = true;
    (async () => {
      const boot = await bootstrapBackend();
      if (!alive) return;
      const name = boot && boot.decision && boot.decision.client_name ? boot.decision.client_name : '';
      const first = name
        ? `${name}, вітаю! Я Соломія, AI-консультант ROBOCASH.`
        : 'Привіт! Я Соломія, AI-консультант ROBOCASH.';
      pushAgent([{ kind: 'text', content: first }], { delay: 200 });
      pushAgent([
        { kind: 'text', content: 'За 1 хвилину я підберу кредитні компанії з найвищим шансом схвалення саме під ваш профіль. Безкоштовно і без зайвих дзвінків.' },
      ], { delay: 1300 });
      pushAgent([
        { kind: 'partners' },
        { kind: 'qr', options: [{ value: 'start', label: 'Почати підбір', emoji: '✨', primary: true }] },
      ], { delay: 2400, afterStep: 'amount' });
    })();
    return () => { alive = false; };
  }, []);

  async function bootstrapBackend() {
    try {
      const res = HERMES.decisionId
        ? await fetch('/api/chat/bootstrap?decision_id=' + encodeURIComponent(HERMES.decisionId))
        : await fetch('/api/chat/session', {
          method: 'POST',
          headers: { 'Content-Type': 'application/json' },
          body: JSON.stringify({}),
        });
      if (!res.ok) throw new Error('bootstrap_http_' + res.status);
      const data = await res.json();
      setSessionId(data.session_id || null);
      setDecision(data.decision || {});
      return data;
    } catch (e) {
      pushAgent([
        { kind: 'text', content: 'Підключення до персонального профілю затримується. Можу все одно зібрати параметри і показати базовий підбір.' },
      ], { delay: 350 });
      return null;
    }
  }

  // ─── Message dispatcher ──────────────────────────────────
  function pushAgent(items, { delay = 600, afterStep } = {}) {
    setTimeout(() => {
      setTyping(true);
      setTimeout(() => {
        setTyping(false);
        setMessages(m => [...m, ...items.map(i => ({ ...i, side: 'agent', id: i.id || Math.random() }))]);
        if (items.some(i => i.kind !== 'processing')) playSolomiyaSound();
        if (afterStep) setStep(afterStep);
      }, Math.min(900, 350 + items.length * 250));
    }, delay);
  }
  function pushUser(content) {
    setMessages(m => [...m, { kind: 'text', side: 'user', content, id: Math.random() }]);
  }

  // ─── Step transitions ────────────────────────────────────
  function handleQuickReply(opt) {
    if (step === 'amount' && opt.value === 'start') {
      pushUser('Почати підбір');
      askAmount();
    } else if (step === 'purpose') {
      pushUser(opt.label);
      setProfile(p => ({ ...p, purpose: opt }));
      askCredit();
    } else if (step === 'credit') {
      pushUser(opt.label);
      setProfile(p => ({ ...p, credit: opt }));
      askPhone();
    } else if (step === 'results' || step === 'free') {
      pushUser(opt.label);
      askAI(opt.label);
    }
  }

  function askAmount() {
    pushAgent([
      { kind: 'text', content: 'Чудово! Спочатку основне — яку суму ви хочете отримати?' },
      { kind: 'slider', config: {
        label: 'Сума кредиту',
        min: 500, max: 100000, step: 500, defaultValue: 8000,
        format: RC2.formatUAH,
        presets: [3000, 8000, 15000, 30000],
        onConfirm: (v) => {
          pushUser(RC2.formatUAH(v));
          setProfile(p => ({ ...p, amount: v }));
          askTerm();
        },
      }},
    ], { delay: 500 });
  }

  function askTerm() {
    pushAgent([
      { kind: 'text', content: 'На який термін потрібні гроші?' },
      { kind: 'slider', config: {
        label: 'Термін повернення',
        min: 7, max: 365, step: 1, defaultValue: 30,
        format: RC2.formatDays,
        presets: [14, 30, 60, 90],
        onConfirm: (v) => {
          pushUser(RC2.formatDays(v));
          setProfile(p => ({ ...p, term: v }));
          askPurpose();
        },
      }},
    ], { delay: 400 });
  }

  function askPurpose() {
    pushAgent([
      { kind: 'text', content: 'Чудово. А на що знадобились гроші? Це впливає на підбір спецпропозицій.' },
      { kind: 'qr', options: RC2.PURPOSE_OPTIONS },
    ], { delay: 400, afterStep: 'purpose' });
  }

  function askCredit() {
    pushAgent([
      { kind: 'text', content: 'Останнє важливе питання — як з кредитною історією?' },
      { kind: 'text', content: '⚠ Це не вплине на вашу КІ — ми робимо м\u02BCяку перевірку.' },
      { kind: 'qr', options: RC2.CREDIT_HISTORY_OPTIONS },
    ], { delay: 400, afterStep: 'credit' });
  }

  function askPhone() {
    pushAgent([
      { kind: 'text', content: 'Готово! Залишилось номер телефону — на нього МФО надішлють SMS з підтвердженням заявки.' },
      { kind: 'phone', onConfirm: (formatted) => {
        pushUser(formatted);
        setProfile(p => ({ ...p, phone: formatted }));
        startProcessing();
      }},
    ], { delay: 400, afterStep: 'phone' });
  }

  function startProcessing() {
    pushAgent([
      { kind: 'processing', onDone: () => showResults() },
    ], { delay: 400, afterStep: 'processing' });
  }

  async function showResults() {
    const p = profileRef.current;
    const hermes = await getHermesOffers(p);
    let sorted = hermes.offers || [];
    if (!sorted.length) {
      sorted = fallbackOffers(p);
    }

    const offersId = 'offers-' + Date.now();
    setOfferFocusId(offersId);
    pushAgent([
      { kind: 'text', content: hermes.reply || 'Готово! Ось усі доступні пропозиції, відсортовані під ваш профіль.' },
      { kind: 'summary' },
      { kind: 'mfos', id: offersId, mfos: sorted, requestedAmount: p.amount, focusStart: true },
      { kind: 'text', content: 'Подати заявку можна одразу до кількох — це збільшує шанс одобрення. Якщо є питання — питайте, я поряд 💬' },
    ], { delay: 500, afterStep: 'free' });
    setInputDisabled(false);
  }

  function fallbackOffers(p) {
    let sorted = [...RC2.MFOS];
    if (p.credit && (p.credit.value === 'bad' || p.credit.value === 'small')) {
      sorted.sort((a, b) => (b.firstFree ? 1 : 0) - (a.firstFree ? 1 : 0));
    } else {
      sorted.sort((a, b) => b.approval - a.approval);
    }
    const reqA = p.amount || 0;
    return sorted.map(m => ({
      ...m,
      _fit: reqA <= m.maxAmount ? 1 : 0,
    })).sort((a, b) => b._fit - a._fit);
  }

  function normalizeHermesOffer(offer, idx) {
    const defaults = RC2.MFOS[idx % RC2.MFOS.length];
    return {
      ...defaults,
      ...offer,
      id: offer.id || offer.name || defaults.id,
      name: offer.name || defaults.name,
      monogram: offer.monogram || defaults.monogram,
      color: offer.color || defaults.color,
      bg: offer.bg || defaults.bg,
      approval: Number(offer.approval || defaults.approval || 88),
      maxAmount: Number(offer.maxAmount || defaults.maxAmount || 25000),
      minAmount: Number(offer.minAmount || defaults.minAmount || 500),
      minRate: offer.minRate || defaults.minRate || 'від 0.01%',
      termRange: offer.termRange || defaults.termRange || '7-30 днів',
      decision: offer.decision || defaults.decision || '5 хв',
      tag: offer.tag || defaults.tag || 'Рекомендовано Hermes',
      perks: offer.perks || defaults.perks || ['Онлайн на картку', 'Швидке рішення', 'Без довідки про доходи'],
      url: offer.url || defaults.url,
    };
  }

  async function getHermesOffers(p) {
    try {
      const res = await fetch('/api/chat/form-complete', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({
          session_id: sessionId,
          decision_id: HERMES.decisionId || null,
          amount: p.amount || 8000,
          term: p.term || 30,
          purpose: p.purpose || null,
          credit: p.credit || null,
          phone: p.phone || null,
        }),
      });
      if (!res.ok) throw new Error('chat_http_' + res.status);
      const data = await res.json();
      if (data.session_id) {
        sessionRef.current = data.session_id;
        setSessionId(data.session_id);
      }
      return {
        reply: data.reply || '',
        offers: (data.offers || []).map(normalizeHermesOffer),
      };
    } catch (e) {
      return { reply: '', offers: [] };
    }
  }

  // ─── Free-text AI chat ───────────────────────────────────
  const profileRef = useRef(profile);
  const sessionRef = useRef(sessionId);
  useEffect(() => { profileRef.current = profile; }, [profile]);
  useEffect(() => { sessionRef.current = sessionId; }, [sessionId]);

  async function askAI(userText) {
    setAiBusy(true);
    setTyping(true);
    try {
      const activeSessionId = sessionRef.current || sessionId;
      if (!activeSessionId) throw new Error('no_session');
      const res = await fetch('/api/chat/message', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({ session_id: activeSessionId, message: userText }),
      });
      if (!res.ok) throw new Error('chat_http_' + res.status);
      const data = await res.json();
      setTyping(false);
      const next = [];
      if (data.reply) next.push({ id: Math.random(), side: 'agent', kind: 'text', content: data.reply });
      setMessages(m => [...m, ...next]);
      if (next.length) playSolomiyaSound();
    } catch (e) {
      setTyping(false);
      setMessages(m => [...m, { id: Math.random(), side: 'agent', kind: 'text', content: 'Напишіть суму і що кошти потрібні на картку, а я підберу найкращі варіанти.' }]);
      playSolomiyaSound();
    }
    setAiBusy(false);
  }

  function sendFreeText(e) {
    e && e.preventDefault();
    const t = inputValue.trim();
    if (!t || aiBusy) return;
    pushUser(t);
    setInputValue('');
    askAI(t);
  }

  // ─── Renderers ────────────────────────────────────────────
  function renderMessage(m) {
    if (m.side === 'user') {
      return <MsgRow key={m.id} side="user"><UserBubble>{m.content}</UserBubble></MsgRow>;
    }
    if (m.kind === 'text') {
      return <MsgRow key={m.id} side="agent"><AgentBubble>{m.content}</AgentBubble></MsgRow>;
    }
    if (m.kind === 'partners') {
      return <MsgRow key={m.id} side="agent"><AgentBubble><PartnerStrip/></AgentBubble></MsgRow>;
    }
    if (m.kind === 'qr') {
      return <MsgRow key={m.id} side="agent" withAvatar={false}>
        <QuickReplies options={m.options} onPick={handleQuickReply}/>
      </MsgRow>;
    }
    if (m.kind === 'slider') {
      return <MsgRow key={m.id} side="agent" withAvatar={false}><SliderWidget {...m.config}/></MsgRow>;
    }
    if (m.kind === 'phone') {
      return <MsgRow key={m.id} side="agent" withAvatar={false}><PhoneWidget onConfirm={m.onConfirm}/></MsgRow>;
    }
    if (m.kind === 'processing') {
      return <MsgRow key={m.id} side="agent" withAvatar={false}><ProcessingWidget onDone={m.onDone}/></MsgRow>;
    }
    if (m.kind === 'summary') {
      const p = profileRef.current;
      return <MsgRow key={m.id} side="agent" withAvatar={false}>
        <div style={{ display: 'flex', flexWrap: 'wrap', gap: 6, marginTop: 2 }}>
          {p.amount && <SummaryChip label="Сума" value={RC2.formatUAH(p.amount)}/>}
          {p.term && <SummaryChip label="Термін" value={RC2.formatDays(p.term)}/>}
          {p.purpose && <SummaryChip label="Ціль" value={p.purpose.label}/>}
          {p.credit && <SummaryChip label="КІ" value={p.credit.label}/>}
        </div>
      </MsgRow>;
    }
    if (m.kind === 'mfos') {
      return <div key={m.id} ref={m.focusStart ? offerFocusRef : null}><MFOCarousel mfos={m.mfos} requestedAmount={m.requestedAmount}/></div>;
    }
    return null;
  }

  // ─── Layout ───────────────────────────────────────────────
  return (
    <div style={{
      height: '100%', display: 'flex', flexDirection: 'column',
      background: T.cream,
      fontFamily: 'Manrope, -apple-system, system-ui, sans-serif',
      position: 'relative',
    }}>
      <Header/>
      <TrustStrip/>
      <div ref={scrollRef} style={{
        flex: 1, overflowY: 'auto',
        display: 'flex', flexDirection: 'column', gap: 6,
        padding: '6px 0 8px',
        scrollBehavior: 'smooth',
      }} className="rc-scroll-y">
        {messages.map(renderMessage)}
        {typing && <Typing/>}
      </div>
      <Composer
        value={inputValue}
        onChange={setInputValue}
        onSend={sendFreeText}
        disabled={inputDisabled || aiBusy}
        placeholder={inputDisabled ? 'Заповніть форму вище…' : 'Запитайте у Соломії…'}
      />
    </div>
  );
}

// ─── Header (avatar + name + status + menu) ────────────────
function Header() {
  return (
    <div style={{
      display: 'flex', alignItems: 'center', gap: 12,
      padding: '10px 14px 10px',
      background: '#fff',
      borderBottom: '1px solid ' + T.line,
      position: 'relative', zIndex: 2,
    }}>
      <button style={iconBtn}>
        <svg width="20" height="20" viewBox="0 0 20 20" fill="none"><path d="M12 4l-6 6 6 6" stroke={T.ink} strokeWidth="2.2" strokeLinecap="round" strokeLinejoin="round"/></svg>
      </button>
      <SolomiyaAvatar size={38} online/>
      <div style={{ flex: 1, minWidth: 0 }}>
        <div style={{
          fontFamily: 'Onest, system-ui',
          fontSize: 15.5, fontWeight: 700, color: T.ink, letterSpacing: -0.3,
          display: 'flex', alignItems: 'center', gap: 6,
        }}>
          Соломія
          <svg width="13" height="13" viewBox="0 0 13 13"><circle cx="6.5" cy="6.5" r="6.5" fill={T.green}/><path d="M3.5 6.8l2 2 4-4.4" stroke="#fff" strokeWidth="1.6" fill="none" strokeLinecap="round" strokeLinejoin="round"/></svg>
        </div>
        <div style={{ fontSize: 11.5, color: T.mute, marginTop: 1, display: 'flex', alignItems: 'center', gap: 4 }}>
          <span style={{ width: 6, height: 6, borderRadius: '50%', background: '#22D26B' }}/>
          AI-консультант · Онлайн
        </div>
      </div>
      <RobocashLogo/>
    </div>
  );
}

function RobocashLogo() {
  return (
    <div style={{
      display: 'flex', alignItems: 'center', gap: 5,
      padding: '5px 9px', borderRadius: 999,
      background: T.cream, border: '1px solid ' + T.lineSoft,
    }}>
      <div style={{
        width: 16, height: 16, borderRadius: 5,
        background: T.green,
        display: 'flex', alignItems: 'center', justifyContent: 'center',
      }}>
        <svg width="10" height="10" viewBox="0 0 10 10"><rect x="1.5" y="2" width="7" height="6" rx="1.6" fill="#fff"/><circle cx="3.6" cy="5" r="0.9" fill={T.green}/><circle cx="6.4" cy="5" r="0.9" fill={T.green}/></svg>
      </div>
      <span style={{
        fontFamily: 'Onest, system-ui',
        fontSize: 11, fontWeight: 800, letterSpacing: 0.4,
        color: T.ink, textTransform: 'uppercase',
      }}>ROBOCASH</span>
    </div>
  );
}

const iconBtn = {
  width: 32, height: 32, borderRadius: 999,
  border: 'none', background: 'transparent',
  display: 'flex', alignItems: 'center', justifyContent: 'center',
  cursor: 'pointer',
};

// ─── Trust strip ────────────────────────────────────────────
function TrustStrip() {
  const icons = {
    check: <path d="M3 6.5l2.2 2.2 5-5.5" stroke="currentColor" strokeWidth="1.8" fill="none" strokeLinecap="round" strokeLinejoin="round"/>,
    shield: <path d="M7 1.5L2.5 3.3v3.6c0 2.4 2 4.5 4.5 5.1 2.5-.6 4.5-2.7 4.5-5.1V3.3L7 1.5z" stroke="currentColor" strokeWidth="1.4" fill="none" strokeLinejoin="round"/>,
    gift: <g stroke="currentColor" strokeWidth="1.4" fill="none" strokeLinecap="round"><rect x="2" y="5.5" width="10" height="6" rx="1"/><path d="M2 7.5h10M7 5.5v6M5 5.5c-1 0-2-.8-2-1.8 0-.6.5-1.2 1.2-1.2 1.4 0 2.8 3 2.8 3M9 5.5c1 0 2-.8 2-1.8 0-.6-.5-1.2-1.2-1.2C8.4 2.5 7 5.5 7 5.5"/></g>,
    bolt: <path d="M7.5 1L3 7.5h3L5.5 12 10 5.5H7L7.5 1z" stroke="currentColor" strokeWidth="1.4" fill="none" strokeLinejoin="round"/>,
  };
  return (
    <div style={{
      display: 'flex', gap: 0, overflowX: 'auto',
      padding: '8px 14px',
      background: '#fff',
      borderBottom: '1px solid ' + T.line,
      scrollbarWidth: 'none',
    }} className="rc-scroll-x">
      {RC2.TRUST.map((t, i) => (
        <div key={t.label} style={{
          display: 'flex', alignItems: 'center', gap: 6,
          padding: '0 10px',
          borderLeft: i === 0 ? 'none' : '1px solid ' + T.lineSoft,
          flexShrink: 0,
        }}>
          <span style={{ color: T.green, display: 'flex' }}>
            <svg width="14" height="14" viewBox="0 0 14 14">{icons[t.icon]}</svg>
          </span>
          <span style={{ fontSize: 11.5, color: T.inkSoft, fontWeight: 600, whiteSpace: 'nowrap' }}>{t.label}</span>
        </div>
      ))}
    </div>
  );
}

// ─── Composer (bottom input) ────────────────────────────────
function Composer({ value, onChange, onSend, disabled, placeholder }) {
  return (
    <form onSubmit={onSend} style={{
      padding: '8px 12px 14px',
      background: '#fff',
      borderTop: '1px solid ' + T.line,
      display: 'flex', gap: 8, alignItems: 'flex-end',
    }}>
      <button type="button" style={{
        width: 38, height: 38, borderRadius: 12,
        background: T.cream, border: 'none',
        display: 'flex', alignItems: 'center', justifyContent: 'center',
        cursor: 'pointer', flexShrink: 0,
      }}>
        <svg width="18" height="18" viewBox="0 0 18 18"><path d="M9 3v12M3 9h12" stroke={T.inkSoft} strokeWidth="2" strokeLinecap="round"/></svg>
      </button>
      <div style={{
        flex: 1, display: 'flex', alignItems: 'center',
        background: T.cream, borderRadius: 22,
        border: '1px solid ' + T.line,
        minHeight: 38,
        padding: '0 4px 0 14px',
      }}>
        <input
          type="text"
          value={value}
          disabled={disabled}
          onChange={e => onChange(e.target.value)}
          placeholder={placeholder}
          style={{
            flex: 1, border: 'none', background: 'transparent',
            fontSize: 14.5, color: T.ink, outline: 'none',
            fontFamily: 'inherit', padding: '9px 4px',
            opacity: disabled ? 0.5 : 1,
          }}
        />
        <button type="submit" disabled={disabled || !value.trim()} style={{
          width: 30, height: 30, borderRadius: '50%',
          background: (!disabled && value.trim()) ? T.green : T.creamDeep,
          border: 'none', flexShrink: 0,
          display: 'flex', alignItems: 'center', justifyContent: 'center',
          cursor: (!disabled && value.trim()) ? 'pointer' : 'not-allowed',
          transition: 'all 0.15s',
          margin: '4px',
        }}>
          <svg width="14" height="14" viewBox="0 0 14 14"><path d="M2 7h10M8 3l4 4-4 4" stroke="#fff" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" fill="none"/></svg>
        </button>
      </div>
    </form>
  );
}

window.Chat = Chat;
