/**
 * ChatStream -- SSE-driven message display for the workspace.
 *
 * Renders messages with full Markdown (GFM tables, code blocks with syntax
 * highlighting), agent progress indicators, and file edit proposals.
 */

import React, { useRef, useEffect, useCallback, useState } from 'react';
import ReactMarkdown from 'react-markdown';
import remarkGfm from 'remark-gfm';
import api from '../../../api';
import { formatBinaryDataSizeBytes } from '../../../utils/formatDataSize';
import type { Message, MessageDocument } from '../../../components/UiComponents/Messages/MessagesTypes';
import type { AgentProgress, FileEditProposal } from './useWorkspace';

import { useLanguage } from '../../../providers/language/LanguageContext';

interface ChatStreamProps {
  messages: Message[];
  agentProgress: AgentProgress | null;
  isProcessing: boolean;
  pendingEdits: FileEditProposal[];
  onAcceptEdit: (editId: string) => void;
  onRejectEdit: (editId: string) => void;
  onOpenEditor?: () => void;
}

export const ChatStream: React.FC<ChatStreamProps> = ({ messages,
  agentProgress,
  isProcessing,
  pendingEdits,
  onAcceptEdit,
  onRejectEdit,
  onOpenEditor,
}) => {
  const bottomRef = useRef<HTMLDivElement>(null);

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

  return (
    <div style={{
      flex: 1,
      minHeight: 0,
      overflowY: 'auto',
      padding: '16px 24px',
      display: 'flex',
      flexDirection: 'column',
      gap: 12,
    }}>
      {messages.map((msg) => (
        <div
          key={msg.id}
          style={{
            flexShrink: 0,
            padding: '10px 14px',
            borderRadius: 8,
            maxWidth: '85%',
            alignSelf: msg.role === 'user' ? 'flex-end' : 'flex-start',
            background: _getBubbleBackground(msg.role || 'assistant'),
            border: msg.role === 'user'
              ? 'none'
              : '1px solid var(--border-color, #e0e0e0)',
            fontSize: msg.role === 'status' ? 12 : 14,
            color: msg.role === 'status' ? '#795548' : 'inherit',
            fontStyle: msg.role === 'status' ? 'italic' : 'normal',
            wordBreak: 'break-word',
            overflow: 'hidden',
          }}
        >
          {msg.role === 'assistant' && (
            <div style={{ fontSize: 11, color: '#888', marginBottom: 4 }}>Assistant</div>
          )}
          {msg.role === 'status' ? (
            <span>{msg.message}</span>
          ) : (
            <div className="workspace-markdown">
              {msg.documentsLabel && (
                <div
                  style={{
                    fontSize: 12,
                    color: '#666',
                    marginBottom: msg.message ? 8 : 0,
                    fontStyle: 'italic',
                  }}
                >
                  {msg.documentsLabel}
                </div>
              )}
              {msg.message && (
                <ReactMarkdown
                  remarkPlugins={[remarkGfm]}
                  components={{
                    code: _CodeBlock,
                    table: ({ children }) => (
                      <div style={{ overflowX: 'auto', margin: '8px 0' }}>
                        <table style={{
                          borderCollapse: 'collapse',
                          width: '100%',
                          fontSize: 13,
                        }}>
                          {children}
                        </table>
                      </div>
                    ),
                    th: ({ children }) => (
                      <th style={{
                        borderBottom: '2px solid #ddd',
                        padding: '6px 10px',
                        textAlign: 'left',
                        fontWeight: 600,
                        background: '#f8f9fa',
                        fontSize: 12,
                      }}>
                        {children}
                      </th>
                    ),
                    td: ({ children }) => (
                      <td style={{
                        borderBottom: '1px solid #eee',
                        padding: '5px 10px',
                        fontSize: 12,
                      }}>
                        {children}
                      </td>
                    ),
                    a: ({ href, children }) => (
                      <a href={href} target="_blank" rel="noopener noreferrer" style={{ color: 'var(--primary-color, #F25843)' }}>
                        {children}
                      </a>
                    ),
                    img: ({ src, alt, ...rest }) =>
                      src ? <img src={src} alt={alt || ''} {...rest} style={{ maxWidth: '100%', borderRadius: 6 }} /> : null,
                  }}
                >
                  {msg.message}
                </ReactMarkdown>
              )}
              {msg.documents && msg.documents.length > 0 && (
                <div style={{ marginTop: msg.message ? 8 : 0, display: 'flex', flexDirection: 'column', gap: 6 }}>
                  {msg.documents.map((doc) => (
                    <_FileCard key={doc.id || doc.fileId} doc={doc} />
                  ))}
                </div>
              )}
              {(msg as any)._audioUrl && (
                <_AudioPlayer
                  url={(msg as any)._audioUrl}
                  language={(msg as any)._audioLang}
                  charCount={(msg as any)._audioCharCount}
                />
              )}
              {msg.role === 'assistant' && msg.documents && msg.documents.length > 0 && (
                <details className="sentDataDetails" style={{ marginTop: 8, fontSize: '0.8rem', borderTop: '1px solid var(--border-color, #e5e7eb)', paddingTop: 6 }}>
                  <summary style={{ cursor: 'pointer', color: 'var(--text-secondary, #6b7280)', fontWeight: 500, userSelect: 'none' }}>
                    Gesendete Daten ({msg.documents.length} {msg.documents.length === 1 ? 'Dokument' : 'Dokumente'})
                  </summary>
                  <div style={{ marginTop: 6, display: 'flex', flexDirection: 'column', gap: 4 }}>
                    {msg.documents.map((doc, idx) => (
                      <div key={doc.id || idx} style={{ display: 'flex', alignItems: 'center', gap: 6, padding: '4px 8px', background: 'var(--bg-hover, rgba(0,0,0,0.02))', borderRadius: 4 }}>
                        <span style={{ flex: 1, overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' }}>
                          {doc.documentName || doc.fileName || `Dokument ${idx + 1}`}
                        </span>
                        {doc.validationMetadata?.neutralized && (
                          <span style={{ fontSize: '0.7rem', padding: '1px 6px', borderRadius: 10, background: '#dcfce7', color: '#166534' }}>
                            neutralisiert
                          </span>
                        )}
                        {doc.validationMetadata?.skipped && (
                          <span style={{ fontSize: '0.7rem', padding: '1px 6px', borderRadius: 10, background: '#fef2f2', color: '#991b1b' }}>
                            übersprungen
                          </span>
                        )}
                      </div>
                    ))}
                  </div>
                  {(msg as any).neutralizationExcluded?.length > 0 && (
                    <div style={{ marginTop: 6, padding: '6px 8px', background: '#fef2f2', borderRadius: 4, border: '1px solid #fecaca' }}>
                      <div style={{ fontWeight: 600, color: '#991b1b', marginBottom: 4 }}>
                        Nicht gesendet (Neutralisierung fehlgeschlagen):
                      </div>
                      {(msg as any).neutralizationExcluded.map((docName: string, i: number) => (
                        <div key={i} style={{ fontSize: '0.75rem', color: '#991b1b', paddingLeft: 4 }}>
                          {docName}
                        </div>
                      ))}
                    </div>
                  )}
                </details>
              )}
            </div>
          )}
        </div>
      ))}

      {/* File edit proposals -- compact notification cards */}
      {pendingEdits.filter(e => e.status === 'pending').length > 0 && (
        <div
          style={{
            flexShrink: 0,
            padding: 12,
            borderRadius: 8,
            border: '1px solid var(--warning-color, #ff9800)',
            background: 'var(--edit-bg, #fff8e1)',
            alignSelf: 'flex-start',
            maxWidth: '85%',
          }}
        >
          <div style={{ fontSize: 13, fontWeight: 600, marginBottom: 6, display: 'flex', alignItems: 'center', gap: 6 }}>
            <span style={{ color: '#ff9800' }}>✎</span>
            {pendingEdits.filter(e => e.status === 'pending').length} Aenderungsvorschlag(e)
          </div>
          <div style={{ display: 'flex', flexDirection: 'column', gap: 4, marginBottom: 8 }}>
            {pendingEdits.filter(e => e.status === 'pending').map(edit => (
              <div key={edit.id} style={{ fontSize: 12, color: '#555', display: 'flex', alignItems: 'center', gap: 6 }}>
                <span style={{ width: 6, height: 6, borderRadius: '50%', background: '#ff9800', flexShrink: 0 }} />
                {edit.fileName}
              </div>
            ))}
          </div>
          <div style={{ display: 'flex', gap: 8 }}>
            {onOpenEditor && (
              <button
                onClick={onOpenEditor}
                style={{
                  padding: '5px 14px', borderRadius: 4, border: 'none',
                  background: 'var(--primary-color, #F25843)', color: '#fff',
                  cursor: 'pointer', fontSize: 12, fontWeight: 600,
                }}
              >
                Im Editor pruefen
              </button>
            )}
            <button
              onClick={() => pendingEdits.filter(e => e.status === 'pending').forEach(e => onAcceptEdit(e.id))}
              style={{
                padding: '5px 14px', borderRadius: 4, border: 'none',
                background: 'var(--success-color, #4caf50)', color: '#fff',
                cursor: 'pointer', fontSize: 12, fontWeight: 600,
              }}
            >
              Alle annehmen
            </button>
            <button
              onClick={() => pendingEdits.filter(e => e.status === 'pending').forEach(e => onRejectEdit(e.id))}
              style={{
                padding: '5px 14px', borderRadius: 4,
                border: '1px solid var(--border-color, #ccc)',
                background: '#fff', cursor: 'pointer', fontSize: 12,
              }}
            >
              Alle ablehnen
            </button>
          </div>
        </div>
      )}

      {/* Agent progress */}
      {isProcessing && agentProgress && (
        <div style={{
          flexShrink: 0,
          padding: '8px 14px', borderRadius: 8, fontSize: 12,
          background: 'var(--progress-bg, #e8f5e9)',
          border: '1px solid var(--progress-border, #c8e6c9)',
          alignSelf: 'flex-start',
          display: 'flex', gap: 12, alignItems: 'center',
        }}>
          <span style={{ fontWeight: 600 }}>
            Round {agentProgress.round}{agentProgress.maxRounds ? `/${agentProgress.maxRounds}` : ''}
          </span>
          <span>{agentProgress.totalToolCalls} tools</span>
          <span>{agentProgress.costCHF?.toFixed(4) || '0'} CHF</span>
        </div>
      )}

      {isProcessing && !agentProgress && (
        <div style={{
          flexShrink: 0,
          padding: '8px 14px', borderRadius: 8, fontSize: 12,
          color: '#666', alignSelf: 'flex-start', fontStyle: 'italic',
          display: 'flex', alignItems: 'center', gap: 8,
        }}>
          <span className="workspace-spinner" style={{
            display: 'inline-block', width: 12, height: 12,
            border: '2px solid var(--border-color, #ccc)', borderTopColor: 'var(--primary-color, #F25843)',
            borderRadius: '50%', animation: 'workspace-spin 0.8s linear infinite',
          }} />
          Processing...
        </div>
      )}

      <div ref={bottomRef} />

      <style>{`
        @keyframes workspace-spin {
          to { transform: rotate(360deg); }
        }
        .workspace-markdown p { margin: 4px 0; }
        .workspace-markdown ul, .workspace-markdown ol { margin: 4px 0; padding-left: 20px; }
        .workspace-markdown blockquote {
          margin: 8px 0; padding: 4px 12px;
          border-left: 3px solid #ddd; color: #666;
        }
        .workspace-markdown h1, .workspace-markdown h2, .workspace-markdown h3 {
          margin: 8px 0 4px; line-height: 1.3;
        }
        .workspace-markdown img { max-width: 100%; border-radius: 4px; }
        .workspace-markdown hr { border: none; border-top: 1px solid #e0e0e0; margin: 8px 0; }
      `}</style>
    </div>
  );
};

function _getBubbleBackground(role: string): string {
  switch (role) {
    case 'user': return 'var(--primary-light, #e3f2fd)';
    case 'status': return 'var(--status-bg, #fff3e0)';
    case 'system': return 'var(--system-bg, #f5f5f5)';
    default: return 'var(--assistant-bg, #ffffff)';
  }
}

function _FileCard({ doc }: { doc: MessageDocument }) {
  const { t } = useLanguage();
  const _handleDownload = useCallback(async () => {
    try {
      const res = await api.get(`/api/files/${doc.fileId}/download`, {
        responseType: 'blob',
      });
      const blob = new Blob([res.data], { type: doc.mimeType || 'application/octet-stream' });
      const url = URL.createObjectURL(blob);
      const a = document.createElement('a');
      a.href = url;
      a.download = doc.fileName || 'download';
      document.body.appendChild(a);
      a.click();
      document.body.removeChild(a);
      URL.revokeObjectURL(url);
    } catch (err) {
      console.error('Download failed:', err);
    }
  }, [doc]);

  const ext = (doc.fileName || '').split('.').pop()?.toLowerCase() || '';
  const icon = _getFileIcon(ext);
  const sizeLabel = doc.fileSize ? formatBinaryDataSizeBytes(doc.fileSize) : '';

  return (
    <div
      onClick={_handleDownload}
      style={{
        display: 'flex',
        alignItems: 'center',
        gap: 10,
        padding: '8px 12px',
        borderRadius: 6,
        border: '1px solid var(--border-color, #e0e0e0)',
        background: 'var(--file-card-bg, #f8f9fa)',
        cursor: 'pointer',
        transition: 'background 0.15s',
        maxWidth: 340,
      }}
      title={`Download ${doc.fileName}`}
      onMouseEnter={e => (e.currentTarget.style.background = '#e8f0fe')}
      onMouseLeave={e => (e.currentTarget.style.background = 'var(--file-card-bg, #f8f9fa)')}
    >
      <span style={{ fontSize: 22 }}>{icon}</span>
      <div style={{ flex: 1, minWidth: 0 }}>
        <div style={{
          fontSize: 13, fontWeight: 600, overflow: 'hidden',
          textOverflow: 'ellipsis', whiteSpace: 'nowrap',
        }}>
          {doc.fileName}
        </div>
        <div style={{ fontSize: 11, color: '#888' }}>
          {ext.toUpperCase()}{sizeLabel ? ` \u00b7 ${sizeLabel}` : ''}
        </div>
      </div>
      <span style={{ fontSize: 14, color: 'var(--primary-color, #F25843)' }} title={t('Download')}>&#x2B07;</span>
    </div>
  );
}

function _getFileIcon(ext: string): string {
  const map: Record<string, string> = {
    pdf: '\uD83D\uDCC4', csv: '\uD83D\uDCCA', xlsx: '\uD83D\uDCCA', xls: '\uD83D\uDCCA',
    doc: '\uD83D\uDCC3', docx: '\uD83D\uDCC3', txt: '\uD83D\uDCC4', json: '\uD83D\uDCCB',
    md: '\uD83D\uDCC4', xml: '\uD83D\uDCCB', yaml: '\uD83D\uDCCB', yml: '\uD83D\uDCCB',
    html: '\uD83C\uDF10', css: '\uD83C\uDFA8', js: '\uD83D\uDCDC', ts: '\uD83D\uDCDC',
    py: '\uD83D\uDC0D', sql: '\uD83D\uDDC3\uFE0F', log: '\uD83D\uDCDD',
    png: '\uD83D\uDDBC\uFE0F', jpg: '\uD83D\uDDBC\uFE0F', jpeg: '\uD83D\uDDBC\uFE0F',
    gif: '\uD83D\uDDBC\uFE0F', svg: '\uD83D\uDDBC\uFE0F', webp: '\uD83D\uDDBC\uFE0F',
    zip: '\uD83D\uDCE6', rar: '\uD83D\uDCE6', '7z': '\uD83D\uDCE6', tar: '\uD83D\uDCE6',
    pptx: '\uD83D\uDCCA', ppt: '\uD83D\uDCCA',
    mp3: '\uD83C\uDFB5', wav: '\uD83C\uDFB5', ogg: '\uD83C\uDFB5',
    mp4: '\uD83C\uDFAC', avi: '\uD83C\uDFAC', mov: '\uD83C\uDFAC', webm: '\uD83C\uDFAC',
    eml: '\uD83D\uDCE7', msg: '\uD83D\uDCE7',
  };
  return map[ext] || '\uD83D\uDCC4';
}

function _AudioPlayer({ url, language }: { url: string; language?: string; charCount?: number }) {
  const audioRef = useRef<HTMLAudioElement | null>(null);
  const [playing, setPlaying] = useState(false);
  const [progress, setProgress] = useState(0);
  const [duration, setDuration] = useState(0);

  useEffect(() => {
    const audio = new Audio(url);
    audioRef.current = audio;

    audio.addEventListener('loadedmetadata', () => setDuration(audio.duration));
    audio.addEventListener('timeupdate', () => {
      if (audio.duration) setProgress(audio.currentTime / audio.duration);
    });
    audio.addEventListener('ended', () => { setPlaying(false); setProgress(0); });
    audio.addEventListener('pause', () => setPlaying(false));
    audio.addEventListener('play', () => setPlaying(true));

    audio.play().catch(() => {});

    return () => {
      audio.pause();
      audio.src = '';
    };
  }, [url]);

  const _togglePlay = useCallback(() => {
    const audio = audioRef.current;
    if (!audio) return;
    if (playing) { audio.pause(); } else { audio.play().catch(() => {}); }
  }, [playing]);

  const _stop = useCallback(() => {
    const audio = audioRef.current;
    if (!audio) return;
    audio.pause();
    audio.currentTime = 0;
    setPlaying(false);
    setProgress(0);
  }, []);

  const _formatTime = (s: number) => {
    const m = Math.floor(s / 60);
    const sec = Math.floor(s % 60);
    return `${m}:${sec.toString().padStart(2, '0')}`;
  };

  return (
    <div style={{
      display: 'flex', alignItems: 'center', gap: 8,
      padding: '8px 12px', borderRadius: 8,
      background: 'var(--audio-player-bg, #f0f4f8)',
      border: '1px solid var(--border-color, #e0e0e0)',
      maxWidth: 360, marginTop: 6,
    }}>
      <button
        onClick={_togglePlay}
        style={{
          width: 32, height: 32, borderRadius: '50%', border: 'none',
          background: 'var(--primary-color, #F25843)', color: '#fff',
          cursor: 'pointer', fontSize: 14,
          display: 'flex', alignItems: 'center', justifyContent: 'center',
          flexShrink: 0,
        }}
        title={playing ? 'Pause' : 'Play'}
      >
        {playing ? '\u275A\u275A' : '\u25B6'}
      </button>

      <div style={{ flex: 1, minWidth: 0 }}>
        <div style={{
          height: 4, borderRadius: 2,
          background: 'var(--border-color, #ddd)',
          overflow: 'hidden',
        }}>
          <div style={{
            height: '100%', borderRadius: 2,
            background: 'var(--primary-color, #F25843)',
            width: `${progress * 100}%`,
            transition: 'width 0.2s',
          }} />
        </div>
        <div style={{ display: 'flex', justifyContent: 'space-between', marginTop: 2 }}>
          <span style={{ fontSize: 10, color: '#888' }}>
            {duration > 0 ? _formatTime(progress * duration) : '0:00'}
          </span>
          <span style={{ fontSize: 10, color: '#888' }}>
            {duration > 0 ? _formatTime(duration) : '--:--'}
          </span>
        </div>
      </div>

      <button
        onClick={_stop}
        style={{
          width: 28, height: 28, borderRadius: '50%', border: '1px solid #ccc',
          background: 'transparent', color: '#888',
          cursor: 'pointer', fontSize: 12,
          display: 'flex', alignItems: 'center', justifyContent: 'center',
          flexShrink: 0,
        }}
        title="Stop"
      >
        &#x25A0;
      </button>

      {language && (
        <span style={{ fontSize: 10, color: '#aaa', flexShrink: 0 }}>
          {language}
        </span>
      )}
    </div>
  );
}

function _CodeBlock({
  className,
  children,
  ...props
}: React.HTMLAttributes<HTMLElement> & { inline?: boolean }) {
  const match = /language-(\w+)/.exec(className || '');
  const isInline = !match && !String(children).includes('\n');

  if (isInline) {
    return (
      <code
        style={{
          background: '#f0f0f0',
          padding: '1px 5px',
          borderRadius: 3,
          fontSize: '0.9em',
          fontFamily: 'Consolas, Monaco, "Courier New", monospace',
        }}
        {...props}
      >
        {children}
      </code>
    );
  }

  return (
    <div style={{ position: 'relative', margin: '8px 0' }}>
      {match && (
        <div style={{
          position: 'absolute', top: 0, right: 0,
          padding: '2px 8px', fontSize: 10, color: '#888',
          background: '#2d2d2d', borderBottomLeftRadius: 4,
        }}>
          {match[1]}
        </div>
      )}
      <pre style={{
        background: '#1e1e1e',
        color: '#d4d4d4',
        padding: '12px 14px',
        borderRadius: 6,
        overflow: 'auto',
        fontSize: 13,
        fontFamily: 'Consolas, Monaco, "Courier New", monospace',
        lineHeight: 1.5,
        margin: 0,
      }}>
        <code className={className} {...props}>
          {children}
        </code>
      </pre>
    </div>
  );
}
