/**
 * CommCoach Dossier View (Main View)
 *
 * Unified view per context: Coaching session, Tasks, Sessions history, Scores.
 * Voice first, always with text fallback.
 * Files & Sources are provided via the shared UnifiedDataBar sidebar.
 */

import React, { useState, useRef, useCallback, useEffect } from 'react';
import { useCommcoach } from '../../../hooks/useCommcoach';
import { type TtsEvent } from '../../../hooks/useTtsPlayback';
import { useApiRequest } from '../../../hooks/useApi';
import { useInstanceId, useMandateId } from '../../../hooks/useCurrentInstance';
import {
  getDossierExportUrl, getSessionExportUrl,
  getScoreHistoryApi, getPersonasApi,
  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 } from '../../../components/UnifiedDataBar';
import { ProviderMultiSelect, _defaultProviderSelection } from '../../../components/ProviderSelector';
import type { ProviderSelection } from '../../../components/ProviderSelector';
import { getPageIcon } from '../../../config/pageRegistry';
import styles from './CommcoachDossierView.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;
}

type TabKey = 'coaching' | 'tasks' | 'sessions' | 'scores';

interface CommcoachDossierViewProps {
  persistentInstanceId?: string;
  persistentMandateId?: string;
}

export const CommcoachDossierView: React.FC<CommcoachDossierViewProps> = ({ persistentInstanceId,
  persistentMandateId,
}) => {
  const { t } = useLanguage();
  const _toolPayloadForDisplay = (payload: Record<string, unknown>): string => {
    const formatted = _formatToolPayload(payload);
    return formatted === '[unlesbar]' ? t('[unlesbar]') : formatted;
  };
  const routeInstanceId = useInstanceId();
  const routeMandateId = useMandateId();
  const instanceId = persistentInstanceId || routeInstanceId;
  const mandateId = persistentMandateId || routeMandateId;
  const coach = useCommcoach(instanceId);
  const { request } = useApiRequest();

  const [activeTab, setActiveTab] = useState<TabKey>('coaching');
  const [showNewContext, setShowNewContext] = useState(false);
  const [newTitle, setNewTitle] = useState('');
  const [newDescription, setNewDescription] = useState('');
  const [newCategory, setNewCategory] = useState('custom');
  const [udbCollapsed, setUdbCollapsed] = useState(false);
  const [udbTab, setUdbTab] = useState<UdbTab>('files');

  const [newTaskTitle, setNewTaskTitle] = useState('');
  const [scoreHistory, setScoreHistory] = useState<Record<string, Array<{ score: number; createdAt?: string }>>>({});
  const [personas, setPersonas] = useState<CoachingPersona[]>([]);
  const [selectedPersonaId, setSelectedPersonaId] = useState<string | undefined>(undefined);

  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 [showSourcePicker, setShowSourcePicker] = useState(false);
  const [showFilePicker, setShowFilePicker] = useState(false);
  const [showAgentActivity, setShowAgentActivity] = useState(true);

  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 first context
  useEffect(() => {
    if (!coach.selectedContextId && coach.contexts.length > 0) {
      coach.selectContext(coach.contexts[0].id, { skipSessionResume: true });
    }
  }, [coach.contexts, coach.selectedContextId, coach.selectContext]);

  // Load scores, personas when context changes
  useEffect(() => {
    if (!instanceId || !coach.selectedContextId) return;
    getScoreHistoryApi(request, instanceId, coach.selectedContextId)
      .then(h => setScoreHistory(h))
      .catch(() => {});
  }, [instanceId, request, coach.selectedContextId]);

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

  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 _handleFileUploaded = () => _refreshWorkspaceAssets();
    window.addEventListener('fileUploaded', _handleFileUploaded);
    return () => window.removeEventListener('fileUploaded', _handleFileUploaded);
  }, [_refreshWorkspaceAssets]);

  useEffect(() => {
    if (activeTab !== 'coaching' || !coach.session) {
      voice.deactivate();
    } else if (voice.state === 'idle') {
      voice.activate();
    }
  }, [activeTab, 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 _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 handleKeyDown = useCallback((e: React.KeyboardEvent) => {
    if (e.key === 'Enter' && !e.shiftKey) { e.preventDefault(); handleSend(); }
  }, [handleSend]);

  const handleCreateContext = useCallback(async () => {
    if (!newTitle.trim()) return;
    await coach.createContext(newTitle, newDescription || undefined, newCategory);
    setNewTitle('');
    setNewDescription('');
    setNewCategory('custom');
    setShowNewContext(false);
  }, [newTitle, newDescription, newCategory, coach]);

  const handleSelectContext = useCallback((contextId: string) => {
    coach.selectContext(contextId, { skipSessionResume: true });
  }, [coach]);

  const handleAddTask = useCallback(async () => {
    if (!newTaskTitle.trim()) return;
    await coach.addTask(newTaskTitle);
    setNewTaskTitle('');
  }, [newTaskTitle, coach]);

  if (coach.loadingContexts) {
    return <div className={styles.empty}><p>{t('lade')}</p></div>;
  }

  return (
    <div className={styles.dossierLayout}>
      {/* UDB Sidebar */}
      {_udbContext && (
        <div className={`${styles.udbSidebar} ${udbCollapsed ? styles.udbSidebarCollapsed : ''}`}>
          <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']}
            />
          )}
        </div>
      )}

      {/* Main Content */}
      <div className={styles.dossier}>
      {/* Context Selector */}
      <div className={styles.contextSelector}>
        {coach.contexts.map(ctx => (
          <button
            key={ctx.id}
            className={`${styles.contextChip} ${ctx.id === coach.selectedContextId ? styles.contextChipActive : ''}`}
            onClick={() => handleSelectContext(ctx.id)}
          >
            <span className={styles.contextChipIcon}>{_categoryIcon(ctx.category)}</span>
            {ctx.title}
          </button>
        ))}
        <button
          className={styles.contextChipNew}
          onClick={() => setShowNewContext(!showNewContext)}
          title={t('Neues Thema')}
        >
          +
        </button>
      </div>

      {/* New Context Form */}
      {showNewContext && (
        <div className={styles.newContextForm}>
          <input
            className={styles.newContextInput}
            placeholder={t('Thema Titel')}
            value={newTitle}
            onChange={e => setNewTitle(e.target.value)}
            onKeyDown={e => e.key === 'Enter' && handleCreateContext()}
            autoFocus
          />
          <input
            className={styles.newContextInput}
            placeholder={t('Beschreibung (optional)')}
            value={newDescription}
            onChange={e => setNewDescription(e.target.value)}
          />
          <select className={styles.newContextInput} value={newCategory} onChange={e => setNewCategory(e.target.value)}>
            <option value="custom">Individuell</option>
            <option value="leadership">{t('Führung')}</option>
            <option value="conflict">Konflikt</option>
            <option value="negotiation">Verhandlung</option>
            <option value="presentation">{t('Präsentation')}</option>
            <option value="feedback">Feedback</option>
            <option value="delegation">Delegation</option>
            <option value="changeManagement">{t('Change Management')}</option>
          </select>
          <div className={styles.newContextActions}>
            <button className={styles.btnPrimary} onClick={handleCreateContext} disabled={!newTitle.trim() || !!coach.actionLoading}>
              {coach.actionLoading === 'creating' ? t('wird erstellt') : t('erstellen')}
            </button>
            <button className={styles.btnSecondary} onClick={() => setShowNewContext(false)}>{t('Abbrechen')}</button>
          </div>
        </div>
      )}

      {/* No context selected */}
      {!coach.selectedContextId && !showNewContext && coach.contexts.length === 0 && (
        <div className={styles.empty}>
          <h3>{t('Willkommen beim Kommunikationscoach')}</h3>
          <p>{t('Erstelle ein Thema, um zu')}</p>
          <button className={styles.btnPrimary} onClick={() => setShowNewContext(true)}>{t('Neues Thema erstellen')}</button>
        </div>
      )}

      {coach.selectedContextId && (<>
        {/* Context Header */}
        <div className={styles.header}>
          <div>
            <h2 className={styles.title}>{coach.selectedContext?.title}</h2>
            {coach.selectedContext?.description && (
              <p className={styles.description}>{coach.selectedContext.description}</p>
            )}
          </div>
          <div className={styles.headerActions}>
            {instanceId && (
              <>
                <a className={styles.btnExport} href={getDossierExportUrl(instanceId, coach.selectedContextId, 'md')} target="_blank" rel="noopener noreferrer">{t('Export MD')}</a>
                <a className={styles.btnExport} href={getDossierExportUrl(instanceId, coach.selectedContextId, 'pdf')} target="_blank" rel="noopener noreferrer">{t('Export PDF')}</a>
              </>
            )}
            <button className={styles.btnArchive} onClick={() => coach.archiveContext(coach.selectedContextId!)} disabled={!!coach.actionLoading}>
              {coach.actionLoading === 'archiving' ? t('wird archiviert') : t('archivieren')}
            </button>
          </div>
        </div>

        {/* Tab Navigation */}
        <div className={styles.tabs}>
          {(['coaching', 'tasks', 'sessions', 'scores'] as TabKey[]).map(tab => (
            <button
              key={tab}
              className={`${styles.tab} ${activeTab === tab ? styles.tabActive : ''}`}
              onClick={() => setActiveTab(tab)}
            >
              {_tabLabel(tab, coach, t)}
            </button>
          ))}
        </div>

        {/* ============================================================ */}
        {/* COACHING TAB */}
        {/* ============================================================ */}
        {activeTab === 'coaching' && (
          <div className={styles.coachingTab}>
            {!coach.session ? (
              <div className={styles.sessionStart}>
                <p>{t('Starte eine neue Coachingsession zu')}</p>
                {personas.length > 0 && (
                  <div className={styles.personaSelector}>
                    <label className={styles.personaLabel}>{t('Gesprächspartner wählen')}</label>
                    <div className={styles.personaGrid}>
                      {personas.map(p => (
                        <button
                          key={p.id}
                          className={`${styles.personaChip} ${selectedPersonaId === p.id ? styles.personaChipActive : ''}`}
                          onClick={() => setSelectedPersonaId(selectedPersonaId === p.id ? undefined : p.id)}
                          title={p.description}
                        >
                          <span className={styles.personaGender}>{p.gender === 'f' ? '\u2640' : p.gender === 'm' ? '\u2642' : '\u25CB'}</span>
                          <span>{p.label}</span>
                        </button>
                      ))}
                    </div>
                  </div>
                )}
                <button className={styles.btnPrimary} onClick={() => coach.startSession(selectedPersonaId)} disabled={!!coach.actionLoading}>
                  {coach.actionLoading === 'starting'
                    ? 'Wird gestartet...'
                    : selectedPersonaId && personas.find(p => p.id === selectedPersonaId)
                      ? `Session starten mit ${personas.find(p => p.id === selectedPersonaId)!.label}`
                      : 'Session starten'}
                </button>
              </div>
            ) : (
              <>
                {/* Session Header */}
                <div className={styles.sessionHeader}>
                  <span className={styles.sessionLabel}>{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}>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('abschließen')}
                    </button>
                    <button className={styles.btnSmallDanger} onClick={coach.cancelSession} disabled={!!coach.actionLoading}>
                      {coach.actionLoading === 'cancelling' ? t('wird abgebrochen') : t('Abbrechen')}
                    </button>
                  </div>
                </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 || 'Coach denkt nach'}<span className={styles.typingDots}>...</span></div>
                          )}
                        </div>
                      </div>
                    )}
                  </div>
                </AutoScroll>

                {(coach.isStreaming || coach.agentToolCalls.length > 0) && (
                  <div className={styles.agentActivityPanel}>
                    <button
                      className={styles.agentActivityHeader}
                      onClick={() => setShowAgentActivity(prev => !prev)}
                      type="button"
                    >
                      <span className={styles.agentActivityTitle}>
                        Agent-Aktivität
                        {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 ? '▾' : '▸'}</span>
                    </button>
                    {showAgentActivity && (
                      <div className={styles.agentActivityBody}>
                        {coach.agentToolCalls.length === 0 ? (
                          <div className={styles.agentActivityEmpty}>
                            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('läuft')}
                                </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}>
                  <div className={styles.voiceStatus}>
                    <span className={`${styles.voiceIndicator} ${voice.state === 'listening' ? styles.voiceActive : ''}`}>
                      {voice.muted
                        ? 'Stumm – Mikrofon aus'
                        : voice.state === 'botSpeaking'
                          ? (coach.streamingStatus || 'Coach spricht...')
                          : coach.isStreaming
                            ? (coach.streamingStatus || 'Coach denkt nach...')
                            : voice.state === 'interrupted'
                              ? 'Unterbrochen – Mikrofon an'
                              : voice.state === 'listening'
                                ? (voice.liveTranscript ? 'Spricht...' : 'Mikrofon an – bitte sprechen')
                                : '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);
                        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,
                          }}>
                            {file?.fileName || fId}
                            <button onClick={() => _toggleFile(fId)} style={{ border: 'none', background: 'none', cursor: 'pointer', fontSize: 11, color: '#1565c0', padding: 0, lineHeight: 1 }}>×</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 }}>×</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 }}>×</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}
                      rows={1}
                      disabled={coach.isStreaming}
                    />

                    {/* File Picker */}
                    {wsFiles.length > 0 && (
                      <div style={{ position: 'relative' }}>
                        <button
                          onClick={() => { setShowFilePicker(v => !v); setShowSourcePicker(false); }}
                          disabled={coach.isStreaming}
                          title={t('Datei anhängen')}
                          style={{
                            width: 36, height: 36, borderRadius: 8,
                            border: `1px solid ${attachedFileIds.length ? '#1565c0' : 'var(--border-color, #ddd)'}`,
                            background: attachedFileIds.length ? '#e3f2fd' : 'var(--secondary-bg, #f5f5f5)',
                            color: attachedFileIds.length ? '#1565c0' : '#666',
                            cursor: coach.isStreaming ? 'not-allowed' : 'pointer',
                            fontSize: 15, display: 'flex', alignItems: 'center', justifyContent: 'center',
                            opacity: coach.isStreaming ? 0.5 : 1, position: 'relative',
                          }}
                        >
                          +
                          {attachedFileIds.length > 0 && (
                            <span style={{ position: 'absolute', top: -4, right: -4, background: '#1565c0', color: '#fff', fontSize: 9, fontWeight: 700, borderRadius: '50%', width: 15, height: 15, display: 'flex', alignItems: 'center', justifyContent: 'center' }}>
                              {attachedFileIds.length}
                            </span>
                          )}
                        </button>
                        {showFilePicker && (
                          <div style={{
                            position: 'absolute', bottom: '100%', right: 0, marginBottom: 4,
                            background: 'var(--bg-card, #fff)', border: '1px solid var(--border-color, #e0e0e0)',
                            borderRadius: 8, boxShadow: '0 -2px 8px rgba(0,0,0,0.1)', zIndex: 20,
                            minWidth: 220, maxHeight: 240, overflowY: 'auto',
                          }}>
                            <div style={{ padding: '6px 12px', fontSize: 11, color: '#999', fontWeight: 600, borderBottom: '1px solid #f0f0f0' }}>{t('Dateien anhängen')}</div>
                            {wsFiles.map(f => {
                              const sel = attachedFileIds.includes(f.id);
                              return (
                                <div key={f.id} onClick={() => _toggleFile(f.id)} style={{
                                  padding: '6px 12px', cursor: 'pointer', fontSize: 12,
                                  display: 'flex', alignItems: 'center', gap: 8,
                                  background: sel ? '#e3f2fd' : 'transparent',
                                }}
                                  onMouseEnter={e => { if (!sel) e.currentTarget.style.background = '#f5f5f5'; }}
                                  onMouseLeave={e => { if (!sel) e.currentTarget.style.background = ''; }}
                                >
                                  <span style={{ width: 14, height: 14, borderRadius: 3, border: sel ? '2px solid #1565c0' : '2px solid #ccc', background: sel ? '#1565c0' : 'transparent', display: 'flex', alignItems: 'center', justifyContent: 'center', color: '#fff', fontSize: 9, fontWeight: 700, flexShrink: 0 }}>
                                    {sel ? '✓' : ''}
                                  </span>
                                  <span style={{ overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' }}>{f.fileName}</span>
                                </div>
                              );
                            })}
                          </div>
                        )}
                      </div>
                    )}

                    {/* Source Picker */}
                    {(wsDataSources.length > 0 || wsFeatureDataSources.length > 0) && (
                      <div style={{ position: 'relative' }}>
                        <button
                          onClick={() => { setShowSourcePicker(v => !v); setShowFilePicker(false); }}
                          disabled={coach.isStreaming}
                          title={t('Datenquellen anhängen')}
                          style={{
                            width: 36, height: 36, borderRadius: 8,
                            border: `1px solid ${(attachedDsIds.length + attachedFdsIds.length) ? '#2e7d32' : 'var(--border-color, #ddd)'}`,
                            background: (attachedDsIds.length + attachedFdsIds.length) ? '#e8f5e9' : 'var(--secondary-bg, #f5f5f5)',
                            color: (attachedDsIds.length + attachedFdsIds.length) ? '#2e7d32' : '#666',
                            cursor: coach.isStreaming ? 'not-allowed' : 'pointer',
                            fontSize: 14, display: 'flex', alignItems: 'center', justifyContent: 'center',
                            opacity: coach.isStreaming ? 0.5 : 1, position: 'relative',
                          }}
                        >
                          &#128279;
                          {(attachedDsIds.length + attachedFdsIds.length) > 0 && (
                            <span style={{ position: 'absolute', top: -4, right: -4, background: '#2e7d32', color: '#fff', fontSize: 9, fontWeight: 700, borderRadius: '50%', width: 15, height: 15, display: 'flex', alignItems: 'center', justifyContent: 'center' }}>
                              {attachedDsIds.length + attachedFdsIds.length}
                            </span>
                          )}
                        </button>
                        {showSourcePicker && (
                          <div style={{
                            position: 'absolute', bottom: '100%', right: 0, marginBottom: 4,
                            background: 'var(--bg-card, #fff)', border: '1px solid var(--border-color, #e0e0e0)',
                            borderRadius: 8, boxShadow: '0 -2px 8px rgba(0,0,0,0.1)', zIndex: 20,
                            minWidth: 240, maxHeight: 260, overflowY: 'auto',
                          }}>
                            {wsDataSources.length > 0 && (
                              <>
                                <div style={{ padding: '6px 12px', fontSize: 11, color: '#999', fontWeight: 600, borderBottom: '1px solid #f0f0f0' }}>{t('Persönliche Quellen')}</div>
                                {wsDataSources.map(ds => {
                                  const sel = attachedDsIds.includes(ds.id);
                                  return (
                                    <div key={ds.id} onClick={() => _toggleDs(ds.id)} style={{
                                      padding: '6px 12px', cursor: 'pointer', fontSize: 12,
                                      display: 'flex', alignItems: 'center', gap: 8,
                                      background: sel ? '#e8f5e9' : 'transparent',
                                    }}
                                      onMouseEnter={e => { if (!sel) e.currentTarget.style.background = '#f5f5f5'; }}
                                      onMouseLeave={e => { if (!sel) e.currentTarget.style.background = ''; }}
                                    >
                                      <span style={{ width: 14, height: 14, borderRadius: 3, border: sel ? '2px solid #2e7d32' : '2px solid #ccc', background: sel ? '#2e7d32' : 'transparent', display: 'flex', alignItems: 'center', justifyContent: 'center', color: '#fff', fontSize: 9, fontWeight: 700, flexShrink: 0 }}>
                                        {sel ? '✓' : ''}
                                      </span>
                                      <span style={{ overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' }}>{ds.label || ds.path}</span>
                                    </div>
                                  );
                                })}
                              </>
                            )}
                            {wsFeatureDataSources.length > 0 && (
                              <>
                                <div style={{ padding: '6px 12px', fontSize: 11, color: '#999', fontWeight: 600, borderTop: wsDataSources.length ? '1px solid #f0f0f0' : 'none', borderBottom: '1px solid #f0f0f0' }}>Feature-Datenquellen</div>
                                {wsFeatureDataSources.map(fds => {
                                  const sel = attachedFdsIds.includes(fds.id);
                                  return (
                                    <div key={fds.id} onClick={() => _toggleFds(fds.id)} style={{
                                      padding: '6px 12px', cursor: 'pointer', fontSize: 12,
                                      display: 'flex', alignItems: 'center', gap: 8,
                                      background: sel ? '#f3e5f5' : 'transparent',
                                    }}
                                      onMouseEnter={e => { if (!sel) e.currentTarget.style.background = '#f5f5f5'; }}
                                      onMouseLeave={e => { if (!sel) e.currentTarget.style.background = ''; }}
                                    >
                                      <span style={{ width: 14, height: 14, borderRadius: 3, border: sel ? '2px solid #7b1fa2' : '2px solid #ccc', background: sel ? '#7b1fa2' : 'transparent', display: 'flex', alignItems: 'center', justifyContent: 'center', color: '#fff', fontSize: 9, fontWeight: 700, flexShrink: 0 }}>
                                        {sel ? '✓' : ''}
                                      </span>
                                      <span style={{ display: 'flex', alignItems: 'center', fontSize: 12, color: '#7b1fa2', flexShrink: 0 }}>{getPageIcon(`feature.${fds.featureCode}`) || '\uD83D\uDDC3\uFE0F'}</span>
                                      <span style={{ overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' }}>{fds.label} – {fds.tableName}</span>
                                    </div>
                                  );
                                })}
                              </>
                            )}
                          </div>
                        )}
                      </div>
                    )}

                    {/* Provider Selector */}
                    <ProviderMultiSelect
                      selection={providerSelection}
                      onChange={setProviderSelection}
                      showLabel={false}
                      disabled={coach.isStreaming}
                    />

                    <button className={styles.sendBtn} onClick={handleSend} disabled={!coach.inputValue.trim() || coach.isStreaming}>
                      Senden
                    </button>
                  </div>
                </div>
              </>
            )}
            {coach.error && <div className={styles.errorBanner}>{coach.error}</div>}
          </div>
        )}

        {/* ============================================================ */}
        {/* TASKS TAB */}
        {/* ============================================================ */}
        {activeTab === 'tasks' && (
          <div className={styles.tabContent}>
            <div className={styles.addTaskRow}>
              <input
                className={styles.addTaskInput}
                placeholder={t('Neue Aufgabe')}
                value={newTaskTitle}
                onChange={e => setNewTaskTitle(e.target.value)}
                onKeyDown={e => e.key === 'Enter' && handleAddTask()}
              />
              <button className={styles.addTaskBtn} onClick={handleAddTask} disabled={!newTaskTitle.trim() || !!coach.actionLoading}>
                {coach.actionLoading === 'addingTask' ? t('wird hinzugefügt') : t('hinzufügen')}
              </button>
            </div>
            {coach.tasks.length === 0 ? (
              <div className={styles.emptyTab}>{t('Noch keine Aufgaben der Coach')}</div>
            ) : (
              <div className={styles.taskList}>
                {coach.tasks.map(task => (
                  <div key={task.id} className={`${styles.taskItem} ${task.status === 'done' ? styles.taskDone : ''}`}>
                    <button className={styles.taskCheck} onClick={() => coach.toggleTaskStatus(task.id, task.status)}>
                      {task.status === 'done' ? '\u2713' : '\u25CB'}
                    </button>
                    <div className={styles.taskContent}>
                      <div className={styles.taskTitle}>{task.title}</div>
                      {task.description && <div className={styles.taskDesc}>{task.description}</div>}
                    </div>
                    <div className={styles.taskMeta}>
                      <span className={`${styles.taskPriority} ${styles[`priority_${task.priority}`]}`}>{task.priority}</span>
                    </div>
                    <button className={styles.taskDelete} onClick={() => coach.removeTask(task.id)}>x</button>
                  </div>
                ))}
              </div>
            )}
          </div>
        )}

        {/* ============================================================ */}
        {/* SESSIONS TAB */}
        {/* ============================================================ */}
        {activeTab === 'sessions' && (
          <div className={styles.tabContent}>
            {coach.sessions.length === 0 ? (
              <div className={styles.emptyTab}>{t('Noch keine abgeschlossenen Sessions')}</div>
            ) : (
              <div className={styles.sessionTimeline}>
                {coach.sessions.map(s => (
                  <div key={s.id} className={styles.sessionItem}>
                    <div className={styles.sessionItemHeader}>
                      <span className={`${styles.sessionStatus} ${styles[`status_${s.status}`]}`}>
                        {s.status === 'completed' ? 'Abgeschlossen' : s.status === 'active' ? t('aktiv') : t('Abgebrochen')}
                      </span>
                      <span className={styles.sessionDate}>{s.startedAt ? new Date(s.startedAt).toLocaleDateString('de-CH') : ''}</span>
                      {s.competenceScore != null && <span className={styles.sessionScore}>Score: {Math.round(s.competenceScore)}</span>}
                    </div>
                    {s.summary && (
                      <div className={styles.sessionSummary}><ReactMarkdown>{s.summary}</ReactMarkdown></div>
                    )}
                    <div className={styles.sessionMeta}>
                      {s.messageCount} Nachrichten | {Math.round(s.durationSeconds / 60)} Min.
                      {s.personaId && <span> {t('Persona')}</span>}
                      {instanceId && s.status === 'completed' && (
                        <a className={styles.sessionExport} href={getSessionExportUrl(instanceId, s.id, 'md')} target="_blank" rel="noopener noreferrer" onClick={e => e.stopPropagation()}>Export</a>
                      )}
                    </div>
                  </div>
                ))}
              </div>
            )}
          </div>
        )}

        {/* ============================================================ */}
        {/* SCORES TAB */}
        {/* ============================================================ */}
        {activeTab === 'scores' && (
          <div className={styles.tabContent}>
            {coach.scores.length === 0 ? (
              <div className={styles.emptyTab}>{t('Noch keine Bewertungen, schließe eine')}</div>
            ) : (
              <div className={styles.scoreList}>
                {_groupScoresByDimension(coach.scores).map(group => (
                  <div key={group.dimension} className={styles.scoreGroup}>
                    <div className={styles.scoreDimension}>
                      <span className={styles.scoreDimensionLabel}>{_dimensionLabel(group.dimension, t)}</span>
                      <span className={styles.scoreLatest}>{Math.round(group.latest.score)}/100</span>
                      <span className={`${styles.scoreTrend} ${styles[`trend_${group.latest.trend}`]}`}>
                        {group.latest.trend === 'improving' ? 'steigend' : group.latest.trend === 'declining' ? 'sinkend' : 'stabil'}
                      </span>
                    </div>
                    <div className={styles.scoreBar}><div className={styles.scoreBarFill} style={{ width: `${group.latest.score}%` }} /></div>
                    {group.latest.evidence && <div className={styles.scoreEvidence}>{group.latest.evidence}</div>}
                    {scoreHistory[group.dimension] && scoreHistory[group.dimension].length > 1 && (
                      <div className={styles.scoreHistory}>
                        <div className={styles.scoreHistoryLabel}>Verlauf:</div>
                        <div className={styles.scoreHistoryPoints}>
                          {scoreHistory[group.dimension].map((entry, i) => (
                            <span key={i} className={styles.scoreHistoryPoint} title={entry.createdAt || ''}>{Math.round(entry.score)}</span>
                          ))}
                        </div>
                      </div>
                    )}
                  </div>
                ))}
              </div>
            )}
          </div>
        )}

      </>)}


    </div>
    </div>
  );
};

function _categoryIcon(category: string): string {
  const icons: Record<string, string> = {
    leadership: 'L', conflict: 'K', negotiation: 'V',
    presentation: 'P', feedback: 'F', delegation: 'D',
    changeManagement: 'C', custom: '*',
  };
  return icons[category] || '*';
}

function _tabLabel(tab: TabKey, coach: any, t: (key: string) => string): string {
  switch (tab) {
    case 'coaching': return coach.session ? t('Coaching aktiv') : t('Coaching');
    case 'tasks': return `${t('Aufgaben')} (${coach.tasks.length})`;
    case 'sessions': return `Sessions (${coach.sessions.length})`;
    case 'scores': return `${t('Bewertungen')} (${coach.scores.length})`;
  }
}

interface ScoreGroup {
  dimension: string;
  latest: { score: number; trend: string; evidence?: string; createdAt?: string };
  history: Array<{ score: number; createdAt?: string }>;
}

function _groupScoresByDimension(scores: any[]): ScoreGroup[] {
  const groups: Record<string, ScoreGroup> = {};
  for (const s of scores) {
    const dim = s.dimension;
    if (!groups[dim]) groups[dim] = { dimension: dim, latest: s, history: [] };
    groups[dim].history.push({ score: s.score, createdAt: s.createdAt });
    if (s.createdAt > (groups[dim].latest.createdAt || '')) groups[dim].latest = s;
  }
  return Object.values(groups);
}

function _dimensionLabel(dim: string, t: (k: string) => string): string {
  switch (dim) {
    case 'empathy': return t('Einfühlungsvermögen');
    case 'clarity': return t('Klarheit');
    case 'assertiveness': return t('Durchsetzung');
    case 'listening': return t('Zuhören');
    case 'selfReflection': return t('Selbstreflexion');
    default: return dim;
  }
}

function _formatToolPayload(payload: Record<string, unknown>): string {
  try {
    const serialized = JSON.stringify(payload);
    if (!serialized) return '';
    return serialized.length > 180 ? `${serialized.slice(0, 177)}...` : serialized;
  } catch {
    return '[unlesbar]';
  }
}

export default CommcoachDossierView;
