import { useState, useRef, useEffect, useCallback } from 'react'
import { motion, AnimatePresence } from 'framer-motion'
import {
  Send, CheckCircle2, XCircle, ChevronDown, ChevronUp,
  Loader2, MessageSquare, Zap, RefreshCw, Trash2,
} from 'lucide-react'
import { useStore } from '../store/useStore'
import { streamExecuteQuery, submitFeedback, fetchPromptHistory } from '../lib/api'
import { ResultsTable } from './ResultsTable'
import type { ChatMessage, AttemptStep } from '../lib/types'

// ─── SQL Syntax Highlighter ───────────────────────────────────────

const SQL_KEYWORDS = /\b(SELECT|FROM|WHERE|JOIN|LEFT|RIGHT|INNER|OUTER|FULL|ON|GROUP\s+BY|ORDER\s+BY|HAVING|LIMIT|OFFSET|UNION|ALL|DISTINCT|AS|AND|OR|NOT|IN|IS|NULL|LIKE|BETWEEN|CASE|WHEN|THEN|ELSE|END|WITH|CTE|INSERT|UPDATE|DELETE|CREATE|DROP|ALTER|TABLE|INDEX|VIEW|SET|VALUES|INTO|EXISTS|COUNT|SUM|AVG|MIN|MAX|COALESCE|NULLIF|CAST|OVER|PARTITION\s+BY|ROW_NUMBER|RANK|DENSE_RANK|LAG|LEAD|DATE|STRFTIME|JULIANDAY|ROUND|ABS|LENGTH|SUBSTR|UPPER|LOWER|TRIM|REPLACE|IFNULL)\b/gi

function SqlBlock({ sql, streaming }: { sql: string; streaming?: boolean }) {
  const parts: React.ReactNode[] = []
  let last = 0
  let match: RegExpExecArray | null

  const re = new RegExp(SQL_KEYWORDS.source, 'gi')
  while ((match = re.exec(sql)) !== null) {
    if (match.index > last) {
      parts.push(<span key={`t-${last}`}>{sql.slice(last, match.index)}</span>)
    }
    parts.push(
      <span key={`k-${match.index}`} className="sql-keyword">
        {match[0]}
      </span>
    )
    last = match.index + match[0].length
  }
  if (last < sql.length) {
    parts.push(<span key={`t-end`}>{sql.slice(last)}</span>)
  }

  return (
    <pre
      className="px-3 py-2.5 text-xs font-mono bg-violet-950/20 whitespace-pre-wrap overflow-x-auto leading-relaxed border-t border-white/[0.04]"
      style={{ color: 'rgba(221, 214, 254, 0.8)' }}
    >
      {parts}
      {streaming && <span className="cursor-blink" />}
    </pre>
  )
}

// ─── Attempt badge ────────────────────────────────────────────────

function AttemptBadge({ attempt, total }: { attempt: number; total: number }) {
  const colors =
    attempt === 1
      ? 'text-gray-400 bg-white/5 border-white/10'
      : attempt === 2
      ? 'text-amber-400 bg-amber-500/10 border-amber-500/20'
      : attempt === 3
      ? 'text-orange-400 bg-orange-500/10 border-orange-500/20'
      : 'text-red-400 bg-red-500/10 border-red-500/20'

  return (
    <span className={`text-[10px] font-semibold px-2 py-0.5 rounded-full border ${colors}`}>
      Attempt {attempt}/{total}
    </span>
  )
}

// ─── RL Action badge ──────────────────────────────────────────────

function RLActionBadge({ action, score }: { action: string; score?: number }) {
  return (
    <span className="inline-flex items-center gap-1 text-[10px] font-semibold px-2 py-0.5 rounded-full border border-orange-500/30 bg-orange-500/10 text-orange-400">
      <Zap size={9} />
      {action}
      {score !== undefined && (
        <span className="text-orange-400/60 ml-0.5">{score.toFixed(2)}</span>
      )}
    </span>
  )
}

// ─── Reward display ──────────────────────────────────────────────

function RewardBadge({ reward }: { reward: number }) {
  const positive = reward >= 0
  return (
    <motion.span
      initial={{ scale: 0.8, opacity: 0 }}
      animate={{ scale: 1, opacity: 1 }}
      transition={{ type: 'spring', stiffness: 300 }}
      className={`inline-flex items-center gap-0.5 text-[11px] font-bold tabular-nums reward-pulse ${
        positive ? 'text-green-400' : 'text-red-400'
      }`}
    >
      {positive ? '+' : ''}{reward.toFixed(2)}
    </motion.span>
  )
}

// ─── Attempt steps collapsible ────────────────────────────────────

function AttemptSteps({ steps }: { steps: AttemptStep[] }) {
  const [open, setOpen] = useState(false)
  if (steps.length <= 1) return null

  return (
    <div className="border border-white/[0.05] rounded-xl overflow-hidden">
      <button
        onClick={() => setOpen((v) => !v)}
        className="w-full flex items-center justify-between px-3 py-2 bg-white/[0.02] hover:bg-white/[0.04] transition-colors text-[10px] text-gray-500"
      >
        <span>{steps.length} attempts to solve</span>
        {open ? <ChevronUp size={11} /> : <ChevronDown size={11} />}
      </button>
      <AnimatePresence>
        {open && (
          <motion.div
            initial={{ height: 0, opacity: 0 }}
            animate={{ height: 'auto', opacity: 1 }}
            exit={{ height: 0, opacity: 0 }}
            transition={{ duration: 0.15 }}
            className="overflow-hidden"
          >
            <div className="flex flex-col divide-y divide-white/[0.04]">
              {steps.map((step) => (
                <div key={step.attempt} className="px-3 py-2">
                  <div className="flex items-center gap-2 mb-1.5">
                    <AttemptBadge attempt={step.attempt} total={steps.length} />
                    {step.action && (
                      <RLActionBadge action={step.action} score={step.actionScore} />
                    )}
                    {step.reward !== undefined && <RewardBadge reward={step.reward} />}
                  </div>
                  {step.error && (
                    <div className="text-[10px] text-red-400/70 mb-1 bg-red-500/5 rounded px-2 py-1 border border-red-500/15">
                      {step.error}
                    </div>
                  )}
                  <SqlBlock sql={step.sql} />
                </div>
              ))}
            </div>
          </motion.div>
        )}
      </AnimatePresence>
    </div>
  )
}

// ─── Suggested query chips ────────────────────────────────────────

const SUGGESTED: Record<string, string[]> = {
  easy: ['Show all products', 'List users from USA', 'What categories exist?'],
  medium: ['Top 5 sellers by revenue', 'Average order value by country', 'Products with low stock'],
  hard: ['Rolling 7-day revenue', 'Seller ranking with rank change', 'Cohort retention analysis'],
}

function SuggestionSkeleton() {
  return (
    <div className="flex flex-col gap-2 w-full max-w-sm">
      {[90, 110, 80].map((w, i) => (
        <div
          key={i}
          className="flex items-center gap-2 px-3 py-2.5 rounded-xl border border-white/[0.06] bg-white/[0.02]"
        >
          <div className="w-1 h-3 rounded bg-violet-500/20 animate-pulse shrink-0" />
          <div
            className="h-3 rounded bg-white/8 animate-pulse"
            style={{ width: w }}
          />
        </div>
      ))}
    </div>
  )
}

function EmptyState({ onSelect }: { onSelect: (q: string) => void }) {
  const { taskDifficulty, isCustomDb, customDbSuggestions, suggestionsLoading } = useStore()
  const suggestions = isCustomDb ? customDbSuggestions : (SUGGESTED[taskDifficulty] ?? SUGGESTED.easy)

  return (
    <div className="flex flex-col items-center justify-center h-full gap-6 px-8 text-center">
      <div>
        <div
          className="w-12 h-12 rounded-2xl flex items-center justify-center mx-auto mb-4"
          style={{ background: '#1e3a5f', boxShadow: '0 8px 24px rgba(30,58,95,0.4)' }}
        >
          <MessageSquare size={22} className="text-white" />
        </div>
        <h2 className="text-base font-semibold text-white mb-1">Ask about your data</h2>
        <p className="text-xs text-gray-500 max-w-xs">
          Type a question in natural language. The agent will generate SQL, execute it,
          and self-repair on errors using reinforcement learning.
        </p>
      </div>

      <div className="flex flex-col gap-2 w-full max-w-sm">
        <div className="text-[10px] text-gray-600 uppercase tracking-wider mb-0.5">
          {isCustomDb && suggestionsLoading ? 'Generating suggestions…' : 'Try these queries'}
        </div>
        {isCustomDb && suggestionsLoading ? (
          <SuggestionSkeleton />
        ) : suggestions.length > 0 ? (
          suggestions.map((q) => (
            <button
              key={q}
              onClick={() => onSelect(q)}
              className="flex items-center gap-2 px-3 py-2.5 rounded-xl border border-white/[0.06] bg-white/[0.02] hover:bg-white/[0.05] hover:border-violet-500/30 transition-all text-left group"
            >
              <span className="text-violet-500 shrink-0 group-hover:text-violet-400">›</span>
              <span className="text-xs text-gray-300">{q}</span>
            </button>
          ))
        ) : null}
      </div>
    </div>
  )
}

// ─── Message Card ─────────────────────────────────────────────────

function MessageCard({
  msg,
  onFeedback,
  onRetry,
}: {
  msg: ChatMessage
  onFeedback: (id: string, correct: boolean, remark?: string) => Promise<void>
  onRetry: (q: string, previousSql?: string) => void
}) {
  const [sqlOpen, setSqlOpen] = useState(true)
  const [wrongOpen, setWrongOpen] = useState(false)
  const [remark, setRemark] = useState('')

  return (
    <div className="flex flex-col gap-2.5">
      {/* User question bubble */}
      <div className="flex justify-end">
        <div className="max-w-[80%] bg-violet-600/20 border border-violet-500/25 rounded-2xl rounded-tr-sm px-4 py-2.5">
          <p className="text-sm text-white leading-relaxed">{msg.question}</p>
        </div>
      </div>

      {/* Agent response */}
      <div className="flex flex-col gap-2">
        {/* Streaming thinking */}
        {msg.status === 'streaming' && !msg.sql && (
          <div className="flex items-center gap-2 text-xs text-gray-500 px-1">
            <Loader2 size={11} className="animate-spin text-violet-400" />
            Generating SQL...
          </div>
        )}

        {/* Multiple attempts */}
        <AttemptSteps steps={msg.steps} />

        {/* Final SQL block */}
        {msg.sql && (
          <div className="border border-white/[0.06] rounded-xl overflow-hidden">
            <button
              onClick={() => setSqlOpen((v) => !v)}
              className="w-full flex items-center justify-between px-3 py-2 bg-white/[0.02] hover:bg-white/[0.04] transition-colors"
            >
              <div className="flex items-center gap-2">
                <span className="text-[10px] font-semibold text-gray-500 uppercase tracking-wider">
                  SQL
                </span>
                {msg.status === 'streaming' && (
                  <Loader2 size={10} className="animate-spin text-violet-400" />
                )}
                {msg.attempts > 1 && (
                  <AttemptBadge attempt={msg.attempts} total={msg.attempts} />
                )}
              </div>
              {sqlOpen ? (
                <ChevronUp size={11} className="text-gray-600" />
              ) : (
                <ChevronDown size={11} className="text-gray-600" />
              )}
            </button>
            {sqlOpen && (
              <SqlBlock sql={msg.sql} streaming={msg.status === 'streaming'} />
            )}
          </div>
        )}

        {/* Executing indicator */}
        {msg.status === 'streaming' && msg.sql && msg.rows.length === 0 && !msg.errorMsg && (
          <div className="flex items-center gap-2 text-xs text-gray-500 px-1">
            <Loader2 size={11} className="animate-spin text-violet-400" />
            Executing...
          </div>
        )}

        {/* RL badges row */}
        {(msg.rlAction || msg.reward !== undefined) && (
          <div className="flex items-center gap-2 flex-wrap">
            {msg.rlAction && (
              <RLActionBadge action={msg.rlAction} score={msg.rlActionScore} />
            )}
            {msg.reward !== undefined && <RewardBadge reward={msg.reward} />}
          </div>
        )}

        {/* Result table */}
        {msg.status === 'done' && msg.attempts > 0 && (
          <div className="flex flex-col gap-1.5">
            <div className="flex items-center gap-2 text-[10px] px-0.5">
              <CheckCircle2 size={11} className="text-green-400" />
              <span className="text-green-400 font-semibold">Success</span>
              <span className="text-gray-600">
                · {msg.rowCount} row{msg.rowCount !== 1 ? 's' : ''}
              </span>
              {msg.attempts > 1 && (
                <span className="text-amber-400/60">{msg.attempts} attempts</span>
              )}
            </div>
            <ResultsTable rows={msg.rows} rowCount={msg.rowCount} />
          </div>
        )}

        {/* Error */}
        {msg.status === 'error' && (
          <div className="flex items-start gap-2 bg-red-500/10 border border-red-500/20 rounded-xl px-3 py-2.5 text-xs text-red-300">
            <XCircle size={12} className="shrink-0 mt-0.5" />
            <div>
              <p className="font-semibold mb-0.5">Query failed</p>
              <p className="opacity-80">{msg.errorMsg ?? 'Agent exhausted all repair attempts'}</p>
            </div>
          </div>
        )}

        {/* Feedback */}
        {msg.status === 'done' && msg.attempts > 0 && (
          <div className="flex flex-col gap-2">
            <div className="flex items-center gap-2">
              {msg.feedback ? (
                <div className={`text-xs flex items-center gap-1.5 ${msg.feedback === 'correct' ? 'text-green-400' : 'text-red-400'}`}>
                  {msg.feedback === 'correct' ? <CheckCircle2 size={12} /> : <XCircle size={12} />}
                  Marked as {msg.feedback}
                </div>
              ) : (
                <>
                  <span className="text-[10px] text-gray-600 mr-0.5">Was this correct?</span>
                  <button
                    disabled={msg.feedbackSending}
                    onClick={() => onFeedback(msg.id, true)}
                    className="flex items-center gap-1 px-2 py-1 text-[10px] font-medium rounded-lg border border-green-500/25 bg-green-500/8 text-green-400 hover:bg-green-500/15 transition-all disabled:opacity-40"
                  >
                    <CheckCircle2 size={10} />
                    Correct
                  </button>
                  <button
                    disabled={msg.feedbackSending}
                    onClick={() => setWrongOpen((v) => !v)}
                    className={`flex items-center gap-1 px-2 py-1 text-[10px] font-medium rounded-lg border transition-all disabled:opacity-40 ${
                      wrongOpen
                        ? 'border-red-500/40 bg-red-500/15 text-red-300'
                        : 'border-red-500/25 bg-red-500/8 text-red-400 hover:bg-red-500/15'
                    }`}
                  >
                    <XCircle size={10} />
                    Wrong
                    <ChevronDown size={9} className={`transition-transform ${wrongOpen ? 'rotate-180' : ''}`} />
                  </button>
                </>
              )}
              {(msg.status === 'done' || msg.status === 'error') && (
                <button
                  onClick={() => onRetry(msg.question, msg.feedback === 'wrong' ? msg.sql : undefined)}
                  className="ml-auto flex items-center gap-1 text-[10px] text-gray-600 hover:text-gray-400 transition-colors"
                >
                  <RefreshCw size={10} />
                  {msg.feedback === 'wrong' ? 'Retry differently' : 'Retry'}
                </button>
              )}
            </div>

            {/* Remarks dropdown for Wrong */}
            <AnimatePresence>
              {wrongOpen && !msg.feedback && (
                <motion.div
                  initial={{ height: 0, opacity: 0 }}
                  animate={{ height: 'auto', opacity: 1 }}
                  exit={{ height: 0, opacity: 0 }}
                  transition={{ duration: 0.15 }}
                  className="overflow-hidden"
                >
                  <div className="flex flex-col gap-2 p-3 rounded-xl border border-red-500/20 bg-red-500/5">
                    <p className="text-[10px] text-red-400/80 font-medium">
                      What was wrong? <span className="text-gray-600">(optional — helps improve the prompt)</span>
                    </p>
                    <textarea
                      value={remark}
                      onChange={(e) => setRemark(e.target.value)}
                      placeholder="e.g. wrong JOIN logic, missing GROUP BY, incorrect column name…"
                      rows={2}
                      className="w-full px-3 py-2 text-xs rounded-lg border border-white/10 bg-black/20 text-gray-300 placeholder-gray-600 resize-none focus:outline-none focus:border-red-500/40 transition-colors"
                    />
                    <div className="flex items-center gap-2 justify-end">
                      <button
                        onClick={() => { setWrongOpen(false); setRemark('') }}
                        className="text-[10px] text-gray-600 hover:text-gray-400 transition-colors px-2 py-1"
                      >
                        Cancel
                      </button>
                      <button
                        disabled={msg.feedbackSending}
                        onClick={() => {
                          void onFeedback(msg.id, false, remark.trim() || undefined)
                          setWrongOpen(false)
                          setRemark('')
                        }}
                        className="flex items-center gap-1 px-3 py-1 text-[10px] font-semibold rounded-lg bg-red-500/20 border border-red-500/30 text-red-300 hover:bg-red-500/30 transition-all disabled:opacity-40"
                      >
                        {msg.feedbackSending ? <Loader2 size={9} className="animate-spin" /> : <XCircle size={9} />}
                        Submit feedback
                      </button>
                    </div>
                  </div>
                </motion.div>
              )}
            </AnimatePresence>
          </div>
        )}
      </div>
    </div>
  )
}

// ─── Chat Panel ───────────────────────────────────────────────────

export function ChatPanel() {
  const {
    messages, addMessage, updateMessage, clearMessages,
    isExecuting, setIsExecuting,
    taskId, taskDifficulty,
    optimizingBanner, setOptimizingBanner,
    promptGeneration,
    isCustomDb, customDbSuggestions,
  } = useStore()

  const [input, setInput] = useState('')
  const bottomRef = useRef<HTMLDivElement>(null)
  const inputRef = useRef<HTMLTextAreaElement>(null)

  useEffect(() => {
    bottomRef.current?.scrollIntoView({ behavior: 'smooth' })
  }, [messages.length])

  const handleFeedback = useCallback(
    async (id: string, correct: boolean, remark?: string) => {
      const msg = messages.find((m) => m.id === id)
      if (!msg) return
      updateMessage(id, { feedbackSending: true })
      try {
        await submitFeedback(msg.question, msg.sql, correct, remark)
        updateMessage(id, { feedback: correct ? 'correct' : 'wrong', feedbackSending: false })
      } catch {
        updateMessage(id, { feedbackSending: false })
      }
    },
    [messages, updateMessage]
  )

  const execute = useCallback(
    async (question: string, previousSql?: string) => {
      if (!question.trim() || isExecuting) return
      setIsExecuting(true)

      const msgId = `msg-${Date.now()}`
      const newMsg: ChatMessage = {
        id: msgId,
        question,
        status: 'streaming',
        sql: '',
        rows: [],
        rowCount: 0,
        attempts: 0,
        steps: [],
        feedback: null,
        promptGeneration,
      }
      addMessage(newMsg)

      try {
        for await (const event of streamExecuteQuery(question, taskId, previousSql)) {
          if (event.type === 'attempt_start') {
            // New attempt — clear SQL so previous attempt's SQL doesn't bleed through
            if ((event.attempt as number) > 1) {
              updateMessage(msgId, { sql: '', attempts: event.attempt as number })
            }
          } else if (event.type === 'sql') {
            updateMessage(msgId, { sql: event.sql as string })
          } else if (event.type === 'sql_chunk') {
            // incremental SQL streaming — read current sql from store
            const curSql = useStore.getState().messages.find((m) => m.id === msgId)?.sql ?? ''
            updateMessage(msgId, { sql: curSql + (event.chunk as string) })
          } else if (event.type === 'attempt') {
            const step: AttemptStep = {
              attempt: event.attempt as number,
              sql: event.sql as string,
              error: event.error as string | undefined,
              action: event.action as string | undefined,
              actionScore: event.action_score as number | undefined,
              reward: event.reward as number | undefined,
            }
            const curSteps = useStore.getState().messages.find((m) => m.id === msgId)?.steps ?? []
            updateMessage(msgId, {
              attempts: event.attempt as number,
              steps: [...curSteps, step],
              sql: event.sql as string,
              rlAction: event.action as string | undefined,
              rlActionScore: event.action_score as number | undefined,
            })
          } else if (event.type === 'result') {
            updateMessage(msgId, {
              rows: (event.rows as Record<string, unknown>[]) ?? [],
              rowCount: (event.row_count as number) ?? 0,
              reward: event.reward as number | undefined,
            })
          } else if (event.type === 'done') {
            updateMessage(msgId, {
              status: 'done',
              attempts: (event.attempts as number) ?? 1,
              reward: event.reward as number | undefined,
            })
          } else if (event.type === 'error') {
            updateMessage(msgId, {
              status: 'error',
              errorMsg: ((event.message ?? event.error) as string | undefined) ?? 'Agent exhausted all repair attempts',
            })
          } else if (event.type === 'gepa_start') {
            setOptimizingBanner(true)
          } else if (event.type === 'gepa_done') {
            setOptimizingBanner(false)
            // Refresh prompt history in right sidebar
            fetchPromptHistory()
              .then((data) => useStore.getState().setPromptData(data))
              .catch(() => { /* noop */ })
          }
        }
      } catch (err) {
        updateMessage(msgId, {
          status: 'error',
          errorMsg: err instanceof Error ? err.message : 'Network error',
        })
      } finally {
        setIsExecuting(false)
        // If still streaming after generator ends, mark done
        const finalMsg = useStore.getState().messages.find((m) => m.id === msgId)
        if (finalMsg?.status === 'streaming') {
          updateMessage(msgId, { status: finalMsg.sql ? 'done' : 'error' })
        }
      }
    },
    [isExecuting, setIsExecuting, addMessage, updateMessage, taskId, promptGeneration, setOptimizingBanner]
  )

  const handleSend = () => {
    if (!input.trim()) return
    const q = input.trim()
    setInput('')
    void execute(q)
  }

  const handleKeyDown = (e: React.KeyboardEvent<HTMLTextAreaElement>) => {
    if (e.key === 'Enter' && !e.shiftKey) {
      e.preventDefault()
      handleSend()
    }
  }

  const suggestions = isCustomDb
    ? customDbSuggestions
    : (SUGGESTED[taskDifficulty] ?? SUGGESTED.easy)

  return (
    <div className="flex flex-col h-full">
      {/* Optimizing banner */}
      <AnimatePresence>
        {optimizingBanner && (
          <motion.div
            initial={{ height: 0, opacity: 0 }}
            animate={{ height: 'auto', opacity: 1 }}
            exit={{ height: 0, opacity: 0 }}
            className="shrink-0 overflow-hidden"
          >
            <div className="shimmer-banner border-b border-violet-500/20 px-4 py-2 flex items-center gap-2">
              <Loader2 size={12} className="animate-spin text-violet-400" />
              <span className="text-xs text-violet-300 font-semibold">
                Optimizing system prompt via GEPA...
              </span>
            </div>
          </motion.div>
        )}
      </AnimatePresence>

      {/* Messages */}
      <div className="flex-1 overflow-y-auto px-4 py-4">
        {messages.length === 0 ? (
          <EmptyState onSelect={(q) => { setInput(q); inputRef.current?.focus() }} />
        ) : (
          <div className="flex flex-col gap-6 max-w-3xl mx-auto">
            {messages.map((msg) => (
              <MessageCard
                key={msg.id}
                msg={msg}
                onFeedback={handleFeedback}
                onRetry={(q, prevSql) => void execute(q, prevSql)}
              />
            ))}
            <div ref={bottomRef} />
          </div>
        )}
      </div>

      {/* Input area */}
      <div
        className="shrink-0 border-t border-white/[0.06] px-4 py-3"
        style={{ background: 'var(--bg-secondary)' }}
      >
        {/* Suggested chips */}
        {messages.length > 0 && (
          <div className="flex gap-1.5 flex-wrap mb-2.5">
            {suggestions.slice(0, 3).map((q) => (
              <button
                key={q}
                onClick={() => { setInput(q); inputRef.current?.focus() }}
                className="text-[10px] px-2.5 py-1 rounded-full border border-white/[0.06] text-gray-500 hover:text-gray-300 hover:border-violet-500/30 transition-all"
              >
                {q}
              </button>
            ))}
          </div>
        )}

        <div className="flex items-end gap-2">
          <div className="flex-1 relative">
            <textarea
              ref={inputRef}
              value={input}
              onChange={(e) => setInput(e.target.value)}
              onKeyDown={handleKeyDown}
              placeholder={isCustomDb ? 'Ask anything about your data…' : 'Ask about products, orders, sellers...'}
              disabled={isExecuting}
              rows={1}
              className="w-full px-3 py-2.5 pr-10 text-sm text-white rounded-xl border border-white/[0.06] bg-white/[0.03] placeholder-gray-600 resize-none focus:outline-none focus:border-violet-500/40 focus:bg-white/[0.05] transition-all disabled:opacity-50"
              style={{ minHeight: 40, maxHeight: 120, overflowY: 'auto' }}
            />
          </div>
          <div className="flex flex-col gap-1.5 shrink-0">
            <button
              onClick={handleSend}
              disabled={!input.trim() || isExecuting}
              className="w-9 h-9 rounded-xl bg-violet-600 hover:bg-violet-500 disabled:opacity-40 disabled:cursor-not-allowed transition-all flex items-center justify-center"
            >
              {isExecuting ? (
                <Loader2 size={14} className="animate-spin text-white" />
              ) : (
                <Send size={14} className="text-white" />
              )}
            </button>
            {messages.length > 0 && (
              <button
                onClick={clearMessages}
                disabled={isExecuting}
                className="w-9 h-9 rounded-xl border border-white/[0.06] hover:bg-white/5 disabled:opacity-40 transition-all flex items-center justify-center text-gray-600 hover:text-gray-400"
                title="Clear chat"
              >
                <Trash2 size={12} />
              </button>
            )}
          </div>
        </div>
        <p className="text-[9px] text-gray-700 mt-1.5 text-center">
          Enter to send · Shift+Enter for newline · Agent uses LinUCB + GEPA
        </p>
      </div>
    </div>
  )
}
