// MiraChat — replaces the old VoiceCoach component on the marketing site.
//
// What changed (vs the old window.claude / web-speech voice demo):
//   - Calls the real KeepAfter backend (the same Anthropic-backed Mira the iOS
//     app uses), via the public /api/coach/public-chat endpoint.
//   - No voice — chat only. The voice demo was misleading because voice isn't
//     in the iOS MVP. We don't ship demos for features we don't have.
//   - 5-message session cap (server-enforced), with a "Download AFTER" CTA
//     that fades in at message 4 and replaces the input at message 5.
//   - Session id is generated client-side per page load (no PII, no cookies).
//   - All responses come from the same Mira system prompt as the app.
//
// Props:
//   seedQuestion  — optional string. If provided, the question is pre-loaded
//                   as the first user turn and Mira's reply streams in
//                   automatically on mount.
//   greeting      — optional string. Overrides Mira's opening line.
//
// Public-chat backend is rate-limited (per-IP + global daily cost ceiling)
// and Haiku-only, so abuse just hits the "demo unavailable" message rather
// than draining the API budget.

const KA_BACKEND_URL =
  (typeof window !== 'undefined' && window.KEEPAFTER_BACKEND_URL) ||
  'https://after-backend.vercel.app';

const MC_COLORS = {
  bg: '#ffffff',
  panel: '#fafaf8',
  ink: '#0f0f0f',
  inkSoft: '#52525b',
  border: '#e2e0db',
  green: '#3d6b4f',
  greenDark: '#2a4d38',
  greenLight: '#e8f0eb',
  cream: '#fafaf8',
};

const APP_STORE_URL = 'https://apps.apple.com/app/id0000000000'; // TODO: real id after App Store launch

const DEFAULT_GREETING =
  "i'm mira, your keepafter coach. food noise, scale stuff, building habits that actually stick — that's my lane. what's going on?";

function genSessionId() {
  if (typeof crypto !== 'undefined' && crypto.randomUUID) return crypto.randomUUID();
  return 'mc-' + Math.random().toString(36).slice(2) + '-' + Date.now();
}

function MiraChat({ seedQuestion, greeting }) {
  const resolvedGreeting = greeting || DEFAULT_GREETING;

  // Build initial messages synchronously in the useState initializer to avoid
  // any flash: greeting bubble (assistant) + optional seed question (user).
  const [messages, setMessages] = React.useState(() => {
    const init = [
      { id: 'a-greeting', role: 'assistant', content: resolvedGreeting },
    ];
    if (seedQuestion) {
      init.push({ id: 'u-seed', role: 'user', content: seedQuestion });
    }
    return init;
  });

  const [input, setInput] = React.useState('');
  // Start in thinking state immediately when a seed is present so the UI
  // shows "Thinking…" before the first effect fires.
  const [thinking, setThinking] = React.useState(!!seedQuestion);
  const [remaining, setRemaining] = React.useState(5);
  const [demoOver, setDemoOver] = React.useState(false);
  const [error, setError] = React.useState(null);
  const sessionIdRef = React.useRef(genSessionId());
  const scrollRef = React.useRef(null);
  // Guard so the seed effect only fires once even in React Strict Mode.
  const seedFiredRef = React.useRef(false);

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

  // ── Core network helper ──────────────────────────────────────────────────
  // Extracted so both sendMessage() and the seed effect can reuse it.
  async function requestReply(historyForApi, userText) {
    let reply = '';
    let isLast = false;
    let demoLimit = false;
    try {
      const res = await fetch(`${KA_BACKEND_URL}/api/coach/public-chat`, {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({
          message: userText,
          session_id: sessionIdRef.current,
          history: historyForApi,
        }),
      });
      const data = await res.json().catch(() => ({}));
      if (res.status === 429 && data.demo_limit) {
        demoLimit = true;
        reply = data.error || 'Demo limit reached.';
      } else if (!res.ok) {
        reply = data.error || 'Mira is unavailable right now. Please try again in a moment.';
        setError('network');
      } else {
        reply = (data.reply || '').trim();
        if (typeof data.remaining === 'number') setRemaining(Math.max(0, data.remaining));
        isLast = Boolean(data.is_last);
      }
    } catch (e) {
      reply = "Mira can't reach the network right now. Try again in a moment.";
      setError('network');
    }

    setMessages((m) => [...m, { id: 'a-' + Date.now(), role: 'assistant', content: reply }]);
    setThinking(false);

    if (demoLimit || isLast || remaining <= 1) {
      setDemoOver(true);
    }
  }

  // ── Seed effect — fires once on mount if seedQuestion is present ─────────
  React.useEffect(() => {
    if (!seedQuestion || seedFiredRef.current) return;
    seedFiredRef.current = true;
    const seedHistory = [{ role: 'user', content: seedQuestion }];
    requestReply(seedHistory, seedQuestion);
  }, []); // intentional empty deps — one-shot on mount

  // ── User-initiated send ──────────────────────────────────────────────────
  async function sendMessage(textOverride) {
    const text = (textOverride ?? input).trim();
    if (!text || thinking || demoOver) return;

    const userId = 'u-' + Date.now();
    setMessages((m) => [...m, { id: userId, role: 'user', content: text }]);
    setInput('');
    setThinking(true);
    setError(null);

    // History we send to the backend (oldest → newest, sans greeting).
    const history = [...messages, { role: 'user', content: text }]
      .filter((m) => m.role === 'user' || m.role === 'assistant')
      .slice(-8)
      .map((m) => ({ role: m.role, content: m.content }));

    await requestReply(history, text);
  }

  return (
    <div
      style={{
        width: '100%',
        maxWidth: 460,
        background: MC_COLORS.bg,
        border: `1px solid ${MC_COLORS.border}`,
        borderRadius: 24,
        padding: 16,
        boxShadow: '0 30px 80px -30px rgba(15,15,15,0.18)',
        fontFamily: '"DM Sans", system-ui, sans-serif',
        color: MC_COLORS.ink,
      }}
    >
      {/* Header */}
      <div
        style={{
          display: 'flex',
          alignItems: 'center',
          gap: 12,
          padding: '4px 8px 14px',
          borderBottom: `1px solid ${MC_COLORS.border}`,
        }}
      >
        <div
          style={{
            width: 36,
            height: 36,
            borderRadius: '50%',
            background: `radial-gradient(circle at 35% 35%, ${MC_COLORS.greenDark}, ${MC_COLORS.green})`,
          }}
        />
        <div style={{ flex: 1 }}>
          <div style={{ fontWeight: 600, fontSize: 15 }}>Mira</div>
          <div style={{ fontSize: 12, color: MC_COLORS.inkSoft }}>
            {demoOver ? 'Demo limit reached' : thinking ? 'Thinking…' : 'Ready'}
          </div>
        </div>
        <div
          style={{
            fontSize: 11,
            color: MC_COLORS.inkSoft,
            fontWeight: 500,
            padding: '4px 10px',
            background: MC_COLORS.panel,
            borderRadius: 999,
          }}
        >
          Live demo · {remaining} left
        </div>
      </div>

      {/* Messages */}
      <div
        ref={scrollRef}
        style={{
          padding: '14px 6px 8px',
          minHeight: 280,
          maxHeight: 400,
          overflowY: 'auto',
          display: 'flex',
          flexDirection: 'column',
          gap: 10,
        }}
      >
        {messages.map((m) => (
          <div
            key={m.id}
            style={{
              alignSelf: m.role === 'user' ? 'flex-end' : 'flex-start',
              maxWidth: '82%',
              padding: '10px 14px',
              borderRadius: 16,
              background: m.role === 'user' ? MC_COLORS.green : MC_COLORS.panel,
              color: m.role === 'user' ? '#ffffff' : MC_COLORS.ink,
              fontSize: 14.5,
              lineHeight: 1.45,
              whiteSpace: 'pre-wrap',
              wordBreak: 'break-word',
            }}
          >
            {m.content}
          </div>
        ))}
        {thinking && (
          <div
            style={{
              alignSelf: 'flex-start',
              padding: '10px 14px',
              borderRadius: 16,
              background: MC_COLORS.panel,
              color: MC_COLORS.inkSoft,
              fontSize: 14,
              fontStyle: 'italic',
            }}
          >
            mira is thinking…
          </div>
        )}
      </div>

      {/* Input or CTA */}
      {demoOver ? (
        <div
          style={{
            marginTop: 12,
            padding: '18px 16px',
            background: MC_COLORS.greenLight,
            border: `1px solid ${MC_COLORS.green}`,
            borderRadius: 16,
            textAlign: 'center',
          }}
        >
          <div
            style={{
              fontFamily: '"DM Serif Display", Georgia, serif',
              fontSize: 18,
              color: MC_COLORS.ink,
              marginBottom: 6,
              lineHeight: 1.3,
            }}
          >
            Mira remembers you in the app.
          </div>
          <div style={{ fontSize: 13, color: MC_COLORS.inkSoft, marginBottom: 14, lineHeight: 1.5 }}>
            On the demo she starts fresh every session. In AFTER she remembers your goals, your food noise patterns, and what you told her last week.
          </div>
          <a
            href={APP_STORE_URL}
            target="_blank"
            rel="noopener noreferrer"
            style={{
              display: 'inline-block',
              padding: '12px 22px',
              background: MC_COLORS.green,
              color: '#fff',
              fontSize: 14,
              fontWeight: 600,
              borderRadius: 12,
              textDecoration: 'none',
            }}
          >
            Download AFTER
          </a>
        </div>
      ) : (
        <div style={{ marginTop: 10 }}>
          <div
            style={{
              display: 'flex',
              gap: 8,
              alignItems: 'flex-end',
              padding: '10px 12px',
              background: MC_COLORS.panel,
              border: `1px solid ${MC_COLORS.border}`,
              borderRadius: 16,
            }}
          >
            <textarea
              value={input}
              onChange={(e) => setInput(e.target.value)}
              onKeyDown={(e) => {
                if (e.key === 'Enter' && !e.shiftKey) {
                  e.preventDefault();
                  sendMessage();
                }
              }}
              placeholder="Message Mira…"
              rows={1}
              maxLength={1000}
              style={{
                flex: 1,
                resize: 'none',
                border: 'none',
                outline: 'none',
                background: 'transparent',
                fontFamily: 'inherit',
                fontSize: 14.5,
                color: MC_COLORS.ink,
                lineHeight: 1.45,
                maxHeight: 100,
              }}
            />
            <button
              onClick={() => sendMessage()}
              disabled={!input.trim() || thinking}
              style={{
                width: 36,
                height: 36,
                borderRadius: '50%',
                background:
                  input.trim() && !thinking ? MC_COLORS.green : MC_COLORS.border,
                color: '#fff',
                border: 'none',
                cursor: input.trim() && !thinking ? 'pointer' : 'not-allowed',
                display: 'flex',
                alignItems: 'center',
                justifyContent: 'center',
                fontSize: 16,
              }}
              aria-label="Send"
            >
              <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.5" strokeLinecap="round" strokeLinejoin="round">
                <line x1="22" y1="2" x2="11" y2="13" />
                <polygon points="22 2 15 22 11 13 2 9 22 2" />
              </svg>
            </button>
          </div>
          <div
            style={{
              marginTop: 10,
              fontSize: 11,
              color: MC_COLORS.inkSoft,
              textAlign: 'center',
              lineHeight: 1.5,
            }}
          >
            This is the real Mira. {remaining} message{remaining === 1 ? '' : 's'} left in this demo.
            {' '}She remembers everything in the <a href={APP_STORE_URL} style={{ color: MC_COLORS.green, fontWeight: 600 }}>iOS app</a>.
          </div>
        </div>
      )}
    </div>
  );
}

// Back-compat exports: the old VoiceCoach is gone; anywhere the page imported
// it now gets MiraChat. The `defaultMode` prop is accepted and ignored — the
// only mode is text.
window.MiraChat = MiraChat;
window.VoiceCoach = MiraChat;
