/**
 * ChatScreen - Hauptchat-Oberflaeche
 *
 * Zeigt die Konversation mit ARIA, Texteingabe, Sprach-Button,
 * Datei- und Kamera-Upload.
 */

import React, { useState, useEffect, useRef, useCallback } from 'react';
import {
  View,
  Text,
  TextInput,
  TouchableOpacity,
  FlatList,
  KeyboardAvoidingView,
  Platform,
  StyleSheet,
  Image,
  Modal,
} from 'react-native';
import AsyncStorage from '@react-native-async-storage/async-storage';
import rvs, { RVSMessage, ConnectionState } from '../services/rvs';
import audioService from '../services/audio';
import wakeWordService from '../services/wakeword';
import VoiceButton from '../components/VoiceButton';
import FileUpload, { FileData } from '../components/FileUpload';
import CameraUpload, { PhotoData } from '../components/CameraUpload';
import { RecordingResult } from '../services/audio';
import Geolocation from '@react-native-community/geolocation';

// --- Typen ---

interface Attachment {
  type: 'image' | 'file' | 'audio';
  name: string;
  size?: number;
  uri?: string;       // Lokaler Pfad oder data URI fuer Anzeige
  mimeType?: string;
}

interface ChatMessage {
  id: string;
  sender: 'user' | 'aria';
  text: string;
  timestamp: number;
  attachments?: Attachment[];
}

// --- Konstanten ---

const CHAT_STORAGE_KEY = 'aria_chat_messages';
const MAX_STORED_MESSAGES = 500;

// --- Komponente ---

const ChatScreen: React.FC = () => {
  const [messages, setMessages] = useState<ChatMessage[]>([]);
  const [inputText, setInputText] = useState('');
  const [connectionState, setConnectionState] = useState<ConnectionState>('disconnected');
  const [showFileUpload, setShowFileUpload] = useState(false);
  const [showCameraUpload, setShowCameraUpload] = useState(false);
  const [gpsEnabled, setGpsEnabled] = useState(false);
  const [wakeWordActive, setWakeWordActive] = useState(false);

  const flatListRef = useRef<FlatList>(null);
  const messageIdCounter = useRef(0);

  // Eindeutige Message-ID generieren
  const nextId = (): string => {
    messageIdCounter.current += 1;
    return `msg_${Date.now()}_${messageIdCounter.current}`;
  };

  // Chat-Verlauf aus AsyncStorage laden
  useEffect(() => {
    const loadMessages = async () => {
      try {
        const stored = await AsyncStorage.getItem(CHAT_STORAGE_KEY);
        if (stored) {
          const parsed: ChatMessage[] = JSON.parse(stored);
          setMessages(parsed);
          // ID-Counter auf hoechsten Wert setzen um Kollisionen zu vermeiden
          const maxId = parsed.reduce((max, msg) => {
            const num = parseInt(msg.id.split('_').pop() || '0', 10);
            return num > max ? num : max;
          }, 0);
          messageIdCounter.current = maxId;
        }
      } catch (err) {
        console.error('[Chat] Fehler beim Laden des Verlaufs:', err);
      }
    };
    loadMessages();
  }, []);

  // RVS-Nachrichten abonnieren
  useEffect(() => {
    const unsubMessage = rvs.onMessage((message: RVSMessage) => {
      // STT-Ergebnis: Spracheingabe-Placeholder mit transkribiertem Text ersetzen
      if (message.type === 'stt_result') {
        const sttText = (message.payload.text as string) || '';
        if (sttText) {
          setMessages(prev => prev.map(m =>
            m.sender === 'user' && m.text.includes('Spracheingabe wird verarbeitet')
              ? { ...m, text: sttText }
              : m
          ));
        } else {
          // Keine Sprache erkannt — Placeholder entfernen
          setMessages(prev => prev.filter(m =>
            !(m.sender === 'user' && m.text.includes('Spracheingabe wird verarbeitet'))
          ));
        }
        return;
      }

      if (message.type === 'chat') {
        // Nur Nachrichten von ARIA anzeigen — eigene Nachrichten werden lokal hinzugefuegt
        const sender = (message.payload.sender as string) || '';
        if (sender === 'user' || sender === 'diagnostic') return;

        const text = (message.payload.text as string) || '';
        const ts = message.timestamp;
        // Duplikat-Schutz: gleicher Text innerhalb 5s ignorieren
        setMessages(prev => {
          const isDuplicate = prev.some(m =>
            m.sender === 'aria' && m.text === text && Math.abs(m.timestamp - ts) < 5000
          );
          if (isDuplicate) return prev;
          const ariaMsg: ChatMessage = {
            id: nextId(),
            sender: 'aria',
            text,
            timestamp: ts,
            attachments: message.payload.attachments as Attachment[] | undefined,
          };
          return [...prev, ariaMsg];
        });
      }

      // TTS-Audio abspielen wenn vorhanden
      if (message.type === 'audio' && message.payload.base64) {
        audioService.playAudio(message.payload.base64 as string);
      }
    });

    const unsubState = rvs.onStateChange((state) => {
      setConnectionState(state);
    });

    // Initalen Status setzen
    setConnectionState(rvs.getState());

    return () => {
      unsubMessage();
      unsubState();
    };
  }, []);

  // Wake Word: "ARIA" Erkennung → Auto-Aufnahme starten
  useEffect(() => {
    const unsubWake = wakeWordService.onWakeWord(async () => {
      console.log('[Chat] Wake Word erkannt — starte Auto-Aufnahme');
      // TTS stoppen damit ARIA sich nicht selbst hoert
      audioService.stopPlayback();
      // Aufnahme mit Auto-Stop (VAD) starten
      const started = await audioService.startRecording(true);
      if (!started) {
        // Mikrofon nicht verfuegbar, Wake Word wieder aktivieren
        wakeWordService.resume();
      }
    });

    // Auto-Stop Callback: wenn Stille erkannt → Aufnahme senden + Wake Word wieder starten
    const unsubSilence = audioService.onSilenceDetected(async () => {
      const result = await audioService.stopRecording();
      if (result && result.durationMs > 500) {
        // Sprachnachricht senden (gleiche Logik wie handleVoiceRecording)
        const location = await getCurrentLocation();
        const userMsg: ChatMessage = {
          id: nextId(),
          sender: 'user',
          text: '🎙 Spracheingabe wird verarbeitet...',
          timestamp: Date.now(),
          attachments: [{ type: 'audio', name: 'Sprachaufnahme' }],
        };
        setMessages(prev => [...prev, userMsg]);
        rvs.send('audio', {
          base64: result.base64,
          durationMs: result.durationMs,
          mimeType: result.mimeType,
          ...(location && { location }),
        });
      }
      // Wake Word wieder aktivieren
      if (wakeWordActive) wakeWordService.resume();
    });

    return () => {
      unsubWake();
      unsubSilence();
    };
  }, [wakeWordActive]);

  // Wake Word Toggle Handler
  const toggleWakeWord = useCallback(async () => {
    if (wakeWordActive) {
      wakeWordService.stop();
      setWakeWordActive(false);
    } else {
      const started = await wakeWordService.start();
      setWakeWordActive(started);
    }
  }, [wakeWordActive]);

  // Chat-Verlauf in AsyncStorage speichern (letzte N Nachrichten)
  useEffect(() => {
    if (messages.length === 0) return;
    const toStore = messages.slice(-MAX_STORED_MESSAGES);
    AsyncStorage.setItem(CHAT_STORAGE_KEY, JSON.stringify(toStore)).catch(err =>
      console.error('[Chat] Fehler beim Speichern:', err),
    );
  }, [messages]);

  // Auto-Scroll wird ueber onContentSizeChange der FlatList gesteuert
  const shouldAutoScroll = useRef(true);
  const handleContentSizeChange = useCallback(() => {
    if (shouldAutoScroll.current) {
      flatListRef.current?.scrollToEnd({ animated: false });
    }
  }, []);
  const handleScrollBeginDrag = useCallback(() => {
    shouldAutoScroll.current = false;
  }, []);
  const handleScrollEndDrag = useCallback((e: any) => {
    // Auto-Scroll wieder aktivieren wenn User ganz unten ist
    const { contentOffset, contentSize, layoutMeasurement } = e.nativeEvent;
    const isAtBottom = contentOffset.y + layoutMeasurement.height >= contentSize.height - 50;
    shouldAutoScroll.current = isAtBottom;
  }, []);

  // GPS-Position holen (optional)
  const getCurrentLocation = useCallback((): Promise<{ lat: number; lon: number } | null> => {
    if (!gpsEnabled) return Promise.resolve(null);

    return new Promise((resolve) => {
      Geolocation.getCurrentPosition(
        (position) => {
          resolve({
            lat: position.coords.latitude,
            lon: position.coords.longitude,
          });
        },
        (_error) => {
          resolve(null);
        },
        { enableHighAccuracy: false, timeout: 5000 },
      );
    });
  }, [gpsEnabled]);

  // --- Nachricht senden ---

  const sendTextMessage = useCallback(async () => {
    const text = inputText.trim();
    if (!text) return;

    setInputText('');

    const location = await getCurrentLocation();

    const userMsg: ChatMessage = {
      id: nextId(),
      sender: 'user',
      text,
      timestamp: Date.now(),
    };
    setMessages(prev => [...prev, userMsg]);

    // An RVS senden
    rvs.send('chat', {
      text,
      ...(location && { location }),
    });
  }, [inputText, getCurrentLocation]);

  // Sprachaufnahme abgeschlossen
  const handleVoiceRecording = useCallback(async (result: RecordingResult) => {
    const location = await getCurrentLocation();

    const userMsg: ChatMessage = {
      id: nextId(),
      sender: 'user',
      text: '🎙 Spracheingabe wird verarbeitet...',
      timestamp: Date.now(),
    };
    setMessages(prev => [...prev, userMsg]);

    rvs.send('audio', {
      base64: result.base64,
      durationMs: result.durationMs,
      mimeType: result.mimeType,
      ...(location && { location }),
    });
  }, [getCurrentLocation]);

  // Datei senden
  const handleFileSelected = useCallback(async (file: FileData) => {
    setShowFileUpload(false);
    const location = await getCurrentLocation();

    const isImage = file.type.startsWith('image/');
    const userMsg: ChatMessage = {
      id: nextId(),
      sender: 'user',
      text: 'Anhang empfangen',
      timestamp: Date.now(),
      attachments: [{
        type: isImage ? 'image' : 'file',
        name: file.name,
        size: file.size,
        uri: isImage && file.base64 ? `data:${file.type};base64,${file.base64}` : file.uri,
        mimeType: file.type,
      }],
    };
    setMessages(prev => [...prev, userMsg]);

    rvs.send('file', {
      name: file.name,
      type: file.type,
      size: file.size,
      base64: file.base64,
      ...(location && { location }),
    });
  }, [getCurrentLocation]);

  // Foto senden
  const handlePhotoSelected = useCallback(async (photo: PhotoData) => {
    setShowCameraUpload(false);
    const location = await getCurrentLocation();

    const userMsg: ChatMessage = {
      id: nextId(),
      sender: 'user',
      text: 'Anhang empfangen',
      timestamp: Date.now(),
      attachments: [{
        type: 'image',
        name: photo.fileName,
        uri: photo.base64 ? `data:${photo.type};base64,${photo.base64}` : undefined,
        mimeType: photo.type,
      }],
    };
    setMessages(prev => [...prev, userMsg]);

    rvs.send('file', {
      name: photo.fileName,
      type: photo.type,
      base64: photo.base64,
      width: photo.width,
      height: photo.height,
      ...(location && { location }),
    });
  }, [getCurrentLocation]);

  // --- Rendering ---

  const renderMessage = ({ item }: { item: ChatMessage }) => {
    const isUser = item.sender === 'user';
    const time = new Date(item.timestamp).toLocaleTimeString('de-DE', {
      hour: '2-digit',
      minute: '2-digit',
    });

    return (
      <View style={[styles.messageBubble, isUser ? styles.userBubble : styles.ariaBubble]}>
        {/* Anhang-Vorschau */}
        {item.attachments?.map((att, idx) => (
          <View key={idx}>
            {att.type === 'image' && att.uri ? (
              <Image
                source={{ uri: att.uri }}
                style={styles.attachmentImage}
                resizeMode="contain"
              />
            ) : (
              <View style={styles.attachmentFile}>
                <Text style={styles.attachmentFileIcon}>
                  {att.mimeType?.includes('pdf') ? '\uD83D\uDCC4' :
                   att.mimeType?.includes('word') || att.mimeType?.includes('document') ? '\uD83D\uDCC3' :
                   att.mimeType?.includes('sheet') || att.mimeType?.includes('excel') ? '\uD83D\uDCC8' :
                   '\uD83D\uDCC1'}
                </Text>
                <Text style={styles.attachmentFileName} numberOfLines={1}>{att.name}</Text>
                {att.size ? <Text style={styles.attachmentFileSize}>{Math.round(att.size / 1024)}KB</Text> : null}
              </View>
            )}
          </View>
        ))}
        {/* Text (nicht anzeigen wenn nur "Anhang empfangen" und ein Bild da ist) */}
        {!(item.text === 'Anhang empfangen' && item.attachments?.some(a => a.type === 'image' && a.uri)) && (
          <Text style={[styles.messageText, isUser ? styles.userText : styles.ariaText]}>
            {item.text}
          </Text>
        )}
        <Text style={styles.timestamp}>{time}</Text>
      </View>
    );
  };

  const connectionDotColor =
    connectionState === 'connected' ? '#34C759' :
    connectionState === 'connecting' ? '#FFD60A' : '#FF3B30';

  return (
    <KeyboardAvoidingView
      style={styles.container}
      behavior={Platform.OS === 'ios' ? 'padding' : undefined}
      keyboardVerticalOffset={90}
    >
      {/* Verbindungsstatus-Leiste */}
      <View style={styles.statusBar}>
        <View style={[styles.statusDot, { backgroundColor: connectionDotColor }]} />
        <Text style={styles.statusText}>
          {connectionState === 'connected' ? 'Verbunden' :
           connectionState === 'connecting' ? 'Verbinde...' : 'Getrennt'}
        </Text>
      </View>

      {/* Nachrichtenliste */}
      <FlatList
        ref={flatListRef}
        data={messages}
        keyExtractor={item => item.id}
        renderItem={renderMessage}
        contentContainerStyle={styles.messageList}
        showsVerticalScrollIndicator={false}
        onContentSizeChange={handleContentSizeChange}
        onScrollBeginDrag={handleScrollBeginDrag}
        onScrollEndDrag={handleScrollEndDrag}
        ListEmptyComponent={
          <View style={styles.emptyContainer}>
            <Text style={styles.emptyIcon}>{'\uD83E\uDD16'}</Text>
            <Text style={styles.emptyText}>ARIA Cockpit</Text>
            <Text style={styles.emptyHint}>Starte eine Konversation mit ARIA</Text>
          </View>
        }
      />

      {/* Eingabebereich */}
      <View style={styles.inputContainer}>
        {/* Datei-Buttons */}
        <TouchableOpacity
          style={styles.actionButton}
          onPress={() => setShowFileUpload(true)}
        >
          <Text style={styles.actionIcon}>{'\uD83D\uDCCE'}</Text>
        </TouchableOpacity>

        <TouchableOpacity
          style={styles.actionButton}
          onPress={() => setShowCameraUpload(true)}
        >
          <Text style={styles.actionIcon}>{'\uD83D\uDCF7'}</Text>
        </TouchableOpacity>

        {/* Texteingabe */}
        <TextInput
          style={styles.textInput}
          value={inputText}
          onChangeText={setInputText}
          placeholder="Nachricht an ARIA..."
          placeholderTextColor="#555570"
          multiline
          maxLength={4000}
          onSubmitEditing={sendTextMessage}
          returnKeyType="send"
        />

        {/* Senden oder Sprache */}
        {inputText.trim() ? (
          <TouchableOpacity style={styles.sendButton} onPress={sendTextMessage}>
            <Text style={styles.sendIcon}>{'\u2B06\uFE0F'}</Text>
          </TouchableOpacity>
        ) : (
          <>
            <VoiceButton
              onRecordingComplete={handleVoiceRecording}
              disabled={connectionState !== 'connected'}
              wakeWordActive={wakeWordActive}
            />
            <TouchableOpacity
              style={[styles.wakeWordBtn, wakeWordActive && styles.wakeWordBtnActive]}
              onPress={toggleWakeWord}
            >
              <Text style={styles.wakeWordIcon}>{wakeWordActive ? '👂' : '🔇'}</Text>
            </TouchableOpacity>
          </>
        )}
      </View>

      {/* Datei-Upload Modal */}
      <Modal visible={showFileUpload} transparent animationType="slide">
        <View style={styles.modalOverlay}>
          <FileUpload
            onFileSelected={handleFileSelected}
            onCancel={() => setShowFileUpload(false)}
          />
        </View>
      </Modal>

      {/* Kamera-Upload Modal */}
      <Modal visible={showCameraUpload} transparent animationType="slide">
        <View style={styles.modalOverlay}>
          <CameraUpload
            onPhotoSelected={handlePhotoSelected}
            onCancel={() => setShowCameraUpload(false)}
          />
        </View>
      </Modal>
    </KeyboardAvoidingView>
  );
};

// --- Styles ---

const styles = StyleSheet.create({
  container: {
    flex: 1,
    backgroundColor: '#0D0D1A',
  },
  statusBar: {
    flexDirection: 'row',
    alignItems: 'center',
    paddingHorizontal: 16,
    paddingVertical: 8,
    backgroundColor: '#12122A',
    borderBottomWidth: 1,
    borderBottomColor: '#1E1E2E',
  },
  statusDot: {
    width: 8,
    height: 8,
    borderRadius: 4,
    marginRight: 8,
  },
  statusText: {
    color: '#8888AA',
    fontSize: 12,
  },
  messageList: {
    padding: 12,
    paddingBottom: 8,
    flexGrow: 1,
  },
  messageBubble: {
    maxWidth: '80%',
    padding: 12,
    borderRadius: 16,
    marginBottom: 8,
  },
  userBubble: {
    alignSelf: 'flex-end',
    backgroundColor: '#0096FF',
    borderBottomRightRadius: 4,
  },
  ariaBubble: {
    alignSelf: 'flex-start',
    backgroundColor: '#1E1E2E',
    borderBottomLeftRadius: 4,
  },
  messageText: {
    fontSize: 15,
    lineHeight: 21,
  },
  userText: {
    color: '#FFFFFF',
  },
  ariaText: {
    color: '#E0E0F0',
  },
  attachmentImage: {
    width: '100%',
    height: 200,
    borderRadius: 8,
    marginBottom: 6,
    backgroundColor: '#0D0D1A',
  },
  attachmentFile: {
    flexDirection: 'row',
    alignItems: 'center',
    backgroundColor: 'rgba(255,255,255,0.1)',
    borderRadius: 8,
    padding: 10,
    marginBottom: 6,
  },
  attachmentFileIcon: {
    fontSize: 24,
    marginRight: 8,
  },
  attachmentFileName: {
    flex: 1,
    color: '#E0E0F0',
    fontSize: 13,
  },
  attachmentFileSize: {
    color: '#8888AA',
    fontSize: 11,
    marginLeft: 8,
  },
  timestamp: {
    color: 'rgba(255,255,255,0.4)',
    fontSize: 10,
    marginTop: 4,
    alignSelf: 'flex-end',
  },
  emptyContainer: {
    flex: 1,
    alignItems: 'center',
    justifyContent: 'center',
    paddingTop: 120,
  },
  emptyIcon: {
    fontSize: 48,
    marginBottom: 12,
  },
  emptyText: {
    color: '#FFFFFF',
    fontSize: 22,
    fontWeight: '700',
  },
  emptyHint: {
    color: '#555570',
    fontSize: 14,
    marginTop: 4,
  },
  inputContainer: {
    flexDirection: 'row',
    alignItems: 'flex-end',
    paddingHorizontal: 10,
    paddingVertical: 8,
    backgroundColor: '#12122A',
    borderTopWidth: 1,
    borderTopColor: '#1E1E2E',
  },
  actionButton: {
    width: 38,
    height: 38,
    borderRadius: 19,
    alignItems: 'center',
    justifyContent: 'center',
    marginRight: 4,
  },
  actionIcon: {
    fontSize: 20,
  },
  textInput: {
    flex: 1,
    backgroundColor: '#1E1E2E',
    borderRadius: 20,
    paddingHorizontal: 16,
    paddingVertical: 10,
    color: '#FFFFFF',
    fontSize: 15,
    maxHeight: 100,
    marginHorizontal: 6,
  },
  sendButton: {
    width: 40,
    height: 40,
    borderRadius: 20,
    backgroundColor: '#0096FF',
    alignItems: 'center',
    justifyContent: 'center',
  },
  sendIcon: {
    fontSize: 18,
  },
  wakeWordBtn: {
    width: 32,
    height: 32,
    borderRadius: 16,
    backgroundColor: 'rgba(255,255,255,0.1)',
    alignItems: 'center',
    justifyContent: 'center',
    marginLeft: 4,
  },
  wakeWordBtnActive: {
    backgroundColor: 'rgba(52, 199, 89, 0.3)',
  },
  wakeWordIcon: {
    fontSize: 16,
  },
  modalOverlay: {
    flex: 1,
    backgroundColor: 'rgba(0,0,0,0.6)',
    justifyContent: 'center',
  },
});

export default ChatScreen;
