import React, { useState, useEffect, useRef, useCallback, useMemo } from 'react';
import { useSearchParams } from 'react-router-dom';
import { useCurrentInstance } from '../../../hooks/useCurrentInstance';
import * as teamsbotApi from '../../../api/teamsbotApi';
import type { TeamsbotSession, TeamsbotTranscript, TeamsbotBotResponse, TeamsbotSSEEvent, ScreenshotInfo } from '../../../api/teamsbotApi';
import { getUserDataCache } from '../../../utils/userCache';
import styles from './Teamsbot.module.css';

/**
 * TeamsbotSessionView - Live session view with real-time transcript and bot responses.
 */
export const TeamsbotSessionView: React.FC = () => {
  const { instance } = useCurrentInstance();
  const instanceId = instance?.id || '';
  const [searchParams, setSearchParams] = useSearchParams();
  const sessionId = searchParams.get('sessionId') || '';

  const cachedUser = getUserDataCache();
  const _isSysAdmin = cachedUser?.isSysAdmin === true;

  const [session, setSession] = useState<TeamsbotSession | null>(null);
  const [allSessions, setAllSessions] = useState<TeamsbotSession[]>([]);
  const [transcripts, setTranscripts] = useState<TeamsbotTranscript[]>([]);
  const [botResponses, setBotResponses] = useState<TeamsbotBotResponse[]>([]);
  const [loading, setLoading] = useState(true);
  const [noSessions, setNoSessions] = useState(false);
  const [error, setError] = useState<string | null>(null);
  const [isLive, setIsLive] = useState(false);

  const [screenshots, setScreenshots] = useState<ScreenshotInfo[]>([]);
  const [screenshotsLoading, setScreenshotsLoading] = useState(false);
  const [screenshotsLoaded, setScreenshotsLoaded] = useState(false);
  const [ttsStatusEvents, setTtsStatusEvents] = useState<Array<{
    status: string;
    message?: string;
    hasWebSocket?: boolean;
    timestamp: string;
  }>>([]);

  const transcriptEndRef = useRef<HTMLDivElement>(null);
  const eventSourceRef = useRef<EventSource | null>(null);

  const debugLogsRef = useRef<string[]>([]);
  const [debugVisible, setDebugVisible] = useState(false);
  const [debugSnapshot, setDebugSnapshot] = useState<string[]>([]);
  const _dlog = useCallback((tag: string, info?: string) => {
    const t = new Date();
    const ts = `${t.getMinutes()}:${String(t.getSeconds()).padStart(2, '0')}.${String(t.getMilliseconds()).padStart(3, '0')}`;
    const entry = `[${ts}] ${tag}${info ? ' ' + info : ''}`;
    debugLogsRef.current.push(entry);
    if (debugLogsRef.current.length > 120) debugLogsRef.current.shift();
  }, []);

  // Load session data - if no sessionId given, load the most recent session
  const _loadSession = useCallback(async () => {
    if (!instanceId) return;
    try {
      setLoading(true);
      setNoSessions(false);

      // Always load the full session list for the switcher
      const listResult = await teamsbotApi.listSessions(instanceId, true);
      const sessions = listResult.sessions || [];
      setAllSessions(sessions);

      let targetSessionId = sessionId;

      // No sessionId in URL -> find the most recent active or latest session
      if (!targetSessionId) {
        if (sessions.length === 0) {
          setNoSessions(true);
          setLoading(false);
          return;
        }
        // Prefer active sessions, then most recent
        const activeSession = sessions.find(s => ['active', 'joining', 'pending'].includes(s.status));
        targetSessionId = activeSession ? activeSession.id : sessions[0].id;
        setSearchParams({ sessionId: targetSessionId }, { replace: true });
      }

      const result = await teamsbotApi.getSession(instanceId, targetSessionId);
      setSession(result.session);
      setTranscripts(result.transcripts || []);
      setBotResponses(result.botResponses || []);
      setError(null);
    } catch (err: any) {
      setError(err.message || 'Fehler beim Laden der Sitzung');
    } finally {
      setLoading(false);
    }
  }, [instanceId, sessionId, setSearchParams]);

  useEffect(() => {
    _loadSession();
  }, [_loadSession]);

  // SSE Live Stream - connect once per session, don't re-create on status changes
  const sseSessionRef = useRef<string | null>(null);
  const sessionStatus = session?.status;
  useEffect(() => {
    if (!instanceId || !sessionId || !sessionStatus) return;
    if (!['active', 'joining', 'pending'].includes(sessionStatus)) return;
    // Avoid reconnecting if already streaming this session
    if (sseSessionRef.current === sessionId && eventSourceRef.current) return;

    eventSourceRef.current?.close();
    sseSessionRef.current = sessionId;

    const eventSource = teamsbotApi.createSessionStream(instanceId, sessionId);
    eventSourceRef.current = eventSource;
    setIsLive(true);
    _dlog('SSE', 'connected');

    eventSource.onmessage = (event) => {
      try {
        const sseEvent: TeamsbotSSEEvent = JSON.parse(event.data);
        const evType = sseEvent.type || 'unknown';

        _dlog('SSE', evType + (sseEvent.data ? ` ${JSON.stringify(sseEvent.data).substring(0, 80)}` : ''));

        switch (evType) {
          case 'sessionState':
            if (sseEvent.data) setSession(prev => prev ? { ...prev, ...sseEvent.data } : sseEvent.data);
            break;

          case 'transcript': {
            const t = sseEvent.data as TeamsbotTranscript;
            _dlog('TRANSCRIPT', `[${t?.speaker || '?'}] ${(t?.text || '').substring(0, 50)}...`);
            if (t?.isContinuation && t?.id) {
              setTranscripts(prev => {
                const idx = prev.findIndex(x => x.id === t.id);
                if (idx >= 0) {
                  const updated = [...prev];
                  updated[idx] = { ...updated[idx], ...t };
                  return updated;
                }
                return [...prev, t];
              });
            } else {
              setTranscripts(prev => [...prev, t]);
            }
            break;
          }

          case 'botResponse':
            setBotResponses(prev => [...prev, sseEvent.data as TeamsbotBotResponse]);
            break;

          case 'statusChange':
            setSession(prev => prev ? { ...prev, status: sseEvent.data.status } : null);
            if (['ended', 'error'].includes(sseEvent.data.status)) {
              setIsLive(false);
              eventSource.close();
              eventSourceRef.current = null;
              sseSessionRef.current = null;
              teamsbotApi.getSession(instanceId, sessionId).then((result) => {
                setSession(result.session);
                if (result.transcripts) setTranscripts(result.transcripts);
                if (result.botResponses) setBotResponses(result.botResponses);
              }).catch(() => {});
            }
            break;

          case 'analysis':
            break;

          case 'ttsDeliveryStatus': {
            const payload = sseEvent.data || {};
            setTtsStatusEvents((prev) => [
              ...prev.slice(-24),
              {
                status: payload.status || 'unknown',
                message: payload.message,
                hasWebSocket: payload.hasWebSocket,
                timestamp: payload.timestamp || new Date().toISOString(),
              },
            ]);
            break;
          }

          case 'chatSendFailed': {
            const failData = sseEvent.data || {};
            const failMsg = `Chat-Nachricht konnte nicht gesendet werden: ${failData.reason || 'unbekannt'}`;
            _dlog('CHAT-FAIL', failMsg);
            setTtsStatusEvents((prev) => [
              ...prev.slice(-24),
              {
                status: 'chat_failed',
                message: failMsg,
                hasWebSocket: false,
                timestamp: failData.timestamp || new Date().toISOString(),
              },
            ]);
            break;
          }

          case 'error': {
            const errData = sseEvent.data || {};
            const errMsg = errData.message || 'Unbekannter Fehler';
            _dlog('ERROR', errMsg);
            setError(errMsg);
            break;
          }

          case 'suggestedResponse':
            break;

          case 'ping':
            break;
        }
      } catch (err) {
        _dlog('SSE-ERR', String(err));
        console.error('SSE parse error:', err);
      }
    };

    eventSource.onerror = () => {
      setIsLive(false);
    };

    return () => {
      eventSource.close();
      eventSourceRef.current = null;
      sseSessionRef.current = null;
      setIsLive(false);
    };
  }, [instanceId, sessionId, sessionStatus, _dlog]);

  // Polling fallback: refresh session data every 5s when SSE is not connected
  const pollRef = useRef<ReturnType<typeof setInterval> | null>(null);
  const isActive = useMemo(() => session && ['pending', 'joining', 'active'].includes(session.status), [session]);
  useEffect(() => {
    if (instanceId && sessionId && (isActive || !session)) {
      pollRef.current = setInterval(async () => {
        if (isLive) return;
        try {
          const result = await teamsbotApi.getSession(instanceId, sessionId);
          setSession(result.session);
          if (result.transcripts) setTranscripts(result.transcripts);
          if (result.botResponses) setBotResponses(result.botResponses);
        } catch {}
      }, 5000);
    }
    return () => { if (pollRef.current) clearInterval(pollRef.current); };
  }, [isActive, instanceId, sessionId, isLive, session]);

  // Auto-scroll transcript
  useEffect(() => {
    transcriptEndRef.current?.scrollIntoView({ behavior: 'smooth' });
  }, [transcripts]);

  const _handleStop = async () => {
    if (!instanceId || !sessionId) return;
    try {
      await teamsbotApi.stopSession(instanceId, sessionId);
    } catch (err: any) {
      setError(err.message);
    }
  };

  const _formatTime = (timestamp: string) => {
    try {
      const dt = new Date(timestamp);
      if (!timestamp || Number.isNaN(dt.getTime())) return '';
      return dt.toLocaleTimeString('de-CH', { hour: '2-digit', minute: '2-digit', second: '2-digit' });
    } catch {
      return '';
    }
  };

  const _getSpeakerColor = (speaker: string) => {
    const colors = ['#4A90D9', '#D94A4A', '#4AD99A', '#D9A84A', '#9A4AD9', '#4AD9D9'];
    let hash = 0;
    for (let i = 0; i < speaker.length; i++) {
      hash = speaker.charCodeAt(i) + ((hash << 5) - hash);
    }
    return colors[Math.abs(hash) % colors.length];
  };

  if (loading) return <div className={styles.loading}>Lade Sitzung...</div>;
  if (noSessions) return (
    <div className={styles.emptyState || styles.loading}>
      <p>Keine Sitzungen vorhanden.</p>
      <p>Starte eine neue Sitzung im <strong>Dashboard</strong>.</p>
    </div>
  );
  if (!session) return <div className={styles.errorBanner}>Sitzung nicht gefunden</div>;

  const _switchSession = (newSessionId: string) => {
    setSearchParams({ sessionId: newSessionId });
  };

  return (
    <div className={styles.sessionContainer}>
      {/* Session Switcher (if multiple sessions exist) */}
      {allSessions.length > 1 && (
        <div style={{ display: 'flex', gap: '8px', marginBottom: '12px', flexWrap: 'wrap' }}>
          {allSessions.map((s) => (
            <button
              key={s.id}
              onClick={() => _switchSession(s.id)}
              style={{
                padding: '6px 12px',
                borderRadius: '6px',
                border: s.id === sessionId ? '2px solid #4A90D9' : '1px solid #ddd',
                background: s.id === sessionId ? '#EBF3FC' : '#fff',
                cursor: 'pointer',
                fontSize: '13px',
                fontWeight: s.id === sessionId ? 600 : 400,
              }}
            >
              {s.botName}
              {['active', 'joining', 'pending'].includes(s.status) && ' (aktiv)'}
              {s.status === 'ended' && ' (beendet)'}
            </button>
          ))}
        </div>
      )}

      {/* Session Header */}
      <div className={styles.sessionViewHeader}>
        <div className={styles.sessionInfo}>
          <h3 className={styles.sessionTitle}>{session.botName}</h3>
          <span className={`${styles.statusBadge} ${styles[`status${session.status.charAt(0).toUpperCase() + session.status.slice(1)}`] || ''}`}>
            {session.status}
          </span>
          {isLive && <span className={styles.liveBadge}>LIVE</span>}
        </div>
        <div className={styles.sessionControls}>
          {['active', 'joining', 'pending'].includes(session.status) && (
            <button className={styles.stopButton} onClick={_handleStop}>Sitzung beenden</button>
          )}
        </div>
      </div>

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

      {/* Main Content: Transcript + Responses */}
      <div className={styles.sessionContent}>
        {/* Left: Transcript */}
        <div className={styles.transcriptPanel}>
          <h4 className={styles.panelTitle}>Transkript ({transcripts.length} Segmente)</h4>
          <div className={styles.transcriptList}>
            {transcripts.map((t) => (
              <div key={t.id} className={styles.transcriptItem}>
                <span className={styles.transcriptTime}>{_formatTime(t.timestamp)}</span>
                <span
                  className={styles.transcriptSpeaker}
                  style={{ color: _getSpeakerColor(t.speaker || 'Unknown') }}
                >
                  {t.speaker || 'Unknown'}:
                </span>
                <span className={styles.transcriptText}>{t.text}</span>
              </div>
            ))}
            <div ref={transcriptEndRef} />
            {transcripts.length === 0 && (
              <div className={styles.emptyState}>Noch kein Transkript vorhanden.</div>
            )}
          </div>
        </div>

        {/* Right: Bot Responses */}
        <div className={styles.responsesPanel}>
          <h4 className={styles.panelTitle}>Bot-Antworten ({botResponses.length})</h4>
          <div className={styles.responseList}>
            {botResponses.map((r) => (
              <div key={r.id} className={styles.responseItem}>
                <div className={styles.responseHeader}>
                  <span className={styles.responseIntent}>{r.detectedIntent}</span>
                  <span className={styles.responseTime}>{_formatTime(r.timestamp || '')}</span>
                </div>
                <div className={styles.responseText}>{r.responseText}</div>
                {r.reasoning && (
                  <div className={styles.responseReasoning}>
                    <em>Reasoning: {r.reasoning}</em>
                  </div>
                )}
                {(r.modelName || r.processingTime != null) && (
                  <div className={styles.responseMeta}>
                    <span>{r.modelName || ''}</span>
                    {r.processingTime != null && <span>{r.processingTime.toFixed(1)}s</span>}
                    {r.priceCHF != null && <span>{r.priceCHF.toFixed(4)} CHF</span>}
                  </div>
                )}
              </div>
            ))}
            {botResponses.length === 0 && (
              <div className={styles.emptyState}>Noch keine Bot-Antworten.</div>
            )}
          </div>
        </div>
      </div>

      {/* Summary (for ended sessions) */}
      {session.summary && (
        <div className={styles.summaryCard}>
          <h4 className={styles.panelTitle}>Meeting-Zusammenfassung</h4>
          <div className={styles.summaryText}>{session.summary}</div>
        </div>
      )}

      {/* TTS Delivery Debug */}
      <div className={styles.summaryCard}>
        <h4 className={styles.panelTitle}>TTS Delivery Status</h4>
        {ttsStatusEvents.length === 0 ? (
          <div className={styles.emptyState}>Noch keine TTS-Events.</div>
        ) : (
          <div style={{ display: 'flex', flexDirection: 'column', gap: '6px' }}>
            {ttsStatusEvents.slice(-10).reverse().map((ev, idx) => (
              <div key={`${ev.timestamp}-${idx}`} className={styles.responseMeta}>
                <span>{_formatTime(ev.timestamp)}</span>
                <span>{ev.status}</span>
                <span>ws: {ev.hasWebSocket ? 'yes' : 'no'}</span>
                <span>{ev.message || ''}</span>
              </div>
            ))}
          </div>
        )}
      </div>

      {/* Debug Log (SSE/Transcript/Chat) */}
      <div style={{ position: 'fixed', bottom: 0, right: 0, zIndex: 9999 }}>
        <button
          onClick={() => { setDebugSnapshot([...debugLogsRef.current]); setDebugVisible(v => !v); }}
          style={{ background: '#333', color: '#0f0', border: 'none', padding: '4px 8px', fontSize: '10px', borderRadius: '4px 0 0 0' }}
        >
          DBG ({debugLogsRef.current.length})
        </button>
        {debugVisible && (
          <div style={{ background: 'rgba(0,0,0,0.9)', color: '#0f0', fontSize: '9px', maxHeight: '40vh', overflow: 'auto', padding: '4px', fontFamily: 'monospace', whiteSpace: 'pre-wrap', width: '100vw' }}>
            {debugSnapshot.map((l, i) => <div key={i}>{l}</div>)}
          </div>
        )}
      </div>

      {/* Debug Screenshots (SysAdmin only) */}
      {_isSysAdmin && (
        <div className={styles.summaryCard}>
          <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', marginBottom: '12px' }}>
            <h4 className={styles.panelTitle} style={{ margin: 0 }}>Debug Screenshots</h4>
            <button
              className={styles.viewButton}
              onClick={async () => {
                setScreenshotsLoading(true);
                try {
                  const result = await teamsbotApi.listScreenshots(instanceId, session.id);
                  setScreenshots(result.screenshots || []);
                  setScreenshotsLoaded(true);
                } catch (err: any) {
                  setScreenshots([]);
                  setScreenshotsLoaded(true);
                } finally {
                  setScreenshotsLoading(false);
                }
              }}
              disabled={screenshotsLoading}
            >
              {screenshotsLoading ? 'Laden...' : screenshotsLoaded ? 'Aktualisieren' : 'Screenshots laden'}
            </button>
          </div>
          {screenshotsLoaded && screenshots.length === 0 && (
            <div className={styles.emptyState}>Keine Screenshots fuer diese Session.</div>
          )}
          {screenshots.length > 0 && (
            <div style={{ display: 'grid', gridTemplateColumns: 'repeat(auto-fill, minmax(220px, 1fr))', gap: '12px' }}>
              {screenshots.map((s) => {
                const imgUrl = teamsbotApi.getScreenshotUrl(instanceId, s.name);
                return (
                  <a
                    key={s.name}
                    href={imgUrl}
                    target="_blank"
                    rel="noopener noreferrer"
                    style={{ display: 'block', textDecoration: 'none', color: 'inherit', border: '1px solid #333', borderRadius: '8px', overflow: 'hidden', background: '#1a1a2e' }}
                  >
                    <img
                      src={imgUrl}
                      alt={s.step}
                      style={{ width: '100%', height: '140px', objectFit: 'cover', display: 'block' }}
                      loading="lazy"
                    />
                    <div style={{ padding: '8px', fontSize: '12px' }}>
                      <div style={{ fontWeight: 600, marginBottom: '2px' }}>{s.step}</div>
                      <div style={{ color: '#888' }}>
                        {new Date(s.timestamp).toLocaleTimeString('de-CH')} — {(s.sizeBytes / 1024).toFixed(0)} KB
                      </div>
                    </div>
                  </a>
                );
              })}
            </div>
          )}
        </div>
      )}
    </div>
  );
};

export default TeamsbotSessionView;
