/**
 * VoiceRecorder — inline UI для записи голосового сообщения через
 * expo-audio (заменил deprecated expo-av).
 *
 * UX:
 *   - При монтировании проверяет permission + запускает запись
 *   - [🗑]  ● timer  Recording…  [↑]
 *   - 🗑 = cancel (discard), ↑ = stop + send
 *
 * Состояние recorder'а живёт в useAudioRecorder hook'е. Prepare + start
 * вызывается из useEffect. Stop — при release, finalized URI через
 * `recorder.uri`.
 */
import React, { useEffect, useRef, useState } from 'react';
import { View, Text, Pressable, Alert, Animated } from 'react-native';
import { Ionicons } from '@expo/vector-icons';
import {
  useAudioRecorder, AudioModule, RecordingPresets, setAudioModeAsync,
} from 'expo-audio';

import type { Attachment } from '@/lib/types';

export interface VoiceRecorderProps {
  onFinish: (att: Attachment) => void;
  onCancel: () => void;
}

export function VoiceRecorder({ onFinish, onCancel }: VoiceRecorderProps) {
  const recorder = useAudioRecorder(RecordingPresets.HIGH_QUALITY);
  const startedAt = useRef(0);
  const [elapsed, setElapsed] = useState(0);
  const [error, setError]     = useState<string | null>(null);
  const [ready, setReady]     = useState(false);

  // Pulsing red dot
  const pulse = useRef(new Animated.Value(1)).current;
  useEffect(() => {
    const loop = Animated.loop(
      Animated.sequence([
        Animated.timing(pulse, { toValue: 0.4, duration: 500, useNativeDriver: true }),
        Animated.timing(pulse, { toValue: 1,   duration: 500, useNativeDriver: true }),
      ]),
    );
    loop.start();
    return () => loop.stop();
  }, [pulse]);

  // Start recording at mount
  useEffect(() => {
    let cancelled = false;
    (async () => {
      try {
        const perm = await AudioModule.requestRecordingPermissionsAsync();
        if (!perm.granted) {
          setError('Microphone permission denied');
          return;
        }
        await setAudioModeAsync({
          allowsRecording: true,
          playsInSilentMode: true,
        });
        await recorder.prepareToRecordAsync();
        if (cancelled) return;
        recorder.record();
        startedAt.current = Date.now();
        setReady(true);
      } catch (e: any) {
        setError(e?.message ?? 'Failed to start recording');
      }
    })();
    return () => { cancelled = true; };
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, []);

  // Timer tick
  useEffect(() => {
    if (!ready) return;
    const t = setInterval(() => {
      setElapsed(Math.floor((Date.now() - startedAt.current) / 1000));
    }, 250);
    return () => clearInterval(t);
  }, [ready]);

  const stop = async (send: boolean) => {
    try {
      if (recorder.isRecording) {
        await recorder.stop();
      }
      const uri = recorder.uri;
      const seconds = Math.max(1, Math.floor((Date.now() - startedAt.current) / 1000));
      if (!send || !uri || seconds < 1) {
        onCancel();
        return;
      }
      onFinish({
        kind:     'voice',
        uri,
        duration: seconds,
        mime:     'audio/m4a',
      });
    } catch (e: any) {
      Alert.alert('Recording failed', e?.message ?? 'Unknown error');
      onCancel();
    }
  };

  const mm = Math.floor(elapsed / 60);
  const ss = elapsed % 60;

  if (error) {
    return (
      <View
        style={{
          flexDirection: 'row',
          alignItems: 'center',
          backgroundColor: '#111111',
          borderRadius: 22,
          borderWidth: 1, borderColor: '#1f1f1f',
          paddingHorizontal: 14, paddingVertical: 8,
          gap: 10,
        }}
      >
        <Ionicons name="alert-circle" size={18} color="#f4212e" />
        <Text style={{ color: '#f4212e', fontSize: 13, flex: 1 }}>{error}</Text>
        <Pressable onPress={onCancel} hitSlop={8}>
          <Ionicons name="close" size={20} color="#8b8b8b" />
        </Pressable>
      </View>
    );
  }

  return (
    <View
      style={{
        flexDirection: 'row',
        alignItems: 'center',
        backgroundColor: '#111111',
        borderRadius: 22,
        borderWidth: 1, borderColor: '#1f1f1f',
        paddingHorizontal: 10, paddingVertical: 6,
        gap: 10,
      }}
    >
      <Pressable
        onPress={() => stop(false)}
        hitSlop={8}
        style={{
          width: 32, height: 32, borderRadius: 16,
          alignItems: 'center', justifyContent: 'center',
        }}
      >
        <Ionicons name="trash-outline" size={20} color="#f4212e" />
      </Pressable>

      <View style={{ flexDirection: 'row', alignItems: 'center', gap: 10, flex: 1 }}>
        <Animated.View
          style={{
            width: 10, height: 10, borderRadius: 5,
            backgroundColor: '#f4212e',
            opacity: pulse,
          }}
        />
        <Text style={{ color: '#ffffff', fontSize: 15, fontWeight: '600' }}>
          {mm}:{String(ss).padStart(2, '0')}
        </Text>
        <Text style={{ color: '#8b8b8b', fontSize: 12 }}>
          Recording…
        </Text>
      </View>

      <Pressable
        onPress={() => stop(true)}
        style={({ pressed }) => ({
          width: 32, height: 32, borderRadius: 16,
          backgroundColor: pressed ? '#1a8cd8' : '#1d9bf0',
          alignItems: 'center', justifyContent: 'center',
        })}
      >
        <Ionicons name="arrow-up" size={18} color="#ffffff" />
      </Pressable>
    </View>
  );
}
