// AI Chat with Oracle agent

const Chat = ({ coin, aiReport, onBack, personality = 'analyst' }) => {
  const seedScore = aiReport?.score ?? coin?.score;
  const seedVerdict = aiReport?.verdict ?? coin?.verdict;
  const [messages, setMessages] = React.useState(() => [
    { role: 'oracle', text: `I've finished analyzing $${coin.ticker}. Composite score ${seedScore}/100 — ${seedVerdict}. Ask me anything about it.` },
  ]);
  const [input, setInput] = React.useState('');
  const [thinking, setThinking] = React.useState(false);
  const scrollRef = React.useRef(null);
  const personalityRef = React.useRef(personality);
  personalityRef.current = personality;
  const coinCtxRef = React.useRef(buildCoinContext(coin, aiReport));
  React.useEffect(() => { coinCtxRef.current = buildCoinContext(coin, aiReport); }, [coin, aiReport]);
  const messagesRef = React.useRef(messages);
  messagesRef.current = messages;

  React.useEffect(() => {
    if (scrollRef.current) scrollRef.current.scrollTop = scrollRef.current.scrollHeight;
  }, [messages, thinking]);

  const send = async (text) => {
    const t = (text || input).trim();
    if (!t) return;
    setMessages(m => [...m, { role: 'user', text: t }]);
    setInput('');
    setThinking(true);
    try {
      const reply = await window.callOracleChat({
        ca: coin?.ca,
        coinContext: coinCtxRef.current,
        history: messagesRef.current,
        message: t,
        personality: personalityRef.current,
      });
      setThinking(false);
      typeReply(reply || '…');
    } catch (e) {
      setThinking(false);
      setMessages(m => [...m, { role: 'oracle', text: `<span style="color:var(--red)">AI is offline right now. ${escapeHtml(e?.message || 'Unknown error')}</span>` }]);
    }
  };

  const typeReply = (full) => {
    let i = 0;
    setMessages(m => [...m, { role: 'oracle', text: '' }]);
    const tick = () => {
      i += Math.max(2, Math.round(full.length / 60));
      setMessages(m => {
        const copy = [...m];
        copy[copy.length - 1] = { role: 'oracle', text: full.slice(0, i) };
        return copy;
      });
      if (i < full.length) setTimeout(tick, 22);
    };
    tick();
  };

  return (
    <div style={{ flex: 1, display: 'flex', flexDirection: 'column', minHeight: 0 }}>
      {/* Header */}
      <div style={{
        padding: '18px 32px',
        borderBottom: '1px solid var(--line)',
        display: 'flex', alignItems: 'center', gap: 14,
      }}>
        <img src="/sixclaw.png" alt="Sixclaw" width={38} height={38} style={{
          display: 'block', objectFit: 'contain',
          filter: 'drop-shadow(0 0 10px rgba(168,130,255,0.6))',
        }} />
        <div style={{ flex: 1 }}>
          <div style={{ fontWeight: 700, fontSize: 14, display: 'flex', alignItems: 'center', gap: 8 }}>
            Sixclaw <Badge tone="green" size="sm" dot>online</Badge>
          </div>
          <div style={{ fontSize: 11, color: 'var(--ink-3)', fontFamily: 'var(--mono)' }}>
            context · ${coin.ticker} · score {coin.score} · {coin.verdict} · {personalityLabel(personality)}
          </div>
        </div>
        <button onClick={onBack} style={{
          padding: '7px 12px', borderRadius: 2,
          background: 'rgba(168,130,255,0.06)', border: '1px solid var(--line-2)',
          color: 'var(--ink-2)', fontSize: 12,
        }}>← Back to report</button>
      </div>

      {/* Messages */}
      <div ref={scrollRef} style={{ flex: 1, overflowY: 'auto', padding: '24px 32px' }}>
        <div style={{ maxWidth: 760, margin: '0 auto', display: 'flex', flexDirection: 'column', gap: 20 }}>
          {messages.map((m, i) => <Bubble key={i} msg={m} />)}
          {thinking && (
            <div style={{ display: 'flex', gap: 12, alignItems: 'flex-start', animation: 'fadeIn 0.2s' }}>
              <Avatar />
              <div style={{
                padding: '12px 16px', borderRadius: 3,
                background: 'rgba(168,130,255,0.06)', border: '1px solid var(--line)',
                fontSize: 13, color: 'var(--ink-3)', display: 'flex', alignItems: 'center', gap: 4,
              }}>
                <span className="shimmer">Reading on-chain data</span><ThinkDots />
              </div>
            </div>
          )}
        </div>
      </div>

      {/* Suggestions */}
      {messages.length <= 2 && !thinking && (
        <div style={{ padding: '0 32px 12px', display: 'flex', gap: 8, justifyContent: 'center', flexWrap: 'wrap' }}>
          {(Array.isArray(aiReport?.suggestedQuestions) && aiReport.suggestedQuestions.length > 0
            ? aiReport.suggestedQuestions.slice(0, 4)
            : window.CHAT_SUGGESTIONS).map(s => (
            <button key={s} onClick={() => send(s)} className="ob ob-sm" style={{
              borderColor: 'var(--line-2)', color: 'var(--ink-2)',
            }}>
              {s}
            </button>
          ))}
        </div>
      )}

      {/* Input */}
      <div style={{ padding: '14px 32px 24px', borderTop: '1px solid var(--line)' }}>
        <div style={{
          maxWidth: 760, margin: '0 auto',
          display: 'flex', alignItems: 'center', gap: 10,
          background: 'rgba(28,21,48,0.5)', border: '1px solid var(--line-2)',
          borderRadius: 3, padding: 6,
        }}>
          <input
            value={input}
            onChange={e => setInput(e.target.value)}
            onKeyDown={e => e.key === 'Enter' && send()}
            placeholder={`Ask anything about $${coin.ticker}…`}
            style={{
              flex: 1, background: 'transparent', border: 'none', outline: 'none',
              padding: '12px 14px', fontSize: 14, color: 'var(--ink)',
            }}
          />
          <button onClick={() => send()} className="ob" style={{
            minWidth: 96, height: 40, justifyContent: 'center',
          }}>
            <span style={{ display: 'inline-flex', alignItems: 'center' }}>
              <svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor"
                   strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
                <path d="m4 12 16-8-5 18-4-7-7-3Z" />
              </svg>
            </span>
            <span>Send</span>
          </button>
        </div>
        <div style={{ textAlign: 'center', fontSize: 10, color: 'var(--ink-4)', marginTop: 8, fontFamily: 'var(--mono)' }}>
          Sixclaw can be wrong. Verify on-chain. Not financial advice.
        </div>
      </div>
    </div>
  );
};

const Avatar = () => (
  <img src="/sixclaw.png" alt="Sixclaw" width={30} height={30} style={{
    display: 'block', objectFit: 'contain', flexShrink: 0,
    filter: 'drop-shadow(0 0 8px rgba(168,130,255,0.5))',
  }} />
);

const Bubble = ({ msg }) => {
  const isUser = msg.role === 'user';
  if (isUser) {
    return (
      <div style={{ display: 'flex', justifyContent: 'flex-end' }}>
        <div style={{
          maxWidth: '78%', padding: '10px 14px', borderRadius: 3,
          background: 'linear-gradient(180deg, rgba(124,77,255,0.20), rgba(91,46,255,0.16))',
          border: '1px solid rgba(168,130,255,0.25)',
          fontSize: 14, lineHeight: 1.55, color: 'var(--ink)',
        }}>{msg.text}</div>
      </div>
    );
  }
  return (
    <div style={{ display: 'flex', gap: 12, alignItems: 'flex-start', animation: 'fadeUp 0.3s' }}>
      <Avatar />
      <div style={{
        maxWidth: '82%', padding: '12px 16px', borderRadius: 3,
        background: 'rgba(168,130,255,0.04)', border: '1px solid var(--line)',
        fontSize: 14, lineHeight: 1.6, color: 'var(--ink-2)',
        whiteSpace: 'pre-wrap',
      }}
        dangerouslySetInnerHTML={{ __html: msg.text }}
      />
    </div>
  );
};

function buildCoinContext(coin, aiReport) {
  if (!coin) return {};
  return {
    ticker: coin.ticker, name: coin.name, ca: coin.ca,
    priceUsd: coin.priceUsd, marketCap: coin.marketCap, fdv: coin.fdv,
    liquidity: coin.liquidity, volume24h: coin.volume24h,
    change1h: coin.change1h, change6h: coin.change6h, change24h: coin.change24h,
    buys24h: coin.buys24h, sells24h: coin.sells24h,
    age: coin.age, dexId: coin.dexId,
    score: aiReport?.score ?? coin.score,
    verdict: aiReport?.verdict ?? coin.verdict,
    riskLevel: aiReport?.riskLevel ?? coin.riskLevel,
    entry: aiReport?.entry, stopLoss: aiReport?.stopLoss, target: aiReport?.target,
    narrative: aiReport?.narrative,
    signalScores: (aiReport?.signals || []).map(s => ({ id: s.id, score: s.score, status: s.status })),
  };
}

function escapeHtml(s) {
  return String(s).replace(/[&<>"]/g, c => ({ '&':'&amp;', '<':'&lt;', '>':'&gt;', '"':'&quot;' }[c]));
}

// Legacy keyword reply — kept as offline fallback only.
function generateReply(q, personality = 'analyst') {
  const lower = q.toLowerCase();
  let base;
  if (lower.includes('not higher') || (lower.includes('why') && lower.includes('score'))) {
    base = `Three things capped the score at 72:\n\n<strong style="color:var(--amber)">1. Bundled wallets.</strong> 3 wallets sniped at launch and they're sitting on a combined 1.8%. If they dump together, you'll see a 6–8% wick.\n\n<strong style="color:var(--amber)">2. No tier-1 callers.</strong> Mention velocity is hot (+280%) but it's mid-tier accounts. The runners I track that hit 5×+ all had at least one tier-1 mention by this stage.\n\n<strong style="color:var(--amber)">3. Single LP pair.</strong> Liquidity is burned but it's all on Raydium. One pool = one point of failure.\n\nFix any one of those and the score moves to ~80+.`;
  } else if (lower.includes('enter') || lower.includes('buy') || lower.includes('when')) {
    base = `Patience pays here. Don't chase the candle.\n\n<strong>Plan:</strong>\n• Limit ladder between <span style="color:var(--green);font-family:var(--mono)">$0.00041</span> and <span style="color:var(--green);font-family:var(--mono)">$0.00046</span> — that's the prior consolidation deck.\n• Size: ≤1.5% of bag for a watch-tier signal.\n• Hard stop: <span style="color:var(--red);font-family:var(--mono)">$0.00032</span> (below the breakout structure).\n• First TP at 2× → <span style="color:var(--purple-glow);font-family:var(--mono)">$0.00088</span>, then trail.\n\nIf it pumps without a pullback, let it go. There will be another setup.`;
  } else if (lower.includes('change your mind') || lower.includes('upgrade')) {
    base = `I'd upgrade to <strong style="color:var(--green)">Buy</strong> if any of these print:\n\n• A tier-1 caller picks it up (instant +8 to score)\n• The bundled wallets dump and get absorbed without breaking structure\n• Holder count crosses 2,500 with top-10 concentration dropping below 25%\n• MC reclaims 600K with volume holding\n\nI'd downgrade to <strong style="color:var(--red)">Avoid</strong> if: dev wallet moves, LP gets a new pair on a sus DEX, or buy/sell ratio inverts for 30+ minutes.`;
  } else if (lower.includes('pixl') || lower.includes('compare')) {
    base = `PIXL vs NEKO at a glance:\n\n• <strong>PIXL</strong> · score 88 · already ran from 200K → 1.84M MC. Tier-1 caller on board, 2 weeks of holder accumulation. Setup is later but cleaner.\n• <strong>NEKO</strong> · score 72 · earlier in the curve, more upside if it follows pattern, but more ways for it to fumble.\n\nPIXL is the safer trade. NEKO is the higher-EV trade if you're willing to take the L on the bundle risk.`;
  } else if (lower.includes('rug') || lower.includes('safe') || lower.includes('honeypot')) {
    base = `On the contract side, NEKO is <strong style="color:var(--green)">structurally safe</strong>:\n\n• Mint authority: revoked ✓\n• Freeze authority: revoked ✓\n• Transfer tax: 0%\n• LP: 100% burned (tx verified)\n• Code matches an audited template\n\nThis isn't a pull-the-LP rug. The risk here is <em>market</em> risk — bundled wallets dumping or volume drying up — not contract risk.`;
  } else {
    base = `Good question. Based on what I'm seeing:\n\nNEKO is in the early-runner pattern but with two caveats — bundle risk and missing tier-1 social signal. The technicals support a trade, but only with a defined entry zone and stop. I wouldn't blind-buy here. Want me to walk through any specific signal in more detail?`;
  }
  return applyPersonality(base, personality);
}

function personalityLabel(p) {
  return ({ analyst: 'analyst', degen: 'degen', dry: 'academic', hype: 'hype' })[p] || 'analyst';
}

function applyPersonality(text, personality) {
  if (personality === 'degen') {
    return `<em style="color:var(--purple-glow)">[degen mode]</em> ngl — ${text}\n\n<span style="color:var(--ink-3)">tldr: don't be a midcurver. plan the trade, trade the plan, take profits.</span>`;
  }
  if (personality === 'dry') {
    return `<em style="color:var(--ink-3)">Per the on-chain telemetry and historical analog cohort:</em>\n\n${text}\n\n<span style="color:var(--ink-3)">Conclusions are probabilistic, not deterministic.</span>`;
  }
  if (personality === 'hype') {
    return `<strong style="color:var(--purple-glow)">Yo fren!</strong> 🔥 ${text}\n\n<span style="color:var(--purple-glow)">LFG — but stick to the plan, no aping in.</span>`;
  }
  return text; // analyst (default)
}

window.Chat = Chat;
