/**
 * VoicePlayer — play/pause voice message через expo-audio.
 *
 * Раздел на две подкомпоненты:
 *   - RealVoicePlayer: useAudioPlayer с настоящим URI
 *   - StubVoicePlayer: отрисовка waveform без player'а (seed-URI)
 *
 * Разделение важно: useAudioPlayer не должен получать null/stub-строки —
 * при падении внутри expo-audio это крашит render всего bubble'а и
 * (в FlatList) визуально "пропадает" интерфейс чата.
 *
 * UI:
 *   [▶/⏸]  ▮▮▮▮▮▮▮▮▮▯▯▯▯▯▯▯▯  0:03 / 0:17
 */
import React, { useMemo } from 'react';
import { View, Text, Pressable } from 'react-native';
import { Ionicons } from '@expo/vector-icons';
import { useAudioPlayer, useAudioPlayerStatus } from 'expo-audio';

export interface VoicePlayerProps {
  uri:       string;
  duration?: number;
  own?:      boolean;
}

const BAR_COUNT = 22;

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

function isStubUri(u: string): boolean {
  return u.startsWith('voice-stub://') || u.startsWith('voice-demo://');
}

function useBars(uri: string) {
  return useMemo(() => {
    const seed = uri.length;
    return Array.from({ length: BAR_COUNT }, (_, i) => {
      const h = ((seed * (i + 1) * 7919) % 11) + 4;
      return h;
    });
  }, [uri]);
}

// ─── Top-level router ──────────────────────────────────────────────

export function VoicePlayer(props: VoicePlayerProps) {
  // Stub-URI (seed) не передаётся в useAudioPlayer — hook может крашить
  // на невалидных source'ах. Рендерим статический waveform.
  if (isStubUri(props.uri)) return <StubVoicePlayer {...props} />;
  return <RealVoicePlayer {...props} />;
}

// ─── Stub (seed / preview) ─────────────────────────────────────────

function StubVoicePlayer({ uri, duration, own }: VoicePlayerProps) {
  const bars = useBars(uri);
  const accent    = own ? 'rgba(255,255,255,0.92)' : '#1d9bf0';
  const subtle    = own ? 'rgba(255,255,255,0.35)' : '#3a3a3a';
  const textColor = own ? 'rgba(255,255,255,0.85)' : '#8b8b8b';

  return (
    <View style={{ flexDirection: 'row', alignItems: 'center', marginBottom: 4, gap: 8 }}>
      <View
        style={{
          width: 32, height: 32, borderRadius: 16,
          backgroundColor: own ? 'rgba(255,255,255,0.18)' : '#1a1a1a',
          alignItems: 'center', justifyContent: 'center',
        }}
      >
        <Ionicons name="play" size={14} color="#ffffff" style={{ marginLeft: 1 }} />
      </View>
      <View style={{ flexDirection: 'row', alignItems: 'center', gap: 2, flex: 1 }}>
        {bars.map((h, i) => (
          <View
            key={i}
            style={{
              width: 2, height: h, borderRadius: 1,
              backgroundColor: i < 6 ? accent : subtle,
            }}
          />
        ))}
      </View>
      <Text style={{ color: textColor, fontSize: 12 }}>
        {formatClock(duration ?? 0)}
      </Text>
    </View>
  );
}

// ─── Real expo-audio player ────────────────────────────────────────

function RealVoicePlayer({ uri, duration, own }: VoicePlayerProps) {
  const player = useAudioPlayer({ uri });
  const status = useAudioPlayerStatus(player);
  const bars = useBars(uri);

  const accent    = own ? 'rgba(255,255,255,0.92)' : '#1d9bf0';
  const subtle    = own ? 'rgba(255,255,255,0.35)' : '#3a3a3a';
  const textColor = own ? 'rgba(255,255,255,0.85)' : '#8b8b8b';

  const playing  = !!status.playing;
  const loading  = !!status.isBuffering && !status.isLoaded;
  const curSec   = status.currentTime ?? 0;
  const totalSec = (status.duration && status.duration > 0) ? status.duration : (duration ?? 0);

  const playedRatio = totalSec > 0 ? Math.min(1, curSec / totalSec) : 0;
  const playedBars  = Math.round(playedRatio * BAR_COUNT);

  const toggle = () => {
    try {
      if (status.playing) {
        player.pause();
      } else {
        if (status.duration && curSec >= status.duration - 0.05) {
          player.seekTo(0);
        }
        player.play();
      }
    } catch {
      /* dbl-tap during load */
    }
  };

  return (
    <View style={{ flexDirection: 'row', alignItems: 'center', marginBottom: 4, gap: 8 }}>
      <Pressable
        onPress={toggle}
        hitSlop={8}
        style={{
          width: 32, height: 32, borderRadius: 16,
          backgroundColor: own ? 'rgba(255,255,255,0.18)' : '#1a1a1a',
          alignItems: 'center', justifyContent: 'center',
        }}
      >
        <Ionicons
          name={playing ? 'pause' : (loading ? 'hourglass-outline' : 'play')}
          size={14}
          color="#ffffff"
          style={{ marginLeft: playing || loading ? 0 : 1 }}
        />
      </Pressable>

      <View style={{ flexDirection: 'row', alignItems: 'center', gap: 2, flex: 1 }}>
        {bars.map((h, i) => (
          <View
            key={i}
            style={{
              width: 2, height: h, borderRadius: 1,
              backgroundColor: i < playedBars ? accent : subtle,
            }}
          />
        ))}
      </View>

      <Text style={{ color: textColor, fontSize: 12 }}>
        {playing || curSec > 0
          ? `${formatClock(Math.floor(curSec))} / ${formatClock(Math.floor(totalSec))}`
          : formatClock(Math.floor(totalSec))}
      </Text>
    </View>
  );
}
