import { useState, useRef, useEffect, useCallback } from 'react';
import styles from './AgentChat.module.css';
import netzerpng from '../assets/guenther_icon.png';

// ============================================================
// Choices Parser
// Extrahiert [CHOICES]...[/CHOICES] aus Agent-Antwort
// ============================================================
function parseChoices(text: string): { before: string; choices: string[]; hasChoices: boolean } {
  const match = text.match(/\[CHOICES\]([\s\S]*?)\[\/CHOICES\]/);
  if (!match) return { before: text, choices: [], hasChoices: false };
  const before = text.slice(0, match.index).trimEnd();
  const choices = match[1]
    .split('\n')
    .map((l) => l.trim())
    .filter((l) => l.length > 0);
  return { before, choices, hasChoices: true };
}

// ============================================================
// ChoiceSelector Komponente
// ============================================================
function ChoiceSelector({
  choices,
  onConfirm,
  disabled,
}: {
  choices: string[];
  onConfirm: (selected: string[]) => void;
  disabled: boolean;
}) {
  const [selected, setSelected] = useState<Set<string>>(new Set());

  function toggle(choice: string) {
    setSelected((prev) => {
      const next = new Set(prev);
      next.has(choice) ? next.delete(choice) : next.add(choice);
      return next;
    });
  }

  function handleConfirm() {
    if (selected.size === 0) return;
    onConfirm([...selected]);
  }

  function handleAll() {
    onConfirm(choices);
  }

  return (
    <div className={styles.choiceSelector}>
      <div className={styles.choiceList}>
        {choices.map((c) => (
          <button
            key={c}
            className={`${styles.choiceItem} ${selected.has(c) ? styles.choiceItemSelected : ''}`}
            onClick={() => toggle(c)}
            disabled={disabled}
          >
            <span className={styles.choiceCheckbox}>
              {selected.has(c) ? '✓' : ''}
            </span>
            {c}
          </button>
        ))}
      </div>
      <div className={styles.choiceActions}>
        <button
          className={styles.choiceConfirm}
          onClick={handleConfirm}
          disabled={disabled || selected.size === 0}
        >
          {selected.size > 0 ? `${selected.size} Spiel${selected.size > 1 ? 'e' : ''} analysieren` : 'Auswahl treffen'}
        </button>
        <button
          className={styles.choiceAll}
          onClick={handleAll}
          disabled={disabled}
        >
          Alle
        </button>
      </div>
    </div>
  );
}

// ============================================================
// Mini Markdown Renderer
// Unterstützt: ## Header, **bold**, *italic*, --- Trennlinie, - Listen
// ============================================================
function renderMarkdown(text: string): React.ReactNode[] {
  const lines = text.split('\n');
  const result: React.ReactNode[] = [];
  let listBuffer: string[] = [];
  let keyCounter = 0;
  const k = () => keyCounter++;

  function flushList() {
    if (listBuffer.length === 0) return;
    result.push(
      <ul key={k()} style={{ paddingLeft: '1.2em', margin: '4px 0', listStyleType: 'disc' }}>
        {listBuffer.map((item, i) => (
          <li key={i} style={{ marginBottom: '2px' }}>{inlineFormat(item)}</li>
        ))}
      </ul>
    );
    listBuffer = [];
  }

  function inlineFormat(line: string): React.ReactNode {
    // **bold** und *italic* inline parsen
    const parts: React.ReactNode[] = [];
    const regex = /(\*\*(.+?)\*\*|\*(.+?)\*)/g;
    let last = 0;
    let match;
    while ((match = regex.exec(line)) !== null) {
      if (match.index > last) parts.push(line.slice(last, match.index));
      if (match[2]) parts.push(<strong key={match.index}>{match[2]}</strong>);
      else if (match[3]) parts.push(<em key={match.index}>{match[3]}</em>);
      last = match.index + match[0].length;
    }
    if (last < line.length) parts.push(line.slice(last));
    return parts.length === 1 ? parts[0] : parts;
  }

  for (const line of lines) {
    // Trennlinie ---
    if (/^---+$/.test(line.trim())) {
      flushList();
      result.push(
        <hr key={k()} style={{ border: 'none', borderTop: '1px solid rgba(255,255,255,0.1)', margin: '8px 0' }} />
      );
      continue;
    }
    // ## H2
    if (line.startsWith('## ')) {
      flushList();
      result.push(
        <div key={k()} style={{ fontFamily: "'Plus Jakarta Sans', sans-serif", fontWeight: 700, fontSize: '13px', color: 'var(--primary)', marginTop: '10px', marginBottom: '3px', letterSpacing: '-0.1px' }}>
          {inlineFormat(line.slice(3))}
        </div>
      );
      continue;
    }
    // # H1
    if (line.startsWith('# ')) {
      flushList();
      result.push(
        <div key={k()} style={{ fontFamily: "'Plus Jakarta Sans', sans-serif", fontWeight: 800, fontSize: '14px', color: 'var(--gold)', marginTop: '8px', marginBottom: '4px' }}>
          {inlineFormat(line.slice(2))}
        </div>
      );
      continue;
    }
    // Listenpunkt - oder *
    if (/^[-*]\s/.test(line)) {
      listBuffer.push(line.slice(2));
      continue;
    }
    // Leere Zeile
    if (line.trim() === '') {
      flushList();
      result.push(<div key={k()} style={{ height: '6px' }} />);
      continue;
    }
    // Normaler Absatz
    flushList();
    result.push(
      <div key={k()} style={{ marginBottom: '2px' }}>{inlineFormat(line)}</div>
    );
  }
  flushList();
  return result;
}

// ============================================================
// Types
// ============================================================
interface Message {
  id: string;
  role: 'user' | 'assistant';
  content: string;
  timestamp: Date;
}

// ============================================================
// Quick-Action Chips
// ============================================================
const QUICK_ACTIONS = [
  { label: '🎯 Tipp-Empfehlung', prompt: 'Gib mir eine Tipp-Empfehlung für die nächsten Spiele der WM 2026!' },
  { label: '📊 Head-to-Head', prompt: 'Zeig mir ein interessantes Head-to-Head zwischen zwei WM-Teams!' },
  { label: '⚡ Fun Fact', prompt: 'Erzähl mir einen kuriosen oder legendären Fun Fact aus der WM-Geschichte!' },
  { label: '🏆 WM-Rekorde', prompt: 'Was sind die spektakulärsten Rekorde aller WM-Turniere?' },
];

// ============================================================
// API: Streaming Chat-Anfrage
// ============================================================
async function sendMessage(
  messages: Array<{ role: 'user' | 'assistant'; content: string }>,
  onChunk: (text: string) => void,
  onDone: () => void,
  onError: (err: string) => void
) {
  try {
    const res = await fetch('/api/agent/chat', {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({ messages }),
    });

    if (!res.ok) {
      const data = await res.json().catch(() => ({}));
      onError(data.error ?? `HTTP ${res.status}`);
      return;
    }

    const reader = res.body?.getReader();
    if (!reader) { onError('Stream nicht verfügbar'); return; }

    const decoder = new TextDecoder();
    let buffer = '';

    while (true) {
      const { done, value } = await reader.read();
      if (done) break;

      buffer += decoder.decode(value, { stream: true });
      const lines = buffer.split('\n');
      buffer = lines.pop() ?? '';

      for (const line of lines) {
        if (!line.startsWith('data: ')) continue;
        const payload = line.slice(6).trim();
        if (payload === '[DONE]') { onDone(); return; }
        try {
          const parsed = JSON.parse(payload);
          if (parsed.text) onChunk(parsed.text);
          if (parsed.error) { onError(parsed.error); return; }
        } catch {
          // ignore parse errors
        }
      }
    }
    onDone();
  } catch (err) {
    onError(err instanceof Error ? err.message : 'Netzwerkfehler');
  }
}

// ============================================================
// AgentChat Component
// ============================================================
export default function AgentChat() {
  const [isOpen, setIsOpen] = useState(false);
  const [messages, setMessages] = useState<Message[]>([]);
  const [input, setInput] = useState('');
  const [isLoading, setIsLoading] = useState(false);
  const [showQuickActions, setShowQuickActions] = useState(true);

  const messagesEndRef = useRef<HTMLDivElement>(null);
  const inputRef = useRef<HTMLTextAreaElement>(null);
  const streamingIdRef = useRef<string | null>(null);

  // Auto-scroll bei neuen Nachrichten
  useEffect(() => {
    messagesEndRef.current?.scrollIntoView({ behavior: 'smooth' });
  }, [messages]);

  // Fokus ins Eingabefeld wenn Panel öffnet
  useEffect(() => {
    if (isOpen) {
      setTimeout(() => inputRef.current?.focus(), 300);
    }
  }, [isOpen]);

  const formatTime = (date: Date) =>
    date.toLocaleTimeString('de-DE', { hour: '2-digit', minute: '2-digit' });

  const handleSend = useCallback(
    async (text?: string) => {
      const messageText = (text ?? input).trim();
      if (!messageText || isLoading) return;

      setInput('');
      setShowQuickActions(false);

      // User-Nachricht hinzufügen
      const userMsg: Message = {
        id: Date.now().toString(),
        role: 'user',
        content: messageText,
        timestamp: new Date(),
      };
      setMessages((prev) => [...prev, userMsg]);
      setIsLoading(true);

      // Leere Assistenten-Nachricht für Streaming vorbereiten
      const assistantId = (Date.now() + 1).toString();
      streamingIdRef.current = assistantId;
      const assistantMsg: Message = {
        id: assistantId,
        role: 'assistant',
        content: '',
        timestamp: new Date(),
      };
      setMessages((prev) => [...prev, assistantMsg]);

      // Chat-History für API aufbauen (nur role + content)
      const history = [
        ...messages.map((m) => ({ role: m.role, content: m.content })),
        { role: 'user' as const, content: messageText },
      ];

      await sendMessage(
        history,
        // onChunk: Text an laufende Nachricht anhängen
        (chunk) => {
          setMessages((prev) =>
            prev.map((m) =>
              m.id === assistantId ? { ...m, content: m.content + chunk } : m
            )
          );
        },
        // onDone
        () => {
          setIsLoading(false);
          streamingIdRef.current = null;
        },
        // onError
        (err) => {
          setMessages((prev) =>
            prev.map((m) =>
              m.id === assistantId
                ? { ...m, content: `⚠️ Fehler: ${err}` }
                : m
            )
          );
          setIsLoading(false);
          streamingIdRef.current = null;
        }
      );
    },
    [input, isLoading, messages]
  );

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

  const handleQuickAction = (prompt: string) => {
    handleSend(prompt);
  };

  return (
    <>
      {/* ---- Floating Button ---- */}
      <button
        className={`${styles.trigger} ${isOpen ? styles.open : ''}`}
        onClick={() => setIsOpen((o) => !o)}
        aria-label={isOpen ? 'Chat schließen' : 'Günther öffnen'}
        title="Günther – Fußball-Experte"
      >
          {isOpen ? '✕' : <img src={netzerpng} alt="Günther" style={{ width: '52px', height: '52px', objectFit: 'contain' }} />}
      </button>

      {/* ---- Chat Panel ---- */}
      {isOpen && (
        <div className={styles.panel} role="dialog" aria-label="Fußball-Experte Chat">
          {/* Header */}
          <div className={styles.header}>
            <span className={styles.headerIcon}><img src={netzerpng} alt="Günther" style={{ width: '28px', height: '28px', objectFit: 'contain' }} /></span>
            <div style={{ flex: 1 }}>
              <div className={styles.headerTitle}>Günther</div>
              <div className={styles.headerSub}>Statistiken · Tipps · Fun Facts</div>
            </div>
            <div className={styles.headerOnline} title="Online" />
          </div>

          {/* Messages */}
          <div className={styles.messages}>
            {messages.length === 0 && (
              <div style={{ color: 'var(--text-secondary)', fontSize: 13, textAlign: 'center', paddingTop: 8 }}>
                Frag mich alles rund um Fußball, WM &amp; EM! ⚽
              </div>
            )}

            {messages.map((msg, idx) => {
              const isLastAssistant =
                msg.role === 'assistant' && idx === messages.length - 1;
              const isStreaming = isLoading && streamingIdRef.current === msg.id;
              const { before, choices, hasChoices } =
                msg.role === 'assistant' && !isStreaming
                  ? parseChoices(msg.content)
                  : { before: msg.content, choices: [], hasChoices: false };

              return (
                <div key={msg.id} className={`${styles.message} ${styles[msg.role]}`}>
                  <div className={styles.bubble}>
                    {msg.role === 'assistant' ? (
                      <>
                        {/* Typing Indicator solange Inhalt noch leer */}
                        {msg.content === '' && isStreaming ? (
                          <div className={styles.typing}>
                            <div className={styles.dot} />
                            <div className={styles.dot} />
                            <div className={styles.dot} />
                          </div>
                        ) : (
                          <div className={styles.markdownBody}>
                            {renderMarkdown(hasChoices ? before : msg.content)}
                          </div>
                        )}
                        {/* Choice-Selector: nur bei letzter Assistenten-Nachricht */}
                        {hasChoices && isLastAssistant && (
                          <ChoiceSelector
                            choices={choices}
                            disabled={isLoading}
                            onConfirm={(selected) => {
                              const text =
                                selected.length === choices.length
                                  ? 'Analysiere bitte alle Spiele.'
                                  : 'Analysiere bitte: ' + selected.join(', ');
                              handleSend(text);
                            }}
                          />
                        )}
                      </>
                    ) : (
                      msg.content
                    )}
                  </div>
                  <div className={styles.messageTime}>{formatTime(msg.timestamp)}</div>
                </div>
              );
            })}
            <div ref={messagesEndRef} />
          </div>

          {/* Quick Actions (nur beim ersten Öffnen, solange kein Chat läuft) */}
          {showQuickActions && messages.length === 0 && (
            <div className={styles.quickActions}>
              <div className={styles.quickActionsLabel}>Schnellauswahl</div>
              <div className={styles.quickChips}>
                {QUICK_ACTIONS.map((qa) => (
                  <button
                    key={qa.label}
                    className={styles.chip}
                    onClick={() => handleQuickAction(qa.prompt)}
                    disabled={isLoading}
                  >
                    {qa.label}
                  </button>
                ))}
              </div>
            </div>
          )}

          {/* Input Area */}
          <div className={styles.inputArea}>
            <textarea
              ref={inputRef}
              className={styles.input}
              placeholder="Frag den Experten…"
              value={input}
              onChange={(e) => setInput(e.target.value)}
              onKeyDown={handleKeyDown}
              disabled={isLoading}
              rows={1}
            />
            <button
              className={styles.sendBtn}
              onClick={() => handleSend()}
              disabled={!input.trim() || isLoading}
              aria-label="Senden"
            >
              ➤
            </button>
          </div>
        </div>
      )}
    </>
  );
}
