import type { Meta, StoryObj } from '@storybook/react';
import { useCallback, useRef, useState } from 'react';
import { twMerge } from 'tailwind-merge';

import { formatDuration } from '@/components/song/songUtils';
import usePolledValue from '@/hooks/usePolledValue';

import PlaybackProgress, { PlaybackProgressProps } from './PlaybackProgress';
import PlaybackProgressHoverOverlay, {
  PlaybackProgressHoverOverlayProps,
} from './PlaybackProgressHoverOverlay';

type PagePropsAndCustomArgs = PlaybackProgressProps & {
  startTime?: number;
  isPlaying?: boolean;
};

const meta: Meta<PagePropsAndCustomArgs> = {
  title: 'components/PlaybackProgress/TimeDurationHover',
  component: PlaybackProgress,
};

export default meta;
type Story = StoryObj<PagePropsAndCustomArgs>;

const PlaybackProgressTestTooltip = (
  props: PlaybackProgressHoverOverlayProps
) => {
  const {
    currentTime,
    duration,
    hoverTime,
    x,
    y,
    width,
    height,
    isHovered,
    disabled,
    className,
    ...restProps
  } = props;

  const tooltipStyle =
    !isHovered || hoverTime == null || x == null || y == null || width == null
      ? {}
      : {
          left: `${x}px`,
          bottom: '100%', // Position above the progress bar
          transform: 'translateX(-50%)', // Center horizontally
        };

  if (!isHovered || hoverTime == null || disabled) {
    return null;
  }

  return (
    <div
      className={twMerge(
        'pointer-events-none absolute z-50',
        'px-2 py-1 text-xs',
        'bg-background-fog-dense text-foreground-primary-glass',
        'rounded border border-border-primary-glass',
        'shadow-lg',
        'mb-1', // Add small margin to separate from progress bar
        className
      )}
      style={tooltipStyle}
      {...restProps}
    >
      {formatDuration(hoverTime)} / {formatDuration(duration)}
    </div>
  );
};

const PlaybackProgressTest = (
  props: PlaybackProgressProps & { startTime?: number; isPlaying?: boolean }
) => {
  const {
    isPlaying = true,
    startTime = 0,
    duration = 60,
    renderTooltip,
    ...restProps
  } = props;

  const [isSeeking, setIsSeeking] = useState(false);
  const stateRef = useRef({
    startTime,
    duration,
  });

  const getCurrentProgress = useCallback(() => {
    const time = (performance.now() - stateRef.current.startTime) / 1000;
    if (time >= duration) {
      stateRef.current.startTime = performance.now();
      return 0;
    }
    return time;
  }, [duration]);

  const [currentTime, updateCurrentProgress] = usePolledValue(
    getCurrentProgress,
    {
      enabled: isPlaying && !isSeeking,
      pollingInterval: 16,
    }
  );

  const handleSeekStart = useCallback(() => {
    setIsSeeking(true);
  }, []);
  const handleSeekEnd = useCallback(() => {
    setIsSeeking(false);
  }, []);
  const handleSeekTo = useCallback(
    (time: number | null) => {
      if (time != null) {
        stateRef.current.startTime = performance.now() - time * 1000;
        updateCurrentProgress();
      }
    },
    [updateCurrentProgress]
  );

  return (
    <div className='fixed inset-0 flex flex-col items-stretch justify-center'>
      <PlaybackProgress
        className='w-full'
        currentTime={currentTime}
        duration={duration}
        onSeekStart={handleSeekStart}
        onSeekEnd={handleSeekEnd}
        onSeekMove={handleSeekTo}
        onSeekTo={handleSeekTo}
        renderTooltip={renderTooltip}
        {...restProps}
      />
    </div>
  );
};

export const Default: Story = {
  render: (args) => {
    return (
      <PlaybackProgressTest
        renderTooltip={PlaybackProgressHoverOverlay}
        {...args}
      />
    );
  },
  args: {
    isPlaying: false,
    startTime: 50,
    duration: 150,
  },
};

export const CustomTooltip: Story = {
  render: (args) => (
    <PlaybackProgressTest
      // custom component extracted from above
      renderTooltip={PlaybackProgressTestTooltip}
      {...args}
    />
  ),
  args: {
    className: '[--button-width:0px] [--track-width:2px]',
    isPlaying: false,
    startTime: 50,
    duration: 150,
    showTime: false,
  },
};
