import { useEffect, useRef, useState } from 'react';
import { View, Text, TouchableOpacity, Alert, StyleSheet } from 'react-native';
import { LinearGradient } from 'expo-linear-gradient';
import { SafeAreaView } from 'react-native-safe-area-context';
import { Ionicons } from '@expo/vector-icons';
import { useRouter } from 'expo-router';
import { useTranslation } from 'react-i18next';
import { useCallStore } from '../stores/call';
import { UserAvatar } from '../components/UserAvatar';

function fmtDuration(ms: number) {
  const s = Math.floor(ms / 1000);
  const m = Math.floor(s / 60);
  return `${m}:${String(s % 60).padStart(2, '0')}`;
}

export default function CallScreen() {
  const { t } = useTranslation();
  const router = useRouter();

  const status = useCallStore((s) => s.status);
  const peer = useCallStore((s) => s.peer);
  const muted = useCallStore((s) => s.muted);
  const speaker = useCallStore((s) => s.speaker);
  const startedAt = useCallStore((s) => s.startedAt);
  const endReason = useCallStore((s) => s.endReason);
  const acceptCall = useCallStore((s) => s.acceptCall);
  const declineCall = useCallStore((s) => s.declineCall);
  const hangup = useCallStore((s) => s.hangup);
  const toggleMute = useCallStore((s) => s.toggleMute);
  const toggleSpeaker = useCallStore((s) => s.toggleSpeaker);
  const clear = useCallStore((s) => s._clear);

  const [elapsed, setElapsed] = useState(0);
  // Race-Guard: zustand-set in dm.tsx → router.push('/call') passiert manchmal
  // bevor unser useCallStore-Selector den neuen status sieht. Beim allerersten
  // Render kann status also kurz 'idle' sein, obwohl gerade ein Call gestartet
  // wird. Wir geben dem Store 250ms Zeit bevor wir bei 'idle' den Screen
  // schlie\u00dfen \u2014 sonst flickert die Call-UI sofort weg ("kurz und verschwindet").
  const mountedAt = useRef(Date.now());

  // Helper: Call-Screen schließen. Wir nutzen IMMER replace('/') statt back().
  //
  // Warum nicht router.back()?
  // React-Navigation dispatched GO_BACK asynchron über seinen Reducer. Wenn
  // canGoBack() zwar true zurückgibt aber der Stack-Zustand zwischenzeitlich
  // (z.B. durch AppState-Change oder Tab-Switch während des Calls) inkonsistent
  // geworden ist, wirft der Reducer einen GO_BACK-Action-Error — und der landet
  // NICHT im try/catch um back(), sondern crasht beim nächsten Render in
  // wrap-jsx.js. replace('/') ist deterministisch.
  const closeScreen = (why: string) => {
    const sinceMount = Date.now() - mountedAt.current;
    console.log('[call-screen] closeScreen why=', why, 'sinceMount=', sinceMount, 'ms');
    try {
      router.replace('/');
    } catch (err) {
      console.warn('[call-screen] router.replace(/) threw', err);
    }
  };

  // Kein aktiver Call \u2192 Screen schlie\u00dfen.
  useEffect(() => {
    if (status !== 'idle') return;
    const sinceMount = Date.now() - mountedAt.current;
    if (sinceMount < 250) {
      // Initial-Mount-Race: noch warten ob startCall/receiveIncoming den status
      // gleich auf outgoing/incoming setzt.
      const tm = setTimeout(() => {
        if (useCallStore.getState().status === 'idle') closeScreen('idle-after-grace');
      }, 250 - sinceMount);
      return () => clearTimeout(tm);
    }
    closeScreen('idle');
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [status]);

  // Call beendet → kurz "beendet" zeigen, dann schließen + aufräumen.
  useEffect(() => {
    if (status !== 'ended') return;
    console.log('[call-screen] status=ended -> will close in 1300ms; endReason=', endReason);
    const tm = setTimeout(() => {
      clear();
      closeScreen('ended-timeout');
    }, 1300);
    return () => clearTimeout(tm);
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [status, clear]);

  // Gesprächsdauer-Timer.
  useEffect(() => {
    if (status !== 'connected' || !startedAt) return;
    const id = setInterval(() => setElapsed(Date.now() - startedAt), 1000);
    return () => clearInterval(id);
  }, [status, startedAt]);

  async function onAccept() {
    try {
      await acceptCall();
    } catch (e: any) {
      if (e?.message === 'webrtc_unavailable') {
        Alert.alert(t('call.title'), t('call.needs_rebuild'));
      }
      hangup('failed');
    }
  }

  const subtitle =
    status === 'outgoing'
      ? t('call.calling')
      : status === 'incoming'
        ? t('call.incoming')
        : status === 'connecting'
          ? t('call.connecting')
          : status === 'connected'
            ? fmtDuration(elapsed)
            : status === 'ended'
              ? endReason === 'declined'
                ? t('call.declined')
                : endReason === 'unanswered'
                  ? t('call.no_answer')
                  : endReason === 'failed'
                    ? t('call.failed')
                    : t('call.ended')
              : '';

  return (
    <View style={{ flex: 1 }}>
      <LinearGradient colors={['#0f172a', '#1e3a34', '#0f172a']} style={StyleSheet.absoluteFill} />
      <SafeAreaView style={{ flex: 1, justifyContent: 'space-between', alignItems: 'center' }}>
        {/* Oben: Avatar + Name + Status */}
        <View style={{ alignItems: 'center', marginTop: 72, gap: 18 }}>
          <UserAvatar
            userId={peer?.id ?? null}
            avatar={peer?.avatar ?? null}
            nickname={peer?.nickname ?? '?'}
            size="xl"
          />
          <Text style={{ color: '#fff', fontSize: 26, fontFamily: 'Nunito_700Bold' }} numberOfLines={1}>
            {peer?.nickname ?? '…'}
          </Text>
          <Text style={{ color: 'rgba(255,255,255,0.7)', fontSize: 16, fontFamily: 'Nunito_600SemiBold', fontVariant: ['tabular-nums'] }}>
            {subtitle}
          </Text>
        </View>

        {/* Unten: Aktions-Buttons */}
        <View style={{ marginBottom: 56, width: '100%', alignItems: 'center' }}>
          {status === 'incoming' ? (
            <View style={{ flexDirection: 'row', justifyContent: 'space-evenly', width: '100%' }}>
              <CircleBtn color="#ef4444" icon="call" rotate onPress={declineCall} label={t('call.decline')} />
              <CircleBtn color="#22c55e" icon="call" onPress={onAccept} label={t('call.accept')} />
            </View>
          ) : status === 'ended' ? null : (
            <View style={{ flexDirection: 'row', justifyContent: 'center', alignItems: 'center', gap: 28 }}>
              {(status === 'connected' || status === 'connecting') && (
                <CircleBtn
                  color={muted ? '#fff' : 'rgba(255,255,255,0.18)'}
                  iconColor={muted ? '#0f172a' : '#fff'}
                  icon={muted ? 'mic-off' : 'mic'}
                  onPress={toggleMute}
                  label={muted ? t('call.unmute') : t('call.mute')}
                />
              )}
              {(status === 'connected' || status === 'connecting' || status === 'outgoing') && (
                <CircleBtn
                  color={speaker ? '#fff' : 'rgba(255,255,255,0.18)'}
                  iconColor={speaker ? '#0f172a' : '#fff'}
                  icon={speaker ? 'volume-high' : 'volume-medium'}
                  onPress={toggleSpeaker}
                  label={speaker ? t('call.speaker_on') : t('call.speaker_off')}
                />
              )}
              <CircleBtn color="#ef4444" icon="call" rotate onPress={() => hangup('ended')} label={t('call.hang_up')} />
            </View>
          )}
        </View>
      </SafeAreaView>
    </View>
  );
}

function CircleBtn({
  color,
  iconColor = '#fff',
  icon,
  rotate,
  onPress,
  label,
}: {
  color: string;
  iconColor?: string;
  icon: keyof typeof Ionicons.glyphMap;
  rotate?: boolean;
  onPress: () => void;
  label: string;
}) {
  return (
    <View style={{ alignItems: 'center', gap: 8 }}>
      <TouchableOpacity
        activeOpacity={0.8}
        onPress={onPress}
        style={{
          width: 68,
          height: 68,
          borderRadius: 34,
          backgroundColor: color,
          alignItems: 'center',
          justifyContent: 'center',
        }}
      >
        <Ionicons name={icon} size={28} color={iconColor} style={rotate ? { transform: [{ rotate: '135deg' }] } : undefined} />
      </TouchableOpacity>
      <Text style={{ color: 'rgba(255,255,255,0.8)', fontSize: 12, fontFamily: 'Nunito_600SemiBold' }}>{label}</Text>
    </View>
  );
}
