/**
 * CommCoach Session View (Refactored)
 *
 * Shows ONLY the active coaching session: Chat, Voice, TTS, Agent activity.
 * Three states:
 *   1. No module selected -> hint with links to Assistant / Modules
 *   2. Module selected, no session -> persona picker + "Start session"
 *   3. Session active -> full chat/voice/TTS interface
 *
 * Reachable via Assistant wizard or Modules page ("Session starten" button).
 * KeepAlive-wrapped — voice sessions persist across tab switches.
 */
import React, { useState, useRef, useCallback, useEffect } from 'react';
import { useSearchParams, useNavigate, useLocation } from 'react-router-dom';
import { useCommcoach } from '../../../hooks/useCommcoach';
import { type TtsEvent } from '../../../hooks/useTtsPlayback';
import { useApiRequest } from '../../../hooks/useApi';
import { useInstanceId, useMandateId } from '../../../hooks/useCurrentInstance';
import {
  getPersonasApi, getModulePersonasApi,
  type CoachingPersona,
  type SendMessageOptions,
} from '../../../api/commcoachApi';
import api from '../../../api';
import AutoScroll from '../../../components/UiComponents/AutoScroll/AutoScroll';
import ReactMarkdown from 'react-markdown';
import remarkGfm from 'remark-gfm';
import { UnifiedDataBar } from '../../../components/UnifiedDataBar';
import type { UdbContext, UdbTab, AddToChat_FileItem } from '../../../components/UnifiedDataBar';
import { _defaultProviderSelection } from '../../../components/ProviderSelector';
import type { ProviderSelection } from '../../../components/ProviderSelector';
import { getPageIcon } from '../../../config/pageRegistry';
import styles from './CommcoachDossierView.module.css';
import sessionStyles from './Commcoach.module.css';
import { useVoiceController } from './useVoiceController';
import { useLanguage } from '../../../providers/language/LanguageContext';

interface WorkspaceFileInfo { id: string; fileName: string; mimeType: string; fileSize: number; }
interface DataSourceInfo { id: string; connectionId: string; sourceType: string; path: string; label: string; }
interface FeatureDataSourceInfo { id: string; featureInstanceId: string; featureCode: string; tableName: string; label: string; }

function _formatToolPayload(payload: Record<string, unknown>): string {
  try {
    const s = JSON.stringify(payload, null, 0);
    return s.length > 120 ? s.substring(0, 120) + '...' : s;
  } catch { return '[unlesbar]'; }
}

export const CommcoachSessionView: React.FC = () => {
  const { t } = useLanguage();
  const navigate = useNavigate();
  const location = useLocation();
  const instanceId = useInstanceId();
  const mandateId = useMandateId();
  const coach = useCommcoach(instanceId);
  const { request } = useApiRequest();
  const [searchParams] = useSearchParams();
  const moduleId = searchParams.get('moduleId');

  const isSessionRoute = /\/commcoach\/[^/]+\/session/.test(location.pathname);

  const [personas, setPersonas] = useState<CoachingPersona[]>([]);
  const [modulePersonaIds, setModulePersonaIds] = useState<string[] | null>(null);
  const [selectedPersonaId, setSelectedPersonaId] = useState<string | undefined>(undefined);
  const [showAgentActivity, setShowAgentActivity] = useState(true);

  const [udbCollapsed, setUdbCollapsed] = useState(false);
  const [udbTab, setUdbTab] = useState<UdbTab>('files');
  const [udbWidth, setUdbWidth] = useState(280);
  const udbResizing = useRef(false);

  const [wsFiles, setWsFiles] = useState<WorkspaceFileInfo[]>([]);
  const [wsDataSources, setWsDataSources] = useState<DataSourceInfo[]>([]);
  const [wsFeatureDataSources, setWsFeatureDataSources] = useState<FeatureDataSourceInfo[]>([]);
  const [attachedFileIds, setAttachedFileIds] = useState<string[]>([]);
  const [attachedDsIds, setAttachedDsIds] = useState<string[]>([]);
  const [attachedFdsIds, setAttachedFdsIds] = useState<string[]>([]);
  const [providerSelection, _setProviderSelection] = useState<ProviderSelection>(_defaultProviderSelection);
  const [_showFilePicker, setShowFilePicker] = useState(false);
  const [_showSourcePicker, setShowSourcePicker] = useState(false);

  const _udbContext: UdbContext | null = instanceId
    ? { instanceId, mandateId: mandateId || undefined, featureInstanceId: instanceId }
    : null;

  const inputRef = useRef<HTMLTextAreaElement>(null);
  const sendMessageRef = useRef(coach.sendMessage);
  sendMessageRef.current = coach.sendMessage;
  const attachedFileIdsRef = useRef(attachedFileIds);
  attachedFileIdsRef.current = attachedFileIds;
  const attachedDsIdsRef = useRef(attachedDsIds);
  attachedDsIdsRef.current = attachedDsIds;
  const attachedFdsIdsRef = useRef(attachedFdsIds);
  attachedFdsIdsRef.current = attachedFdsIds;
  const providerSelRef = useRef(providerSelection);
  providerSelRef.current = providerSelection;

  const voice = useVoiceController({
    onFinalText: (text) => {
      const opts: SendMessageOptions = {};
      if (attachedFileIdsRef.current.length) opts.fileIds = attachedFileIdsRef.current;
      if (attachedDsIdsRef.current.length) opts.dataSourceIds = attachedDsIdsRef.current;
      if (attachedFdsIdsRef.current.length) opts.featureDataSourceIds = attachedFdsIdsRef.current;
      const allowed = providerSelRef.current.include.length > 0 ? providerSelRef.current.include : undefined;
      if (allowed) opts.allowedProviders = allowed;
      sendMessageRef.current(text, Object.keys(opts).length ? opts : undefined);
    },
  });

  useEffect(() => {
    coach.onTtsEventRef.current = (event: TtsEvent) => {
      if (event === 'playing') voice.ttsPlaying();
      else if (event === 'ended') voice.ttsEnded();
      else if (event === 'paused') voice.ttsPaused();
      else if (event === 'error') voice.ttsEnded();
    };
    return () => { coach.onTtsEventRef.current = null; };
  }, [coach.onTtsEventRef, voice.ttsPlaying, voice.ttsEnded, voice.ttsPaused]);

  // Auto-select module from URL param
  useEffect(() => {
    if (moduleId && coach.contexts.length > 0 && coach.selectedContextId !== moduleId) {
      const found = coach.contexts.find(c => c.id === moduleId);
      if (found) coach.selectContext(moduleId);
    } else if (!moduleId && !coach.selectedContextId && coach.contexts.length > 0) {
      coach.selectContext(coach.contexts[0].id, { skipSessionResume: true });
    }
  }, [moduleId, coach.contexts, coach.selectedContextId, coach.selectContext]);

  useEffect(() => {
    if (!instanceId || !isSessionRoute) return;
    getPersonasApi(request, instanceId).then(p => setPersonas(p)).catch(() => {});
  }, [instanceId, request, isSessionRoute]);

  useEffect(() => {
    if (!instanceId || !coach.selectedContextId || !isSessionRoute) { setModulePersonaIds(null); return; }
    getModulePersonasApi(request, instanceId, coach.selectedContextId)
      .then(ids => setModulePersonaIds(ids.length > 0 ? ids : null))
      .catch(() => setModulePersonaIds(null));
  }, [instanceId, request, coach.selectedContextId, isSessionRoute]);

  const _refreshWorkspaceAssets = useCallback(() => {
    if (!instanceId) return;
    api.get(`/api/workspace/${instanceId}/files`).then(r => setWsFiles(r.data.files || [])).catch(() => {});
    api.get(`/api/workspace/${instanceId}/datasources`).then(r => setWsDataSources(r.data.dataSources || [])).catch(() => {});
    api.get(`/api/workspace/${instanceId}/feature-datasources`).then(r => setWsFeatureDataSources(r.data.featureDataSources || [])).catch(() => {});
  }, [instanceId]);

  useEffect(() => { _refreshWorkspaceAssets(); }, [_refreshWorkspaceAssets]);
  useEffect(() => {
    const h = () => _refreshWorkspaceAssets();
    window.addEventListener('fileUploaded', h);
    return () => window.removeEventListener('fileUploaded', h);
  }, [_refreshWorkspaceAssets]);

  useEffect(() => {
    if (!coach.session) {
      voice.deactivate();
    } else if (voice.state === 'idle') {
      voice.activate();
    }
  }, [coach.session?.id, voice]);

  useEffect(() => {
    coach.onDocumentCreatedRef.current = () => {
      window.dispatchEvent(new CustomEvent('fileUploaded', { detail: { source: 'commcoachDocument' } }));
    };
    return () => { coach.onDocumentCreatedRef.current = null; };
  }, [coach, _refreshWorkspaceAssets]);

  useEffect(() => {
    if (coach.agentToolCalls.length > 0) setShowAgentActivity(true);
  }, [coach.agentToolCalls.length]);

  const handleStopTts = useCallback(() => { coach.stopTts(); voice.ttsStopped(); }, [coach, voice]);
  const handlePauseTts = useCallback(() => coach.pauseTts(), [coach]);
  const handleResumeTts = useCallback(() => coach.resumeTts(), [coach]);

  const handleSend = useCallback(async () => {
    if (!coach.inputValue.trim() || coach.isStreaming) return;
    const opts: SendMessageOptions = {};
    if (attachedFileIds.length) opts.fileIds = attachedFileIds;
    if (attachedDsIds.length) opts.dataSourceIds = attachedDsIds;
    if (attachedFdsIds.length) opts.featureDataSourceIds = attachedFdsIds;
    const allowed = providerSelection.include.length > 0 ? providerSelection.include : undefined;
    if (allowed) opts.allowedProviders = allowed;
    await coach.sendMessage(coach.inputValue, Object.keys(opts).length ? opts : undefined);
    setAttachedFileIds([]);
    setShowSourcePicker(false);
    setShowFilePicker(false);
  }, [coach, attachedFileIds, attachedDsIds, attachedFdsIds, providerSelection]);

  const handleKeyDown = useCallback((e: React.KeyboardEvent) => {
    if (e.key === 'Enter' && !e.shiftKey) { e.preventDefault(); handleSend(); }
  }, [handleSend]);

  const _toggleFile = useCallback((fileId: string) => {
    setAttachedFileIds(prev => prev.includes(fileId) ? prev.filter(id => id !== fileId) : [...prev, fileId]);
  }, []);
  const _toggleDs = useCallback((dsId: string) => {
    setAttachedDsIds(prev => prev.includes(dsId) ? prev.filter(id => id !== dsId) : [...prev, dsId]);
  }, []);
  const _toggleFds = useCallback((fdsId: string) => {
    setAttachedFdsIds(prev => prev.includes(fdsId) ? prev.filter(id => id !== fdsId) : [...prev, fdsId]);
  }, []);

  const attachedFileNamesRef = useRef<Record<string, string>>({});

  const _handleUdbFileSelect = useCallback((fileId: string, fileName?: string) => {
    if (fileName) attachedFileNamesRef.current[fileId] = fileName;
    setAttachedFileIds(prev => prev.includes(fileId) ? prev : [...prev, fileId]);
  }, []);

  const _handleUdbSendToChat = useCallback((items: AddToChat_FileItem[]) => {
    for (const item of items) {
      if (item.name) attachedFileNamesRef.current[item.id] = item.name;
    }
    const fileIds = items.filter(i => i.type === 'file').map(i => i.id);
    setAttachedFileIds(prev => {
      const merged = [...prev];
      for (const fId of fileIds) {
        if (!merged.includes(fId)) merged.push(fId);
      }
      return merged;
    });
  }, []);

  const _isTreeDrag = useCallback((e: React.DragEvent) => {
    return e.dataTransfer.types.includes('application/tree-items') ||
      e.dataTransfer.types.includes('application/file-id') ||
      e.dataTransfer.types.includes('application/file-ids');
  }, []);

  const _handleInputDragOver = useCallback((e: React.DragEvent) => {
    if (_isTreeDrag(e)) {
      e.preventDefault();
      e.stopPropagation();
      e.dataTransfer.dropEffect = 'copy';
    }
  }, [_isTreeDrag]);

  const _handleInputDrop = useCallback((e: React.DragEvent) => {
    const treeJson = e.dataTransfer.getData('application/tree-items');
    if (treeJson) {
      e.preventDefault();
      e.stopPropagation();
      try {
        const items: AddToChat_FileItem[] = JSON.parse(treeJson);
        for (const item of items) {
          if (item.name) attachedFileNamesRef.current[item.id] = item.name;
        }
        const fileIds = items.filter(i => i.type === 'file').map(i => i.id);
        setAttachedFileIds(prev => {
          const merged = [...prev];
          for (const fId of fileIds) {
            if (!merged.includes(fId)) merged.push(fId);
          }
          return merged;
        });
      } catch {}
      return;
    }
    const fileId = e.dataTransfer.getData('application/file-id');
    if (fileId) {
      e.preventDefault();
      e.stopPropagation();
      const name = e.dataTransfer.getData('text/plain');
      if (name) attachedFileNamesRef.current[fileId] = name;
      setAttachedFileIds(prev => prev.includes(fileId) ? prev : [...prev, fileId]);
    }
  }, []);

  const _toolPayloadForDisplay = (payload: Record<string, unknown>): string => {
    const formatted = _formatToolPayload(payload);
    return formatted === '[unlesbar]' ? t('[unlesbar]') : formatted;
  };

  if (coach.loadingContexts) {
    return <div className={sessionStyles.loading}>{t('Laden...')}</div>;
  }

  // ========== STATE 1: No module selected ==========
  if (!coach.selectedContextId && coach.contexts.length === 0) {
    return (
      <div className={sessionStyles.modulesContainer} style={{ alignItems: 'center', justifyContent: 'center' }}>
        <h3>{t('Keine aktive Session')}</h3>
        <p style={{ color: 'var(--text-secondary, #666)', textAlign: 'center', maxWidth: 400 }}>
          {t('Erstelle zuerst ein Modul ueber den Assistenten oder starte eine Session ueber die Module-Seite.')}
        </p>
        <div style={{ display: 'flex', gap: '0.75rem', marginTop: '1rem' }}>
          <button className={sessionStyles.btnPrimary}
            onClick={() => navigate(`/mandates/${mandateId}/commcoach/${instanceId}/assistant`)}
          >{t('Zum Assistenten')}</button>
          <button className={sessionStyles.btnSecondary}
            onClick={() => navigate(`/mandates/${mandateId}/commcoach/${instanceId}/modules`)}
          >{t('Zu den Modulen')}</button>
        </div>
      </div>
    );
  }

  // ========== STATE 2: Module selected, no active session ==========
  if (coach.selectedContextId && !coach.session) {
    return (
      <div className={sessionStyles.modulesContainer}>
        <div style={{ marginBottom: '1rem' }}>
          <h3>{coach.selectedContext?.title || t('Modul')}</h3>
          {coach.selectedContext?.description && (
            <p style={{ color: 'var(--text-secondary, #666)', marginTop: '0.25rem' }}>{coach.selectedContext.description}</p>
          )}
        </div>

        {personas.length > 0 && (() => {
          const availablePersonas = modulePersonaIds
            ? personas.filter(p => modulePersonaIds.includes(p.id))
            : personas;
          return availablePersonas.length > 0 ? (
            <div style={{ marginBottom: '1rem' }}>
              <label style={{ display: 'block', fontWeight: 500, marginBottom: '0.5rem' }}>{t('Gespraechspartner waehlen')}</label>
              {modulePersonaIds && (
                <p style={{ fontSize: '0.8rem', color: 'var(--text-secondary, #888)', margin: '0 0 0.5rem' }}>
                  {t('Fuer dieses Modul sind bestimmte Gespraechspartner konfiguriert.')}
                </p>
              )}
              <div style={{ display: 'flex', flexWrap: 'wrap', gap: '0.5rem' }}>
                {availablePersonas.map(p => (
                  <button
                    key={p.id}
                    className={`${sessionStyles.btnSmall} ${selectedPersonaId === p.id ? sessionStyles.btnSmallActive : ''}`}
                    onClick={() => setSelectedPersonaId(selectedPersonaId === p.id ? undefined : p.id)}
                    title={p.description}
                  >
                    <span>{p.gender === 'f' ? '\u2640' : p.gender === 'm' ? '\u2642' : '\u25CB'}</span>
                    {' '}{p.label}
                  </button>
                ))}
              </div>
            </div>
          ) : null;
        })()}

        <button
          className={sessionStyles.btnPrimary}
          onClick={() => coach.startSession(selectedPersonaId)}
          disabled={!!coach.actionLoading}
          style={{ alignSelf: 'flex-start' }}
        >
          {coach.actionLoading === 'starting'
            ? t('Wird gestartet...')
            : selectedPersonaId && personas.find(p => p.id === selectedPersonaId)
              ? `${t('Session starten mit')} ${personas.find(p => p.id === selectedPersonaId)!.label}`
              : t('Session starten')}
        </button>

        {coach.error && <div className={sessionStyles.errorBanner}>{coach.error}</div>}
      </div>
    );
  }

  // ========== STATE 3: Active session ==========
  return (
    <div className={styles.dossierLayout}>
      {/* UDB Sidebar */}
      {_udbContext && (
        <div
          className={`${styles.udbSidebar} ${udbCollapsed ? styles.udbSidebarCollapsed : ''}`}
          style={udbCollapsed ? undefined : { width: udbWidth, minWidth: 180 }}
        >
          <button
            className={styles.udbToggle}
            onClick={() => setUdbCollapsed(v => !v)}
            title={udbCollapsed ? t('Seitenleiste einblenden') : t('Seitenleiste ausblenden')}
          >
            {udbCollapsed ? '\u25B6' : '\u25C0'}
          </button>
          {!udbCollapsed && (
              <UnifiedDataBar
                context={_udbContext}
                activeTab={udbTab}
                onTabChange={setUdbTab}
                hideTabs={['chats']}
                onFileSelect={_handleUdbFileSelect}
                onSendToChat_Files={_handleUdbSendToChat}
              />
          )}
        </div>
      )}
      {_udbContext && !udbCollapsed && (
        <div
          className={styles.udbResizeHandle}
          onMouseDown={(e) => {
            e.preventDefault();
            udbResizing.current = true;
            const startX = e.clientX;
            const startW = udbWidth;
            const onMove = (ev: MouseEvent) => {
              if (!udbResizing.current) return;
              const newW = Math.max(180, Math.min(600, startW + (ev.clientX - startX)));
              setUdbWidth(newW);
            };
            const onUp = () => {
              udbResizing.current = false;
              document.removeEventListener('mousemove', onMove);
              document.removeEventListener('mouseup', onUp);
            };
            document.addEventListener('mousemove', onMove);
            document.addEventListener('mouseup', onUp);
          }}
        />
      )}

      {/* Main Session Content */}
      <div className={styles.dossier}>
        {/* Session Header */}
        <div className={styles.sessionHeader}>
          <span className={styles.sessionLabel}>
            {coach.selectedContext?.title ? `${coach.selectedContext.title} — ` : ''}
            {t('Session aktiv')}
          </span>
          <div className={styles.sessionActions}>
            {voice.state === 'botSpeaking' && (
              <>
                <button className={styles.btnSmall} onClick={handlePauseTts}>Pause</button>
                <button className={styles.btnSmallDanger} onClick={handleStopTts}>Stop</button>
              </>
            )}
            {voice.state === 'interrupted' && coach.hasAudioToResume() && (
              <button className={styles.btnSmall} onClick={handleResumeTts}>{t('Weitersprechen')}</button>
            )}
            <button
              className={`${styles.btnSmall} ${voice.muted ? styles.mutedActive : ''}`}
              onClick={voice.toggleMute}
              title={voice.muted ? t('Stummschaltung aufheben') : t('stummschalten')}
            >
              {voice.muted ? t('Stumm') : t('Ton an')}
            </button>
            <button className={styles.btnSmall} onClick={coach.completeSession} disabled={!!coach.actionLoading}>
              {coach.actionLoading === 'completing' ? t('wird abgeschlossen') : t('abschliessen')}
            </button>
            <button className={styles.btnSmallDanger} onClick={coach.cancelSession} disabled={!!coach.actionLoading}>
              {coach.actionLoading === 'cancelling' ? t('wird abgebrochen') : t('Abbrechen')}
            </button>
          </div>
        </div>

        {coach.error && <div className={styles.errorBanner || sessionStyles.errorBanner}>{coach.error}</div>}

        {/* Messages */}
        <AutoScroll scrollDependency={coach.messages.length + (coach.isStreaming ? 1 : 0) + voice.liveTranscript.length}>
          <div className={styles.messages}>
            {coach.messages.map(msg => (
              <div key={msg.id} className={`${styles.message} ${msg.role === 'user' ? styles.messageUser : styles.messageAssistant}`}>
                <div className={styles.messageBubble}>
                  <ReactMarkdown remarkPlugins={[remarkGfm]}>{msg.content}</ReactMarkdown>
                </div>
                <div className={styles.messageTime}>
                  {msg.createdAt ? new Date(msg.createdAt).toLocaleTimeString('de-CH', { hour: '2-digit', minute: '2-digit' }) : ''}
                </div>
              </div>
            ))}
            {voice.liveTranscript && (
              <div className={`${styles.message} ${styles.messageUser}`}>
                <div className={`${styles.messageBubble} ${styles.messageLive}`}>{voice.liveTranscript}</div>
              </div>
            )}
            {coach.isStreaming && (
              <div className={`${styles.message} ${styles.messageAssistant}`}>
                <div className={styles.messageBubble}>
                  {coach.streamingMessage ? (
                    <ReactMarkdown remarkPlugins={[remarkGfm]}>{coach.streamingMessage}</ReactMarkdown>
                  ) : (
                    <div className={styles.typing}>{coach.streamingStatus || t('Coach denkt nach')}<span className={styles.typingDots}>...</span></div>
                  )}
                </div>
              </div>
            )}
          </div>
        </AutoScroll>

        {/* Agent Activity Panel */}
        {(coach.isStreaming || coach.agentToolCalls.length > 0) && (
          <div className={styles.agentActivityPanel}>
            <button
              className={styles.agentActivityHeader}
              onClick={() => setShowAgentActivity(prev => !prev)}
              type="button"
            >
              <span className={styles.agentActivityTitle}>
                {t('Agent-Aktivitaet')}
                {coach.agentToolCalls.length > 0 ? ` (${coach.agentToolCalls.length})` : ''}
              </span>
              <span className={styles.agentActivityStatus}>
                {coach.streamingStatus || (coach.agentToolCalls.length > 0 ? t('Toolaufrufe vorhanden') : t('Warte auf Agent'))}
              </span>
              <span className={styles.agentActivityChevron}>{showAgentActivity ? '\u25BE' : '\u25B8'}</span>
            </button>
            {showAgentActivity && (
              <div className={styles.agentActivityBody}>
                {coach.agentToolCalls.length === 0 ? (
                  <div className={styles.agentActivityEmpty}>{t('Noch keine Tool-Aufrufe in dieser Antwort.')}</div>
                ) : (
                  coach.agentToolCalls.map((toolCall, idx) => (
                    <div key={`${toolCall.toolName}-${idx}`} className={styles.agentActivityItem}>
                      <div className={styles.agentActivityItemHeader}>
                        <span className={styles.agentActivityToolName}>{toolCall.toolName}</span>
                        <span className={`${styles.agentActivityBadge} ${
                          toolCall.success === true ? styles.agentActivityBadgeSuccess
                            : toolCall.success === false ? styles.agentActivityBadgeError
                              : styles.agentActivityBadgeRunning
                        }`}>
                          {toolCall.success === true ? t('fertig') : toolCall.success === false ? t('fehler') : t('laeuft')}
                        </span>
                      </div>
                      {toolCall.args && (
                        <div className={styles.agentActivityMeta}>
                          <strong>{t('Argumente:')}</strong> {_toolPayloadForDisplay(toolCall.args)}
                        </div>
                      )}
                      {toolCall.result && (
                        <div className={styles.agentActivityMeta}>
                          <strong>{t('Ergebnis:')}</strong> {toolCall.result}
                        </div>
                      )}
                    </div>
                  ))
                )}
              </div>
            )}
          </div>
        )}

        {/* Input Area */}
        <div className={styles.inputArea} onDragOver={_handleInputDragOver} onDrop={_handleInputDrop}>
          <div className={styles.voiceStatus}>
            <span className={`${styles.voiceIndicator} ${voice.state === 'listening' ? styles.voiceActive : ''}`}>
              {voice.muted
                ? t('Stumm - Mikrofon aus')
                : voice.state === 'botSpeaking'
                  ? (coach.streamingStatus || t('Coach spricht...'))
                  : coach.isStreaming
                    ? (coach.streamingStatus || t('Coach denkt nach...'))
                    : voice.state === 'interrupted'
                      ? t('Unterbrochen - Mikrofon an')
                      : voice.state === 'listening'
                        ? (voice.liveTranscript ? t('Spricht...') : t('Mikrofon an - bitte sprechen'))
                        : t('Mikrofon wird gestartet...')}
            </span>
          </div>

          {/* Attachment Chips */}
          {(attachedFileIds.length > 0 || attachedDsIds.length > 0 || attachedFdsIds.length > 0) && (
            <div style={{ display: 'flex', gap: 6, flexWrap: 'wrap', paddingBottom: 4 }}>
              {attachedFileIds.map(fId => {
                const file = wsFiles.find(f => f.id === fId);
                const displayName = file?.fileName || attachedFileNamesRef.current[fId] || fId;
                return (
                  <span key={fId} style={{ display: 'inline-flex', alignItems: 'center', gap: 4, padding: '2px 8px', borderRadius: 12, fontSize: 11, background: '#e3f2fd', color: '#1565c0', fontWeight: 500 }}>
                    {displayName}
                    <button onClick={() => _toggleFile(fId)} style={{ border: 'none', background: 'none', cursor: 'pointer', fontSize: 11, color: '#1565c0', padding: 0, lineHeight: 1 }}>x</button>
                  </span>
                );
              })}
              {attachedDsIds.map(dsId => {
                const ds = wsDataSources.find(d => d.id === dsId);
                return (
                  <span key={dsId} style={{ display: 'inline-flex', alignItems: 'center', gap: 4, padding: '2px 8px', borderRadius: 12, fontSize: 11, background: '#e8f5e9', color: '#2e7d32', fontWeight: 500 }}>
                    {ds?.label || ds?.path || dsId}
                    <button onClick={() => _toggleDs(dsId)} style={{ border: 'none', background: 'none', cursor: 'pointer', fontSize: 11, color: '#2e7d32', padding: 0, lineHeight: 1 }}>x</button>
                  </span>
                );
              })}
              {attachedFdsIds.map(fdsId => {
                const fds = wsFeatureDataSources.find(d => d.id === fdsId);
                return (
                  <span key={fdsId} style={{ display: 'inline-flex', alignItems: 'center', gap: 4, padding: '2px 8px', borderRadius: 12, fontSize: 11, background: '#f3e5f5', color: '#7b1fa2', fontWeight: 500 }}>
                    <span style={{ fontSize: 12 }}>{fds ? getPageIcon(`feature.${fds.featureCode}`) || '\uD83D\uDDC3\uFE0F' : '\uD83D\uDDC3\uFE0F'}</span>
                    {fds?.label || fdsId}
                    <button onClick={() => _toggleFds(fdsId)} style={{ border: 'none', background: 'none', cursor: 'pointer', fontSize: 11, color: '#7b1fa2', padding: 0, lineHeight: 1 }}>x</button>
                  </span>
                );
              })}
            </div>
          )}

          <div className={styles.textInputRow}>
            <textarea
              ref={inputRef}
              className={styles.textInput}
              placeholder={t('Nachricht eingeben')}
              value={coach.inputValue}
              onChange={e => coach.setInputValue(e.target.value)}
              onKeyDown={handleKeyDown}
              onDragOver={_handleInputDragOver}
              onDrop={_handleInputDrop}
              rows={1}
              disabled={coach.isStreaming}
            />
            <button
              className={styles.sendBtn}
              onClick={handleSend}
              disabled={coach.isStreaming || !coach.inputValue.trim()}
            >
              {t('Senden')}
            </button>
          </div>
        </div>
      </div>
    </div>
  );
};
