import React, {memo, useCallback, useMemo} from 'react';
import {View} from 'react-native';
import {IconPlayerPause, IconPlayerPlay} from '@tabler/icons-react-native';
import Animated from 'react-native-reanimated';
import {IconButton} from '@components/_HuGo';
import {Typography} from '@components/_core';
import {formatSecondsToTime} from '@modules/chat/utils';
import {useAudioTrackPlayer} from '@modules/chats/contexts/AudioPlayerContext';
import {useCurrentTrack} from '@modules/chats/store/zustand/useTrackStateStore';
import {AudioTimeline} from '@modules/chats/components';
import {BARS_PER_SECOND} from '@modules/chats/hooks/useWaveformBarHeights';
import {useTheme} from '@shared/theme';

import {styles} from './styles';

// Extracts actual recorded bars and resamples via linear interpolation
// to align waveform visual with audio playback position
function stretchBarHeights(
  barHeights: number[],
  durationSec: number,
  targetCount: number,
): number[] {
  if (barHeights.length === 0 || durationSec <= 0) {
    return barHeights;
  }

  const actualCount = Math.min(
    Math.max(1, Math.round(durationSec * BARS_PER_SECOND)),
    barHeights.length,
  );

  // Recording filled the full waveform — nothing to stretch
  if (actualCount >= targetCount) {
    return barHeights;
  }

  // Actual recorded bars sit at the end of the array
  const actualBars = barHeights.slice(barHeights.length - actualCount);

  // Resample actualCount → targetCount using linear interpolation
  return Array.from({length: targetCount}, (_, i) => {
    if (actualCount === 1) {
      return actualBars[0];
    }
    const srcIdx = (i / (targetCount - 1)) * (actualCount - 1);
    const floorIdx = Math.floor(srcIdx);
    const ceilIdx = Math.min(floorIdx + 1, actualCount - 1);
    const frac = srcIdx - floorIdx;
    return actualBars[floorIdx] * (1 - frac) + actualBars[ceilIdx] * frac;
  });
}

interface Props {
  url: string;
  durationSec: number;
  normalizedBarsHeights: number[];
}

function VoiceRecordingPlayer({
  url,
  durationSec,
  normalizedBarsHeights,
}: Props) {
  const {theme} = useTheme();

  const stretchedBarHeights = useMemo(
    () =>
      stretchBarHeights(
        normalizedBarsHeights,
        durationSec,
        normalizedBarsHeights.length,
      ),
    [normalizedBarsHeights, durationSec],
  );

  const {play, pause, currentId, state, seekTo, initializePlaylist} =
    useAudioTrackPlayer();

  const progress = useCurrentTrack(url);

  const isPlaying = state?.isPlaying;

  const isCurrentActive = currentId === url;

  const onSeekTo = useCallback(
    (position: number) => {
      if (isCurrentActive) {
        seekTo(position);
      }
    },
    [isCurrentActive, seekTo],
  );

  const onPlay = () => {
    initializePlaylist([{uri: url, id: url}]);
    play({uri: url, id: url});
  };

  return (
    <Animated.View
      style={[
        styles.container,
        {backgroundColor: theme.background.layout.tertiary},
      ]}>
      <View style={styles.content}>
        <IconButton
          variant="tertiary"
          Icon={isCurrentActive && isPlaying ? IconPlayerPause : IconPlayerPlay}
          onPress={isCurrentActive && isPlaying ? pause : onPlay}
          useGestureHandler
        />
        <AudioTimeline
          duration={progress.duration ?? 0}
          progress={
            progress.duration ? progress.position / progress.duration : 0
          }
          onChangeProgress={onSeekTo}
          normalizedBarsHeights={stretchedBarHeights}
        />
        <Typography variant="xs">
          {formatSecondsToTime(
            Math.floor(isCurrentActive ? progress.position : durationSec),
            {
              minutesFormat: 'm',
            },
          )}
        </Typography>
      </View>
    </Animated.View>
  );
}

export default memo(VoiceRecordingPlayer);
