import React, {useCallback, useEffect, useId, useRef, useState} from 'react';
import {View} from 'react-native';
import {IconMusic} from '@tabler/icons-react-native';
import {useAudioPlayer, useAudioPlayerStatus} from 'expo-audio';
import {AudioPlayer} from '@components/_custom/Audio';
import {Avatar} from '@components/_HuGo/Avatar';
import {CardContainer} from '@components/_HuGo/CardContainer';
import {Title} from '@components/_HuGo/Title';
import {Attachment} from '@interfaces/attachments';
import {bytesToSize, getFileNameExtension} from '@shared/utils';
import {useActiveAudioStore} from '@stores/activeAudio';

import {styles} from './styles';

const PLAYBACK_RATES = [1, 1.5, 2];
/** `useAudioPlayer` status refresh — drives scrubber smoothness (expo-audio `updateInterval`). */
const PLAYBACK_STATUS_UPDATE_MS = 50;

interface Props {
  attachment: Attachment;
}

export function PostAudioCard({attachment}: Props) {
  const {url, name, bytes} = attachment;
  const [rateIndex, setRateIndex] = useState(0);
  const playerInstanceId = useId();
  const playerRef = useRef<ReturnType<typeof useAudioPlayer> | null>(null);

  const player = useAudioPlayer(url ? {uri: url} : null, {
    updateInterval: PLAYBACK_STATUS_UPDATE_MS,
  });
  playerRef.current = player;

  const registerPause = useActiveAudioStore(s => s.registerPause);
  const unregisterPause = useActiveAudioStore(s => s.unregisterPause);
  const pauseAllExcept = useActiveAudioStore(s => s.pauseAllExcept);

  useEffect(() => {
    registerPause(playerInstanceId, () => {
      playerRef.current?.pause();
    });
    return () => {
      unregisterPause(playerInstanceId);
    };
  }, [playerInstanceId, registerPause, unregisterPause]);

  const status = useAudioPlayerStatus(player);

  const duration = status.duration || 0;
  const currentTime = status.currentTime || 0;
  const progress = duration > 0 ? currentTime / duration : 0;
  const isPlaying = status.playing;
  const isPaused = !status.playing && currentTime > 0 && !status.didJustFinish;
  const isLoading = status.isBuffering && !isPlaying;

  const onPlay = useCallback(() => {
    pauseAllExcept(playerInstanceId);
    if (status.didJustFinish || (duration > 0 && currentTime >= duration)) {
      player.seekTo(0);
    }
    player.play();
  }, [
    currentTime,
    duration,
    pauseAllExcept,
    player,
    playerInstanceId,
    status.didJustFinish,
  ]);

  const onPause = useCallback(() => {
    player.pause();
  }, [player]);

  const onSeek = useCallback(
    (position: number) => {
      player.seekTo(position);
    },
    [player],
  );

  const onToggleRate = useCallback(() => {
    const next = (rateIndex + 1) % PLAYBACK_RATES.length;
    setRateIndex(next);
    player.setPlaybackRate(PLAYBACK_RATES[next]);
  }, [player, rateIndex]);

  const extension = getFileNameExtension(name ?? '', true);
  const sizeText = bytes ? `${bytesToSize(bytes, 0)} • ` : '';

  return (
    <CardContainer style={styles.container}>
      <View style={styles.headerRow}>
        <Avatar size="sm" Icon={IconMusic} variant="highlight" />
        <Title
          title={name ?? ''}
          description={`${sizeText}${extension}`}
          size="s"
          style={styles.titleColumn}
        />
      </View>
      <AudioPlayer
        isPlaying={isPlaying}
        isPaused={isPaused}
        isLoading={isLoading}
        layout="fill"
        rate={PLAYBACK_RATES[rateIndex]}
        duration={duration}
        progress={progress}
        onPlay={onPlay}
        onPause={onPause}
        onSeek={onSeek}
        onToggleRate={onToggleRate}
        containerStyle={styles.player}
        showLeadingAvatar={false}
        timelineHorizontalInset={0}
      />
    </CardContainer>
  );
}
