import { useRef, useEffect } from 'react';
import { useNavigate } from 'react-router-dom';

function renderInlineMarkdown(text, keyPrefix) {
  const out = [];
  const re = /(\*\*[^*]+?\*\*|__[^_]+?__|`[^`]+?`|\[[^\]]+?\]\([^)]+?\))/g;
  let last = 0;
  let match;
  let idx = 0;

  while ((match = re.exec(text)) !== null) {
    if (match.index > last) {
      out.push(text.slice(last, match.index));
    }

    const token = match[0];
    if (token.startsWith('**') || token.startsWith('__')) {
      out.push(<strong key={`${keyPrefix}-b-${idx++}`}>{token.slice(2, -2)}</strong>);
    } else if (token.startsWith('`')) {
      out.push(<code key={`${keyPrefix}-c-${idx++}`}>{token.slice(1, -1)}</code>);
    } else {
      const close = token.indexOf(']');
      const label = token.slice(1, close);
      const href = token.slice(close + 2, -1);
      out.push(
        <a key={`${keyPrefix}-a-${idx++}`} href={href} target="_blank" rel="noreferrer">
          {label}
        </a>,
      );
    }
    last = match.index + token.length;
  }

  if (last < text.length) {
    out.push(text.slice(last));
  }
  return out;
}

function MarkdownText({ text }) {
  const source = (text || '').replace(/\r\n/g, '\n');
  const lines = source.split('\n');
  const blocks = [];
  let i = 0;
  let blockKey = 0;

  while (i < lines.length) {
    const line = lines[i];
    if (!line.trim()) {
      i += 1;
      continue;
    }

    if (line.startsWith('```')) {
      const codeLines = [];
      i += 1;
      while (i < lines.length && !lines[i].startsWith('```')) {
        codeLines.push(lines[i]);
        i += 1;
      }
      if (i < lines.length) i += 1;
      blocks.push(
        <pre key={`md-${blockKey++}`} className="bubble-code">
          <code>{codeLines.join('\n')}</code>
        </pre>,
      );
      continue;
    }

    const heading = line.match(/^(#{1,6})\s+(.*)$/);
    if (heading) {
      const level = Math.min(heading[1].length, 3);
      const Tag = `h${level}`;
      blocks.push(
        <Tag key={`md-${blockKey++}`} className={`bubble-heading bubble-heading-${level}`}>
          {renderInlineMarkdown(heading[2], `h-${blockKey}`)}
        </Tag>,
      );
      i += 1;
      continue;
    }

    if (/^\s*[-*+]\s+/.test(line)) {
      const items = [];
      while (i < lines.length && /^\s*[-*+]\s+/.test(lines[i])) {
        items.push(lines[i].replace(/^\s*[-*+]\s+/, ''));
        i += 1;
      }
      blocks.push(
        <ul key={`md-${blockKey++}`} className="bubble-list">
          {items.map((item, idx) => (
            <li key={`md-${blockKey}-${idx}`}>{renderInlineMarkdown(item, `ul-${blockKey}-${idx}`)}</li>
          ))}
        </ul>,
      );
      continue;
    }

    if (/^\s*\d+\.\s+/.test(line)) {
      const items = [];
      while (i < lines.length && /^\s*\d+\.\s+/.test(lines[i])) {
        items.push(lines[i].replace(/^\s*\d+\.\s+/, ''));
        i += 1;
      }
      blocks.push(
        <ol key={`md-${blockKey++}`} className="bubble-list bubble-list-ordered">
          {items.map((item, idx) => (
            <li key={`md-${blockKey}-${idx}`}>{renderInlineMarkdown(item, `ol-${blockKey}-${idx}`)}</li>
          ))}
        </ol>,
      );
      continue;
    }

    const para = [];
    while (
      i < lines.length &&
      lines[i].trim() &&
      !lines[i].startsWith('```') &&
      !/^(#{1,6})\s+/.test(lines[i]) &&
      !/^\s*[-*+]\s+/.test(lines[i]) &&
      !/^\s*\d+\.\s+/.test(lines[i])
    ) {
      para.push(lines[i]);
      i += 1;
    }

    blocks.push(
      <p key={`md-${blockKey++}`} className="bubble-paragraph">
        {renderInlineMarkdown(para.join(' '), `p-${blockKey}`)}
      </p>,
    );
  }

  return <div className="bubble-markdown">{blocks}</div>;
}

function AudioButton({ base64, mimeType = 'audio/mp3', label = '🔊' }) {
  const src = base64
    ? `data:${mimeType};base64,${base64}`
    : null;

  if (!src) return null;
  return (
    <audio
      className="audio-btn"
      controls
      src={src}
      title={label}
      preload="none"
    />
  );
}

const TOOL_ICON = {
  terminal:     '💻',
  web_search:   '🔍',
  web_extract:  '📄',
  browser:      '🌐',
  read_file:    '📂',
  write_file:   '✏️',
  execute_code: '⚡',
  delegate_task:'🤖',
};

function ToolCallsList({ toolCalls }) {
  if (!toolCalls || toolCalls.length === 0) return null;
  return (
    <details className="tool-calls">
      <summary className="tool-calls-summary">
        🔧 Hermes 使用了 {toolCalls.length} 个工具
      </summary>
      <ul className="tool-calls-list">
        {toolCalls.map((t, i) => (
          <li key={i} className="tool-calls-item">
            <span className="tool-calls-icon">{TOOL_ICON[t.tool] || '🔧'}</span>
            <span className="tool-calls-name">{t.tool}</span>
            {t.preview && (
              <code className="tool-calls-preview">{t.preview}</code>
            )}
          </li>
        ))}
      </ul>
    </details>
  );
}

function Bubble({ role, text, audioBase64, audioMime, toolCalls }) {
  const isUser = role === 'user';
  return (
    <div className={`bubble ${isUser ? 'bubble-user' : 'bubble-bot'}`}>
      <div className="bubble-label">{isUser ? '你' : 'JBOT'}</div>
      {!isUser && <ToolCallsList toolCalls={toolCalls} />}
      <div className="bubble-text"><MarkdownText text={text} /></div>
      {audioBase64 && (
        <AudioButton base64={audioBase64} mimeType={audioMime || 'audio/mp3'} />
      )}
    </div>
  );
}

export default function ChatPanel({ messages, voiceStatus }) {
  const bottomRef = useRef(null);
  const navigate  = useNavigate();

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

  return (
    <section className="chat-panel">
      <div className="chat-header">
        <span className="chat-title">对话</span>
        <button className="history-link" onClick={() => navigate('/history')}>
          历史记录 →
        </button>
      </div>

      {voiceStatus && (
        <div className={`voice-status voice-status-${voiceStatus.type}`}>
          {voiceStatus.text}
        </div>
      )}

      <div className="chat-messages">
        {messages.length === 0 ? (
          <p className="chat-empty">按住 Space 开始说话…</p>
        ) : (
          messages.map((m) => (
            <Bubble
              key={m.id}
              role={m.role}
              text={m.text}
              audioBase64={m.audioBase64}
              audioMime={m.audioMime}
              toolCalls={m.toolCalls}
            />
          ))
        )}
        <div ref={bottomRef} />
      </div>
    </section>
  );
}
