import { useState, useRef, useEffect, useCallback } from 'react'
import { useI18n } from '../i18n'

const RANKS = {
  commandant: { label: 'Commandant', short: 'CDT', color: '#FFD740' },
  general:    { label: 'General',    short: 'GEN', color: '#FF9100' },
  colonel:    { label: 'Colonel',    short: 'COL', color: '#FF6D00' },
  lieutenant: { label: 'Lieutenant', short: 'LT',  color: '#448AFF' },
  soldat:     { label: 'Soldat',     short: 'SDT', color: '#00E676' },
}

function getRank(role) {
  if (role === 'user') return RANKS.commandant
  if (role === 'system') return null
  return RANKS.general
}

function RankIcon({ rank }) {
  if (rank === RANKS.commandant) {
    return (
      <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke={rank.color} strokeWidth="2">
        <polygon points="12,2 15.09,8.26 22,9.27 17,14.14 18.18,21.02 12,17.77 5.82,21.02 7,14.14 2,9.27 8.91,8.26"/>
      </svg>
    )
  }
  return (
    <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke={rank.color} strokeWidth="2">
      <path d="M12 2L2 7l10 5 10-5-10-5z"/><path d="M2 17l10 5 10-5"/><path d="M2 12l10 5 10-5"/>
    </svg>
  )
}

function renderContent(text) {
  const parts = []
  const codeBlockRegex = /(```[\s\S]*?```)/g
  let match
  let lastIndex = 0
  while ((match = codeBlockRegex.exec(text)) !== null) {
    if (match.index > lastIndex) {
      parts.push({ type: 'text', content: text.slice(lastIndex, match.index) })
    }
    const full = match[1]
    const firstNewline = full.indexOf('\n')
    const lang = firstNewline > -1 ? full.slice(3, firstNewline).trim() : ''
    const code = firstNewline > -1 ? full.slice(firstNewline + 1, -3) : full.slice(3, -3)
    parts.push({ type: 'code', lang, content: code })
    lastIndex = match.index + full.length
  }
  if (lastIndex < text.length) {
    parts.push({ type: 'text', content: text.slice(lastIndex) })
  }
  return parts
}

function formatText(text) {
  return text
    .replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;')
    .replace(/\*\*(.+?)\*\*/g, '<strong>$1</strong>')
    .replace(/`([^`]+)`/g, '<code class="inline-code">$1</code>')
    .replace(/^### (.+)$/gm, '<h4 class="msg-h4">$1</h4>')
    .replace(/^## (.+)$/gm, '<h3 class="msg-h3">$1</h3>')
    .replace(/^# (.+)$/gm, '<h2 class="msg-h2">$1</h2>')
    .replace(/^\s*[-*] (.+)$/gm, '<div class="msg-bullet">• $1</div>')
    .replace(/^\s*(\d+)[.)] (.+)$/gm, '<div class="msg-step"><span class="msg-step-num">$1</span> $2</div>')
}

function ThinkingBlock({ content, done }) {
  return (
    <div className={`feed-thinking-block ${done ? 'done' : 'active'}`}>
      <div className="feed-thinking-header">
        <svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2">
          <circle cx="12" cy="12" r="10"/><path d="M12 6v6l4 2"/>
        </svg>
        <span>Reflexion</span>
        {!done && <span className="feed-thinking-dots"><span/><span/><span/></span>}
      </div>
      <div className="feed-thinking-content">{content}</div>
    </div>
  )
}

const TOOL_ICONS = {
  terminal: '⌨',
  crush_run: '⚡',
  read_file: '📄',
  list_files: '📁',
  search_files: '🔍',
  grep_content: '🔎',
  get_config: '⚙',
  set_provider: '🔑',
  manage_ssh: '🌐',
  web_fetch: '🌐',
}

const TOOL_LABELS = {
  terminal: 'Terminal',
  crush_run: 'Crush Agent',
  read_file: 'Read File',
  list_files: 'List Files',
  search_files: 'Search Files',
  grep_content: 'Grep',
  get_config: 'Config',
  set_provider: 'Set Provider',
  manage_ssh: 'SSH',
  web_fetch: 'Web Fetch',
}

function ToolCallBlock({ call, result }) {
  const icon = TOOL_ICONS[call.name] || '🔧'
  const label = TOOL_LABELS[call.name] || call.name
  const isErr = result && result.is_error

  let argsPreview = ''
  try {
    const args = typeof call.args === 'string' ? JSON.parse(call.args) : call.args
    if (args.command) argsPreview = args.command
    else if (args.task) argsPreview = args.task
    else if (args.path) argsPreview = args.path
    else if (args.pattern) argsPreview = args.pattern
    else if (args.url) argsPreview = args.url
    else if (args.action) argsPreview = args.action
    else argsPreview = JSON.stringify(args).slice(0, 80)
  } catch {
    argsPreview = String(call.args).slice(0, 80)
  }

  const truncatedResult = result ? (result.content || '').slice(0, 2000) : null

  return (
    <div className={`studio-tool-block ${isErr ? 'error' : ''} ${result ? 'done' : 'running'}`}>
      <div className="studio-tool-header">
        <span className="studio-tool-icon">{icon}</span>
        <span className="studio-tool-name">{label}</span>
        {!result && <span className="studio-tool-spinner"><span/><span/><span/></span>}
        {result && <span className={`studio-tool-status ${isErr ? 'error' : 'ok'}`}>{isErr ? '✗' : '✓'}</span>}
      </div>
      <div className="studio-tool-args" title={argsPreview}>{argsPreview}</div>
      {truncatedResult && (
        <div className="studio-tool-result">
          <pre>{truncatedResult}</pre>
        </div>
      )}
    </div>
  )
}

function FeedItem({ msg }) {
  const isUser = msg.role === 'user'
  const isSystem = msg.role === 'system'
  const rank = getRank(msg.role)

  const timeStr = msg.time ? new Date(msg.time).toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' }) : ''

  let parsedToolCalls = null
  let parsedToolResults = null
  let displayContent = msg.content
  try {
    const parsed = JSON.parse(msg.content)
    if (parsed && Array.isArray(parsed.tool_calls)) {
      parsedToolCalls = parsed.tool_calls
      parsedToolResults = parsed.tool_results || null
      displayContent = parsed.content || ''
    }
  } catch {}

  if (isSystem) {
    return (
      <div className="feed-item system">
        <div className="feed-system-badge" />
        <div className="feed-system-text">{msg.content}</div>
        {timeStr && <span className="feed-time">{timeStr}</span>}
      </div>
    )
  }

  const cleanContent = displayContent.replace(/<think[^>]*>[\s\S]*?<\/think>/gi, '')

  return (
    <div className={`feed-item ${msg.role}`}>
      <div className={`feed-avatar ${isUser ? 'user-rank' : 'ai-rank'}`}>
        <RankIcon rank={rank} />
      </div>
      <div className="feed-body">
        <div className="feed-header">
          <span className="feed-rank-badge" style={{ color: rank.color, borderColor: rank.color }}>
            {rank.short}
          </span>
          <span className="feed-role">{rank.label}</span>
          {timeStr && <span className="feed-time">{timeStr}</span>}
        </div>
        {msg.thinking && <ThinkingBlock content={msg.thinking} done />}
        {parsedToolCalls && parsedToolCalls.map((tc, i) => {
          const resultData = parsedToolResults
            ? parsedToolResults.find(r => r.tool_call_id === tc.tool_call_id)
            : null
          const result = resultData
            ? { content: resultData.result, is_error: resultData.is_error }
            : null
          return <ToolCallBlock key={tc.tool_call_id || i} call={tc} result={result} />
        })}
        {cleanContent && (
          <div className="feed-content">
            {renderContent(cleanContent).map((part, i) =>
              part.type === 'code' ? (
                <div key={i} className="studio-code-block">
                  {part.lang && <div className="studio-code-lang">{part.lang}</div>}
                  <pre><code>{part.content}</code></pre>
                </div>
              ) : (
                <span key={i} dangerouslySetInnerHTML={{ __html: formatText(part.content) }} />
              )
            )}
          </div>
        )}
      </div>
    </div>
  )
}

function StreamingItem({ content, thinking, toolCalls }) {
  const rank = RANKS.general
  const cleanContent = content.replace(/<think[^>]*>[\s\S]*?<\/think>/gi, '')
  const hasToolCalls = toolCalls && toolCalls.length > 0

  return (
    <div className="feed-item assistant">
      <div className="feed-avatar ai-rank">
        <RankIcon rank={rank} />
      </div>
      <div className="feed-body">
        <div className="feed-header">
          <span className="feed-rank-badge" style={{ color: rank.color, borderColor: rank.color }}>
            {rank.short}
          </span>
          <span className="feed-role">{rank.label}</span>
        </div>
        {thinking && <ThinkingBlock content={thinking} done={false} />}
        {hasToolCalls && toolCalls.map((tc, i) => (
          <ToolCallBlock key={tc.call?.tool_call_id || i} call={tc.call} result={tc.result} />
        ))}
        {!thinking && !cleanContent && !hasToolCalls && (
          <div className="feed-content">
            <div className="studio-thinking"><span /><span /><span /></div>
          </div>
        )}
        {cleanContent && (
          <div className="feed-content">
            {renderContent(cleanContent).map((part, i) =>
              part.type === 'code' ? (
                <div key={i} className="studio-code-block">
                  {part.lang && <div className="studio-code-lang">{part.lang}</div>}
                  <pre><code>{part.content}</code></pre>
                </div>
              ) : (
                <span key={i} dangerouslySetInnerHTML={{ __html: formatText(part.content) }} />
              )
            )}
            <span className="studio-cursor" />
          </div>
        )}
      </div>
    </div>
  )
}

export default function Studio({ api }) {
  const { t } = useI18n()
  const [messages, setMessages] = useState([])
  const [input, setInput] = useState('')
  const [loading, setLoading] = useState(false)
  const [streaming, setStreaming] = useState('')
  const [streamThinking, setStreamThinking] = useState('')
  const [streamToolCalls, setStreamToolCalls] = useState([])
  const [loaded, setLoaded] = useState(false)
  const messagesEnd = useRef(null)
  const textareaRef = useRef(null)
  const abortRef = useRef(null)

  useEffect(() => {
    api.getChatHistory().then(data => {
      if (data.messages && data.messages.length > 0) {
        setMessages(data.messages)
      } else {
        setMessages([
          { id: 'welcome', role: 'system', content: t('studio.welcomeNew'), time: new Date().toISOString() },
        ])
      }
      setLoaded(true)
    }).catch(() => {
      setMessages([
        { id: 'welcome', role: 'system', content: t('studio.welcomeNew'), time: new Date().toISOString() },
      ])
      setLoaded(true)
    })
  }, [])

  useEffect(() => {
    messagesEnd.current?.scrollIntoView({ behavior: 'smooth' })
  }, [messages, streaming, streamThinking, streamToolCalls])

  useEffect(() => {
    if (textareaRef.current) {
      textareaRef.current.style.height = 'auto'
      textareaRef.current.style.height = Math.min(textareaRef.current.scrollHeight, 200) + 'px'
    }
  }, [input])

  const handleClear = useCallback(async () => {
    try {
      await api.clearChat()
      setMessages([
        { id: 'clear-' + Date.now(), role: 'system', content: t('studio.cleared'), time: new Date().toISOString() },
      ])
    } catch {}
  }, [api, t])

  const handleSend = useCallback(async () => {
    if (!input.trim() || loading) return
    const text = input.trim()
    setInput('')

    if (text === '/clear') {
      handleClear()
      return
    }

    const userMsg = { id: Date.now().toString(), role: 'user', content: text, time: new Date().toISOString() }
    setMessages(prev => [...prev, userMsg])
    setLoading(true)
    setStreaming('')
    setStreamThinking('')
    setStreamToolCalls([])

    const controller = new AbortController()
    abortRef.current = controller

    try {
      let accumulated = ''
      let thinking = ''
      let toolCalls = []

      await api.sendChat(text, true, (partial, event) => {
        if (event && (event.thinking_start || event.thinking_end || event.thinking !== undefined)) {
          if (event.thinking !== undefined) {
            thinking += event.thinking
            setStreamThinking(thinking)
          }
          return
        }
        if (event && event.tool_call) {
          toolCalls = [...toolCalls, { call: event.tool_call, result: null }]
          setStreamToolCalls([...toolCalls])
          return
        }
        if (event && event.tool_result) {
          const idx = toolCalls.findIndex(tc => tc.call && tc.call.tool_call_id === event.tool_result.tool_call_id)
          if (idx >= 0) {
            toolCalls[idx] = { ...toolCalls[idx], result: event.tool_result }
            setStreamToolCalls([...toolCalls])
          }
          return
        }
        accumulated = partial
        setStreaming(partial)
      }, controller.signal)

      const finalContent = accumulated || t('studio.noResponse')
      const aiMsg = {
        id: (Date.now() + 1).toString(),
        role: 'assistant',
        content: finalContent,
        time: new Date().toISOString(),
      }
      if (thinking) aiMsg.thinking = thinking
      if (toolCalls.length > 0) {
        aiMsg.content = JSON.stringify({
          content: finalContent,
          tool_calls: toolCalls.map(tc => tc.call),
        })
      }
      setMessages(prev => [...prev, aiMsg])
    } catch (err) {
      if (err.name === 'AbortError') {
        if (streaming) {
          setMessages(prev => [...prev, {
            id: (Date.now() + 1).toString(),
            role: 'system',
            content: t('studio.cancelled'),
            time: new Date().toISOString(),
          }])
        }
      } else {
        setMessages(prev => [...prev, {
          id: (Date.now() + 1).toString(),
          role: 'system',
          content: `${t('studio.error')}: ${err.message}`,
          time: new Date().toISOString(),
        }])
      }
    } finally {
      setLoading(false)
      setStreaming('')
      setStreamThinking('')
      setStreamToolCalls([])
      abortRef.current = null
    }
  }, [input, loading, api, t, handleClear, streaming])

  const handleStop = useCallback(() => {
    if (abortRef.current) {
      abortRef.current.abort()
    }
  }, [])

  const handleKeyDown = (e) => {
    if (e.key === 'Enter' && !e.shiftKey) {
      e.preventDefault()
      handleSend()
    }
  }

  if (!loaded) {
    return (
      <div className="studio-feed-layout">
        <div className="studio-feed">
          <div className="feed-loading">
            <div className="studio-thinking"><span /><span /><span /></div>
          </div>
        </div>
      </div>
    )
  }

  return (
    <div className="studio-feed-layout">
      <div className="studio-feed">
        {messages.map(msg => (
          <FeedItem key={msg.id} msg={msg} />
        ))}
        {(streaming || streamThinking || loading || streamToolCalls.length > 0) && (
          <StreamingItem content={streaming} thinking={streamThinking} toolCalls={streamToolCalls} />
        )}
        <div ref={messagesEnd} />
      </div>

      <div className="studio-input-area">
        <div className="studio-input-row">
          <textarea
            ref={textareaRef}
            value={input}
            onChange={e => setInput(e.target.value)}
            onKeyDown={handleKeyDown}
            placeholder={t('studio.placeholderNew')}
            disabled={loading}
            rows={1}
          />
          <button
            className="studio-send-btn"
            onClick={handleSend}
            disabled={loading || !input.trim()}
          >
            <svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2">
              <line x1="22" y1="2" x2="11" y2="13"/><polygon points="22 2 15 22 11 13 2 9 22 2"/>
            </svg>
          </button>
          {loading && (
            <button className="studio-stop-btn" onClick={handleStop} title={t('studio.stop')}>
              <svg width="16" height="16" viewBox="0 0 24 24" fill="currentColor">
                <rect x="4" y="4" width="16" height="16" rx="2"/>
              </svg>
            </button>
          )}
        </div>
        <div className="studio-input-hint">
          {t('studio.inputHint')} &middot; /clear
        </div>
      </div>
    </div>
  )
}
