import { useState, useRef, useEffect, useCallback } from 'react';
import { useSocket, type RobotState } from './hooks/useSocket';
import { useMicrophone } from './hooks/useMicrophone';

const STATE_COLORS: Record<RobotState, string> = {
  disconnected: '#666',
  idle: '#4caf50',
  listening: '#2196f3',
  thinking: '#ff9800',
  speaking: '#ab47bc',
};

const STATE_LABELS: Record<RobotState, string> = {
  disconnected: 'Déconnecté',
  idle: 'Prêt',
  listening: 'Écoute...',
  thinking: 'Réflexion...',
  speaking: 'Parle...',
};

const LS_KEY_TOKEN = 'tipote_device_token';
const LS_KEY_URL = 'tipote_server_url';

function App() {
  const [serverUrl, setServerUrl] = useState(() => localStorage.getItem(LS_KEY_URL) || 'http://localhost:3000');
  const [deviceToken, setDeviceToken] = useState(() => localStorage.getItem(LS_KEY_TOKEN) || '');
  const [conversationActive, setConversationActive] = useState(false);
  const [showLogs, setShowLogs] = useState(false);
  const { state, connected, logs, connect, disconnect, emit, clearLogs } = useSocket();
  const logsEndRef = useRef<HTMLDivElement>(null);
  const prevStateRef = useRef<RobotState>('disconnected');

  const onAudioChunk = useCallback(
    (chunk: ArrayBuffer, sampleRate: number) => {
      emit('audio_chunk', { data: chunk, sampleRate });
    },
    [emit],
  );

  const onSpeechEnd = useCallback(() => {
    emit('speech_end');
  }, [emit]);

  const { recording, start: startMic, stop: stopMic, silentStop } = useMicrophone({ onAudioChunk, onSpeechEnd });

  // Stop mic when Ti-Pote starts thinking/speaking
  useEffect(() => {
    if (recording && (state === 'thinking' || state === 'speaking')) {
      silentStop();
    }
  }, [state, recording, silentStop]);

  // Auto-restart listening when Ti-Pote finishes speaking
  useEffect(() => {
    const prevState = prevStateRef.current;
    prevStateRef.current = state;

    if (conversationActive && state === 'idle' && (prevState === 'speaking' || prevState === 'thinking')) {
      const timer = setTimeout(() => {
        emit('wake_word_detected');
        startMic();
      }, 500);
      return () => clearTimeout(timer);
    }
  }, [state, conversationActive, emit, startMic]);

  useEffect(() => {
    logsEndRef.current?.scrollIntoView({ behavior: 'smooth' });
  }, [logs]);

  // Persist settings to localStorage
  const handleServerUrlChange = (value: string) => {
    setServerUrl(value);
    localStorage.setItem(LS_KEY_URL, value);
  };

  const handleTokenChange = (value: string) => {
    setDeviceToken(value);
    localStorage.setItem(LS_KEY_TOKEN, value);
  };

  const handleConnect = () => {
    if (connected) {
      disconnect();
      setConversationActive(false);
    } else {
      if (!deviceToken.trim()) return alert('Device token requis');
      connect(serverUrl, deviceToken.trim());
    }
  };

  const handleConversation = () => {
    if (conversationActive) {
      setConversationActive(false);
      emit('user_interrupt');
      if (recording) stopMic();
    } else {
      setConversationActive(true);
      emit('wake_word_detected');
      startMic();
    }
  };

  return (
    <div style={styles.container}>
      {/* Header */}
      <div style={styles.header}>
        <h1 style={styles.title}>Ti-Pote Simulator</h1>
        <div
          style={{
            ...styles.statusBadge,
            background: STATE_COLORS[state],
            boxShadow: state !== 'disconnected' ? `0 0 10px ${STATE_COLORS[state]}60` : 'none',
          }}
        >
          {STATE_LABELS[state]}
        </div>
      </div>

      {/* Connection */}
      {!connected ? (
        <div style={styles.panel}>
          <h2 style={styles.panelTitle}>Connexion</h2>
          <div style={styles.field}>
            <label style={styles.label}>Server URL</label>
            <input
              style={styles.input}
              value={serverUrl}
              onChange={(e) => handleServerUrlChange(e.target.value)}
              placeholder="http://localhost:3000"
            />
          </div>
          <div style={styles.field}>
            <label style={styles.label}>Device Token</label>
            <input
              style={styles.input}
              value={deviceToken}
              onChange={(e) => handleTokenChange(e.target.value)}
              placeholder="Coller le JWT du device ici"
            />
          </div>
          <button
            style={{ ...styles.btn, background: '#4caf50', width: '100%', padding: '12px 20px', fontSize: 16 }}
            onClick={handleConnect}
            disabled={!deviceToken.trim()}
          >
            Connecter
          </button>
        </div>
      ) : (
        <>
          {/* Main action */}
          <div style={styles.panel}>
            <button
              style={{
                ...styles.btn,
                width: '100%',
                padding: '20px',
                fontSize: 18,
                background: conversationActive ? '#f44336' : '#2196f3',
                borderRadius: 12,
                transition: 'all 0.2s',
              }}
              onClick={handleConversation}
            >
              {conversationActive ? 'Arrêter la conversation' : 'Parler à Ti-Pote'}
            </button>

            {conversationActive && recording && (
              <div style={styles.listeningIndicator}>
                <span style={styles.pulse} />
                Micro actif — parlez, Ti-Pote écoute
              </div>
            )}

            {conversationActive && state === 'thinking' && (
              <div style={styles.thinkingIndicator}>Ti-Pote réfléchit...</div>
            )}

            {conversationActive && state === 'speaking' && (
              <div style={styles.speakingIndicator}>Ti-Pote parle...</div>
            )}
          </div>

          {/* Disconnect */}
          <button
            style={{ ...styles.btn, background: 'transparent', color: '#888', width: '100%', marginBottom: 16 }}
            onClick={handleConnect}
          >
            Déconnecter
          </button>
        </>
      )}

      {/* Logs (collapsible) */}
      <div style={styles.panel}>
        <div style={styles.logHeader}>
          <button
            style={{ ...styles.btn, background: 'transparent', color: '#888', padding: '4px 0', fontSize: 12 }}
            onClick={() => setShowLogs(!showLogs)}
          >
            {showLogs ? '▼' : '▶'} Logs ({logs.length})
          </button>
          {showLogs && (
            <button
              style={{ ...styles.btn, background: '#333', padding: '4px 12px', fontSize: 11 }}
              onClick={clearLogs}
            >
              Clear
            </button>
          )}
        </div>
        {showLogs && (
          <div style={styles.logContainer}>
            {logs.map((log, i) => (
              <div key={i} style={styles.logEntry}>
                <span style={styles.logTime}>{log.timestamp.toLocaleTimeString()}</span>
                <span
                  style={{
                    ...styles.logDirection,
                    color: log.direction === 'in' ? '#4caf50' : log.direction === 'out' ? '#2196f3' : '#ff9800',
                  }}
                >
                  {log.direction === 'in' ? '◀' : log.direction === 'out' ? '▶' : '●'}
                </span>
                <span style={styles.logEvent}>{log.event}</span>
                {log.data && <span style={styles.logData}>{log.data}</span>}
              </div>
            ))}
            <div ref={logsEndRef} />
          </div>
        )}
      </div>
    </div>
  );
}

const styles: Record<string, React.CSSProperties> = {
  container: {
    maxWidth: 480,
    margin: '0 auto',
    padding: 20,
    fontFamily: '-apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif',
    color: '#e0e0e0',
    background: '#1a1a2e',
    minHeight: '100vh',
  },
  header: {
    display: 'flex',
    justifyContent: 'space-between',
    alignItems: 'center',
    marginBottom: 20,
  },
  title: {
    fontSize: 20,
    fontWeight: 700,
    color: '#fff',
    margin: 0,
  },
  statusBadge: {
    padding: '6px 14px',
    borderRadius: 20,
    fontSize: 12,
    fontWeight: 600,
    color: '#fff',
    transition: 'all 0.3s',
  },
  panel: {
    background: '#16213e',
    borderRadius: 12,
    padding: 16,
    marginBottom: 12,
  },
  panelTitle: {
    fontSize: 13,
    fontWeight: 600,
    textTransform: 'uppercase' as const,
    letterSpacing: 1,
    color: '#666',
    margin: '0 0 12px 0',
  },
  field: {
    marginBottom: 12,
  },
  label: {
    display: 'block',
    fontSize: 12,
    color: '#aaa',
    marginBottom: 4,
  },
  input: {
    width: '100%',
    padding: '10px 12px',
    border: '1px solid #333',
    borderRadius: 8,
    background: '#0f3460',
    color: '#fff',
    fontSize: 14,
    boxSizing: 'border-box' as const,
    outline: 'none',
  },
  btn: {
    padding: '8px 20px',
    border: 'none',
    borderRadius: 8,
    color: '#fff',
    fontSize: 14,
    fontWeight: 600,
    cursor: 'pointer',
  },
  listeningIndicator: {
    display: 'flex',
    alignItems: 'center',
    gap: 10,
    marginTop: 12,
    padding: '10px 14px',
    background: '#1a237e',
    borderRadius: 8,
    fontSize: 13,
    color: '#90caf9',
  },
  pulse: {
    display: 'inline-block',
    width: 10,
    height: 10,
    borderRadius: '50%',
    background: '#2196f3',
    animation: 'pulse 1.5s infinite',
    flexShrink: 0,
  },
  thinkingIndicator: {
    marginTop: 12,
    padding: '10px 14px',
    background: '#4a2800',
    borderRadius: 8,
    fontSize: 13,
    color: '#ffb74d',
    textAlign: 'center' as const,
  },
  speakingIndicator: {
    marginTop: 12,
    padding: '10px 14px',
    background: '#2a1040',
    borderRadius: 8,
    fontSize: 13,
    color: '#ce93d8',
    textAlign: 'center' as const,
  },
  logHeader: {
    display: 'flex',
    justifyContent: 'space-between',
    alignItems: 'center',
  },
  logContainer: {
    maxHeight: 200,
    overflowY: 'auto' as const,
    fontFamily: 'monospace',
    fontSize: 11,
    background: '#0a0a1a',
    borderRadius: 6,
    padding: 8,
    marginTop: 8,
  },
  logEntry: {
    display: 'flex',
    gap: 6,
    padding: '2px 0',
    borderBottom: '1px solid #1a1a2e',
  },
  logTime: { color: '#555', flexShrink: 0 },
  logDirection: { flexShrink: 0 },
  logEvent: { color: '#ccc', fontWeight: 600, flexShrink: 0 },
  logData: { color: '#888', overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' as const },
};

export default App;
