/* eslint-disable */
// ChatInterface — chat with the Pi AI agent.
// Props (TS): { initialMessages?: Message[]; onSend?(text:string):void }
// Message = { id:string; role:"user"|"agent"; text:string; ts:string; rich?:any }

const PI_RESPONSES = [
  {
    trigger: /position|p&l|pnl|exposure/i,
    text:
`Here's your current exposure snapshot:

\`\`\`positions
BTC/USDT   LONG    0.2500    65,432.10   →  67,842.31    +602.55  (+3.68%)
ETH/USDT   LONG    2.0000    3,120.50    →  3,215.67     +190.34  (+3.05%)
SOL/USDT   SHORT   10.000    175.80      →  168.34       +74.60   (+4.24%)
\`\`\`

Net unrealised **+867.49 USDT** (+3.45%). Drawdown is sitting at 2.13%, well under your 5% policy ceiling.`
  },
  {
    trigger: /alert|notify/i,
    text:
`Got it — I'll watch **BTC/USDT** and ping you the moment it prints above **70,000 USDT**.

\`\`\`alert
symbol:        BTC/USDT
condition:     price > 70,000.00 USDT
type:          Price Alert
notifications: in-app, telegram
\`\`\`

Want me to also trigger a partial take-profit if the alert fires while you're sleeping?`
  },
  {
    trigger: /risk|drawdown|safe/i,
    text:
`Across the book, your aggregate VaR(1d, 95%) is **−1,842 USDT** — about 1.4% of equity. The SOL short is the only position with notional > 1500 USDT; I'd flag that as the tail-risk concentration.

Three things I'd surface:
1. **Funding skew on SOL** is at +0.018% — your short is being subsidised right now.
2. ETH long has a stop **2.1% below entry**, which is inside the 1d ATR.
3. No active hedge on BTC despite your "hedge if exposure > 50k" rule.`
  },
];

function pickResponse(text) {
  for (const r of PI_RESPONSES) if (r.trigger.test(text)) return r.text;
  return `I can help with positions, alerts, risk checks, and order routing.

Some things to try:
• "What are my open positions?"
• "Set an alert for BTC above 70,000 USDT"
• "Run a risk audit on the current book"

You've got me wired into your Telegram and Slack gateways, so anything I do here syncs there too.`;
}

/* renders the agent's rich text — handles fenced code blocks + bold + lists */
function AgentBody({ text }) {
  const blocks = useMemo(() => {
    const out = [];
    const parts = text.split(/```([\s\S]*?)```/g);
    parts.forEach((part, i) => {
      if (i % 2 === 1) {
        const [first, ...rest] = part.split("\n");
        const lang = first.trim();
        const body = rest.join("\n");
        out.push({ kind: "code", lang, body });
      } else if (part.trim()) {
        out.push({ kind: "prose", body: part });
      }
    });
    return out;
  }, [text]);

  const renderInline = (s) => {
    const parts = s.split(/(\*\*[^*]+\*\*|`[^`]+`)/g);
    return parts.map((p, i) => {
      if (p.startsWith("**") && p.endsWith("**"))
        return <strong key={i} style={{ color: "var(--text-1)", fontWeight: 700 }}>{p.slice(2, -2)}</strong>;
      if (p.startsWith("`") && p.endsWith("`"))
        return <code key={i} className="mono" style={{
          background: "var(--bg-2)", padding: "1px 6px", borderRadius: 4,
          fontSize: 12, color: "var(--accent)", border: "1px solid var(--border-s)"
        }}>{p.slice(1, -1)}</code>;
      return p;
    });
  };

  return (
    <div style={{ display: "flex", flexDirection: "column", gap: 12 }}>
      {blocks.map((b, i) => {
        if (b.kind === "code") {
          return (
            <pre key={i} className="mono" style={{
              margin: 0,
              padding: "12px 14px",
              background: "var(--bg-0)",
              border: "1px solid var(--border-s)",
              borderRadius: "var(--r-md)",
              color: "var(--text-2)",
              fontSize: 12.5,
              lineHeight: 1.65,
              overflowX: "auto",
              whiteSpace: "pre",
              position: "relative",
            }}>
              {b.lang && (
                <div className="mono" style={{
                  position: "absolute", top: 8, right: 10,
                  fontSize: 10, color: "var(--text-4)",
                  textTransform: "uppercase", letterSpacing: "0.08em"
                }}>{b.lang}</div>
              )}
              {colorize(b.body)}
            </pre>
          );
        }
        return (
          <div key={i} style={{ fontSize: 13.5, lineHeight: 1.65, color: "var(--text-2)" }}>
            {b.body.split("\n").map((line, j) => {
              const m = line.match(/^(\d+)\.\s+(.*)/);
              const li = line.match(/^[•\-]\s+(.*)/);
              if (m) return (
                <div key={j} style={{ display: "flex", gap: 10, padding: "2px 0" }}>
                  <span className="mono" style={{ color: "var(--accent)", minWidth: 18 }}>{m[1]}.</span>
                  <span>{renderInline(m[2])}</span>
                </div>
              );
              if (li) return (
                <div key={j} style={{ display: "flex", gap: 10, padding: "2px 0" }}>
                  <span style={{ color: "var(--accent)", minWidth: 18 }}>•</span>
                  <span>{renderInline(li[1])}</span>
                </div>
              );
              if (!line.trim()) return <div key={j} style={{ height: 4 }}/>;
              return <div key={j}>{renderInline(line)}</div>;
            })}
          </div>
        );
      })}
    </div>
  );
}

// crude syntax highlighter for code blocks (numbers green, words ALLCAPS amber-ish)
function colorize(s) {
  const tokens = s.split(/(\s+|[,.:>→])/g);
  return tokens.map((t, i) => {
    if (/^[+\-−]?\$?\d[\d,]*\.?\d*%?$/.test(t)) {
      const positive = !t.startsWith("−") && !t.startsWith("-");
      return <span key={i} style={{ color: positive ? "var(--good)" : "var(--bad)" }}>{t}</span>;
    }
    if (/^(LONG|BUY)$/.test(t)) return <span key={i} style={{ color: "var(--good)" }}>{t}</span>;
    if (/^(SHORT|SELL)$/.test(t)) return <span key={i} style={{ color: "var(--bad)" }}>{t}</span>;
    if (/^[A-Z]{3,}\/[A-Z]{3,}$/.test(t)) return <span key={i} style={{ color: "var(--text-1)" }}>{t}</span>;
    if (/^[a-z_]+:$/.test(t)) return <span key={i} style={{ color: "var(--info)" }}>{t}</span>;
    if (/^→$/.test(t)) return <span key={i} style={{ color: "var(--text-4)" }}>{t}</span>;
    return <span key={i}>{t}</span>;
  });
}

/* --- main component ----------------------------------------------- */
function ChatInterface() {
  const [messages, setMessages] = useState([
    { id: "m1", role: "user", text: "What are my current open positions?", ts: "10:30" },
    { id: "m2", role: "agent", text: PI_RESPONSES[0].text, ts: "10:30" },
    { id: "m3", role: "user", text: "Set an alert for BTC if it breaks above 70,000 USDT", ts: "10:31" },
    { id: "m4", role: "agent", text: PI_RESPONSES[1].text, ts: "10:31" },
  ]);
  const [draft, setDraft] = useState("");
  const [streaming, setStreaming] = useState(null); // {id, target, shown}
  const scroller = useRef(null);

  // auto-scroll on new content (within scroll container only — never scrollIntoView)
  useEffect(() => {
    if (!scroller.current) return;
    scroller.current.scrollTop = scroller.current.scrollHeight;
  }, [messages, streaming]);

  // streaming reveal: chunk by ~3 chars at 14ms
  useEffect(() => {
    if (!streaming) return;
    if (streaming.shown >= streaming.target.length) {
      setMessages((ms) => ms.map((m) => m.id === streaming.id ? { ...m, text: streaming.target } : m));
      setStreaming(null);
      return;
    }
    const next = Math.min(streaming.shown + 3 + Math.floor(Math.random() * 4), streaming.target.length);
    const t = setTimeout(() => {
      setMessages((ms) => ms.map((m) => m.id === streaming.id ? { ...m, text: streaming.target.slice(0, next) } : m));
      setStreaming({ ...streaming, shown: next });
    }, 14);
    return () => clearTimeout(t);
  }, [streaming]);

  const send = () => {
    const v = draft.trim();
    if (!v || streaming) return;
    const ts = new Date().toLocaleTimeString("en-US", { hour: "2-digit", minute: "2-digit", hour12: false });
    const userMsg = { id: "u" + Date.now(), role: "user", text: v, ts };
    const agentId = "a" + Date.now();
    const target = pickResponse(v);
    setMessages((ms) => [...ms, userMsg, { id: agentId, role: "agent", text: "", ts }]);
    setDraft("");
    setStreaming({ id: agentId, target, shown: 0 });
  };

  const suggestions = [
    "Run a risk audit on my book",
    "Why did the SOL position close?",
    "Pause all alerts for 1 hour",
    "What's my Telegram gateway uptime?",
  ];

  return (
    <div style={{ height: "100%", display: "grid", gridTemplateRows: "auto 1fr auto", minHeight: 0 }}>
      {/* header */}
      <header style={{
        display: "flex", alignItems: "center", gap: 14,
        padding: "20px 28px 16px",
        borderBottom: "1px solid var(--border-s)",
      }}>
        <PiAvatar large/>
        <div style={{ flex: 1, minWidth: 0 }}>
          <div style={{ display: "flex", alignItems: "center", gap: 10 }}>
            <h2 style={{ margin: 0, fontSize: 18, fontWeight: 700, letterSpacing: "-0.01em" }}>Pi</h2>
            <Pill tone="good" style={{ paddingLeft: 6 }}>
              <StatusDot tone="good" size={6}/> Online
            </Pill>
            <span style={{ fontSize: 12, color: "var(--text-4)" }}>·</span>
            <span style={{ fontSize: 12, color: "var(--text-3)" }}>haiku-4.5 · ctx 47%</span>
          </div>
          <p style={{ margin: "2px 0 0", fontSize: 13, color: "var(--text-3)" }}>
            Your trading copilot — synced to Telegram, Slack, and the live position book.
          </p>
        </div>
        <Btn kind="ghost" size="sm" icon={<I.Trash size={14}/>} onClick={() => setMessages([])}>Clear chat</Btn>
      </header>

      {/* messages */}
      <div ref={scroller} style={{
        overflowY: "auto", padding: "24px 28px 8px",
        display: "flex", flexDirection: "column", gap: 18,
      }}>
        {messages.length === 0 && <EmptyState/>}
        {messages.map((m) => (
          <MessageRow key={m.id} m={m} streaming={streaming?.id === m.id}/>
        ))}
      </div>

      {/* composer */}
      <div style={{ padding: "12px 28px 20px" }}>
        {messages.length > 0 && (
          <div style={{ display: "flex", gap: 8, marginBottom: 10, flexWrap: "wrap" }}>
            {suggestions.map((s) => (
              <button key={s} onClick={() => setDraft(s)} style={{
                background: "transparent",
                border: "1px solid var(--border-s)",
                color: "var(--text-3)",
                fontSize: 12, padding: "4px 10px", borderRadius: 999,
                transition: "all 120ms ease",
              }}
              onMouseEnter={(e) => { e.currentTarget.style.color="var(--text-1)"; e.currentTarget.style.borderColor="var(--border-m)"; }}
              onMouseLeave={(e) => { e.currentTarget.style.color="var(--text-3)"; e.currentTarget.style.borderColor="var(--border-s)"; }}
              >{s}</button>
            ))}
          </div>
        )}
        <Composer value={draft} onChange={setDraft} onSend={send} streaming={!!streaming}/>
      </div>
    </div>
  );
}

function PiAvatar({ large }) {
  const s = large ? 36 : 26;
  return (
    <div style={{
      width: s, height: s, borderRadius: 999,
      background: "linear-gradient(135deg, oklch(0.42 0.10 170), oklch(0.30 0.08 235))",
      display: "flex", alignItems: "center", justifyContent: "center",
      color: "var(--accent)", flex: "none",
      boxShadow: "inset 0 0 0 1px oklch(1 0 0 / 0.06), 0 0 0 1px var(--border-s)",
      fontFamily: "var(--font-mono)", fontWeight: 600, fontSize: large ? 16 : 12,
    }}>π</div>
  );
}

function MessageRow({ m, streaming }) {
  if (m.role === "user") {
    return (
      <div className="fade-up" style={{ display: "flex", justifyContent: "flex-end" }}>
        <div style={{
          maxWidth: "72%",
          background: "linear-gradient(180deg, oklch(0.28 0.06 235), oklch(0.24 0.05 235))",
          border: "1px solid oklch(0.45 0.08 235 / 0.4)",
          color: "var(--text-1)",
          padding: "10px 14px",
          borderRadius: "14px 14px 4px 14px",
          fontSize: 13.5, lineHeight: 1.55,
        }}>
          <div>{m.text}</div>
          <div style={{ fontSize: 10.5, color: "oklch(0.85 0.04 235)", marginTop: 4, textAlign: "right", opacity: 0.7 }} className="mono">
            {m.ts} · sent ✓✓
          </div>
        </div>
      </div>
    );
  }
  return (
    <div className="fade-up" style={{ display: "flex", gap: 12, alignItems: "flex-start", maxWidth: "84%" }}>
      <PiAvatar/>
      <div style={{
        flex: 1, minWidth: 0,
        background: "var(--bg-1)",
        border: "1px solid var(--border-s)",
        borderRadius: "4px 14px 14px 14px",
        padding: "14px 16px",
      }}>
        {m.text
          ? <AgentBody text={m.text}/>
          : <TypingDots/>
        }
        {streaming && m.text && <Caret/>}
        <div style={{ fontSize: 10.5, color: "var(--text-4)", marginTop: 8 }} className="mono">{m.ts}</div>
      </div>
    </div>
  );
}

function TypingDots() {
  return (
    <div style={{ display: "inline-flex", gap: 4, alignItems: "center", padding: "4px 0" }}>
      {[0, 1, 2].map((i) => (
        <span key={i} style={{
          width: 6, height: 6, background: "var(--text-3)", borderRadius: 999,
          animation: `pulse-dot 1.2s ease-in-out ${i * 0.18}s infinite`,
        }}/>
      ))}
    </div>
  );
}
function Caret() {
  return <span style={{
    display: "inline-block", width: 7, height: 14, background: "var(--accent)",
    marginLeft: 2, verticalAlign: "-2px", animation: "blink 1s steps(1) infinite"
  }}/>;
}

function Composer({ value, onChange, onSend, streaming }) {
  const ta = useRef(null);
  useLayoutEffect(() => {
    if (!ta.current) return;
    ta.current.style.height = "auto";
    ta.current.style.height = Math.min(140, ta.current.scrollHeight) + "px";
  }, [value]);
  return (
    <div style={{
      display: "flex", alignItems: "flex-end", gap: 10,
      padding: 10,
      background: "var(--bg-1)",
      border: "1px solid var(--border-m)",
      borderRadius: "var(--r-lg)",
      transition: "border-color 140ms ease",
    }}
    onFocus={(e) => { e.currentTarget.style.borderColor = "var(--accent-dim)"; }}
    onBlur={(e) => { e.currentTarget.style.borderColor = "var(--border-m)"; }}
    >
      <textarea
        ref={ta}
        rows={1}
        value={value}
        onChange={(e) => onChange(e.target.value)}
        onKeyDown={(e) => {
          if (e.key === "Enter" && !e.shiftKey) { e.preventDefault(); onSend(); }
        }}
        placeholder="Ask Pi about positions, alerts, runners, risk…"
        style={{
          flex: 1, resize: "none", border: "none", outline: "none",
          background: "transparent", color: "var(--text-1)",
          fontSize: 14, lineHeight: 1.5,
          padding: "6px 4px", minHeight: 22, maxHeight: 140,
        }}
      />
      <div style={{ display: "flex", alignItems: "center", gap: 6 }}>
        <span className="mono" style={{ fontSize: 10.5, color: "var(--text-4)" }}>⏎ send · ⇧⏎ newline</span>
        <button onClick={onSend} disabled={!value.trim() || streaming} title="Send"
          style={{
            width: 34, height: 34, borderRadius: "var(--r-sm)",
            background: value.trim() && !streaming ? "var(--accent)" : "var(--bg-3)",
            color: value.trim() && !streaming ? "oklch(0.18 0.04 170)" : "var(--text-4)",
            border: "none",
            display: "inline-flex", alignItems: "center", justifyContent: "center",
            transition: "all 140ms ease",
          }}>
          <I.Send size={15}/>
        </button>
      </div>
    </div>
  );
}

function EmptyState() {
  return (
    <div style={{
      flex: 1, display: "flex", flexDirection: "column",
      alignItems: "center", justifyContent: "center",
      color: "var(--text-3)", textAlign: "center",
      padding: "60px 20px",
    }}>
      <PiAvatar large/>
      <h3 style={{ margin: "16px 0 4px", color: "var(--text-1)", fontSize: 18 }}>How can I help today?</h3>
      <p style={{ margin: 0, fontSize: 13.5, maxWidth: 360 }}>
        Pi is wired into your position book, runners, and gateways. Ask anything from "how's the book" to "pause SOL strategy for an hour".
      </p>
    </div>
  );
}

window.ChatInterface = ChatInterface;
