import React, { useEffect, useRef, useState } from 'react'

import { describeChange, type IssueChange } from '@commitea/core'

import { useChat } from '../../lib/use-chat.js'
import { Button, Icon, IconButton } from '../ui/index.js'

/**
 * Reginald's panel — chat is the write-path (decisions.md D1). Wired to the
 * model bridge via `useChat`: a configured model drives a real agent turn
 * (query_project + prose, propose_change for edits); otherwise it echoes the
 * scripted fixture reply. Proposed changes are approved inline here — the write
 * runs through `onApplyChange`, the same guarded handler the Issue screen uses.
 */
export interface ChatPanelProps {
  onOpenDirectives?: () => void
  offline?: boolean
  onApplyChange?: (change: IssueChange) => Promise<{ ok: boolean }>
}

export function ChatPanel({ onOpenDirectives, offline, onApplyChange }: ChatPanelProps) {
  const { msgs, thinking, live, model, steps, proposals, send: sendChat, approve, dismiss } = useChat(onApplyChange)
  // shorten "google/gemma-4-26b-a4b-qat" → "gemma-4-26b" for the header chip
  const modelLabel = model ? (model.split('/').pop() ?? model).replace(/-(qat|instruct|it|gguf)$/i, '') : 'gemma-4'
  const [text, setText] = useState('')
  const scrollRef = useRef<HTMLDivElement>(null)

  useEffect(() => {
    const el = scrollRef.current
    if (el) el.scrollTop = el.scrollHeight
  }, [msgs, thinking])

  const send = () => {
    const t = text.trim()
    if (!t) return
    setText('')
    sendChat(t)
  }

  return (
    <aside
      style={{
        width: 330,
        flexShrink: 0,
        display: 'flex',
        flexDirection: 'column',
        background: 'var(--surface-card)',
        borderLeft: '1px solid var(--line-1)',
        minHeight: 0,
      }}
    >
      <header
        style={{
          display: 'flex',
          alignItems: 'center',
          gap: 8,
          padding: '14px 16px',
          borderBottom: '1px solid var(--line-1)',
          flexShrink: 0,
        }}
      >
        <Icon name="sparkles" size={16} style={{ color: offline ? 'var(--ink-3)' : 'var(--jade)' }} />
        <span style={{ font: 'var(--text-body-strong)', color: 'var(--ink-1)' }}>Reginald</span>
        <span style={{ font: '400 11px var(--font-mono)', color: 'var(--ink-3)', marginLeft: 'auto' }}>
          {offline ? 'offline · queueing' : live ? `${modelLabel} · local` : 'demo · scripted'}
        </span>
        <IconButton icon="history" label="Directive log" size="sm" onClick={onOpenDirectives} />
      </header>

      <div
        ref={scrollRef}
        style={{ flex: 1, overflowY: 'auto', padding: 16, display: 'flex', flexDirection: 'column', gap: 12, minHeight: 0 }}
      >
        {msgs.map((m, i) =>
          m.from === 'agent' ? (
            <div key={i} style={{ font: 'var(--text-agent)', color: 'var(--ink-1)', lineHeight: 1.55 }}>
              {m.text}
            </div>
          ) : (
            <div
              key={i}
              style={{
                alignSelf: 'flex-end',
                maxWidth: '85%',
                background: 'var(--paper-2)',
                borderRadius: '10px 10px 2px 10px',
                padding: '8px 12px',
                font: 'var(--text-small)',
                color: 'var(--ink-1)',
              }}
            >
              {m.text}
            </div>
          ),
        )}
        {offline ? (
          <div style={{ font: 'var(--text-agent)', color: 'var(--ink-3)' }}>
            The model is away from its desk. Reads still work; writes will wait their turn.
          </div>
        ) : null}
        {thinking ? <div style={{ font: 'var(--text-agent)', color: 'var(--ink-3)' }}>considering…</div> : null}
        {!thinking && steps.length ? (
          <div style={{ font: 'var(--text-caption)', color: 'var(--ink-3)', display: 'flex', alignItems: 'center', gap: 5 }}>
            <Icon name="eye" size={11} /> consulted {Array.from(new Set(steps.map((s) => s.replace('query_project', 'the project').replace('propose_change', 'the labels').replace('record_directive', 'the directive ledger')))).join(', ')}
          </div>
        ) : null}
        {proposals.map((p) => (
          <div
            key={`${p.change.issue}:${p.change.kind}`}
            style={{
              border: '1px solid var(--line-2)',
              borderRadius: 'var(--radius-2)',
              background: 'var(--paper-0)',
              padding: '10px 12px',
              display: 'flex',
              flexDirection: 'column',
              gap: 8,
            }}
          >
            <div style={{ font: 'var(--text-caption)', color: 'var(--ink-3)', textTransform: 'uppercase', letterSpacing: 'var(--letter-spacing-wide)' }}>
              Proposed · #{p.change.issue}
            </div>
            <div style={{ font: '500 13px var(--font-mono)', color: 'var(--ink-1)' }}>{describeChange(p.plan)}</div>
            <div style={{ display: 'flex', gap: 8 }}>
              <Button size="sm" onClick={() => approve(p)} disabled={offline}>
                Approve
              </Button>
              <Button size="sm" variant="ghost" onClick={() => dismiss(p)}>
                Dismiss
              </Button>
            </div>
          </div>
        ))}
      </div>

      <div style={{ padding: 14, borderTop: '1px solid var(--line-1)', flexShrink: 0 }}>
        <div
          style={{
            display: 'flex',
            alignItems: 'flex-end',
            gap: 8,
            background: 'var(--paper-0)',
            border: '1px solid var(--line-2)',
            borderRadius: 'var(--radius-2)',
            padding: '8px 8px 8px 12px',
          }}
        >
          <textarea
            value={text}
            onChange={(e) => setText(e.target.value)}
            onKeyDown={(e) => {
              if (e.key === 'Enter' && !e.shiftKey) {
                e.preventDefault()
                send()
              }
            }}
            placeholder={offline ? 'Writes wait for the connection…' : 'Tell me what to do…'}
            disabled={offline}
            rows={1}
            style={{
              flex: 1,
              resize: 'none',
              border: 'none',
              outline: 'none',
              background: 'transparent',
              font: 'var(--text-body)',
              color: 'var(--ink-1)',
              lineHeight: 1.45,
              maxHeight: 96,
            }}
          />
          <button
            type="button"
            onClick={send}
            aria-label="Send"
            disabled={offline}
            style={{
              width: 30,
              height: 30,
              borderRadius: 'var(--radius-2)',
              border: 'none',
              cursor: offline ? 'not-allowed' : 'pointer',
              background: offline ? 'var(--paper-3)' : 'var(--accent)',
              color: offline ? 'var(--ink-3)' : 'var(--ink-inverse)',
              display: 'inline-flex',
              alignItems: 'center',
              justifyContent: 'center',
              flexShrink: 0,
            }}
          >
            <Icon name="send" size={14} />
          </button>
        </div>
        <p style={{ font: 'var(--text-caption)', color: 'var(--ink-3)', margin: '8px 2px 0' }}>
          Chat is the write-path. Destructive changes are proposed, never assumed.
        </p>
      </div>
    </aside>
  )
}
