import * as React from 'react';
import { FC, useRef, useState, useEffect, MouseEvent } from 'react';
import { style } from 'typestyle';

interface VideoDurationBarProps {
  currentTime: number;
  duration: number;
  /** Called with the target time in seconds when the user clicks or drags the bar. */
  onSeek?: (time: number) => void;
  /** When true, positions the bar at the top of the container instead of the bottom. */
  positionTop?: boolean;
}

const VideoDurationBar: FC<VideoDurationBarProps> = ({ currentTime, duration, onSeek, positionTop }) => {
  const trackRef = useRef<HTMLDivElement>(null);
  const [isDragging, setIsDragging] = useState(false);
  const [isHovered, setIsHovered] = useState(false);
  const [dragRatio, setDragRatio] = useState<number | null>(null);

  const getRatioFromClientX = (clientX: number): number => {
    const track = trackRef.current;
    if (!track) return 0;
    const rect = track.getBoundingClientRect();
    return Math.max(0, Math.min(1, (clientX - rect.left) / rect.width));
  };

  const handleMouseDown = (e: React.MouseEvent<HTMLDivElement>) => {
    if (!onSeek || !duration) return;
    e.stopPropagation();
    e.preventDefault();
    setIsDragging(true);
    setDragRatio(getRatioFromClientX(e.clientX));
  };

  useEffect(() => {
    if (!isDragging) return;

    const handleMouseMove = (e: globalThis.MouseEvent) => {
      setDragRatio(getRatioFromClientX(e.clientX));
    };

    const handleMouseUp = (e: globalThis.MouseEvent) => {
      const ratio = getRatioFromClientX(e.clientX);
      setIsDragging(false);
      setDragRatio(null);
      if (onSeek && duration) onSeek(ratio * duration);
    };

    window.addEventListener('mousemove', handleMouseMove as EventListener);
    window.addEventListener('mouseup', handleMouseUp as EventListener);
    return () => {
      window.removeEventListener('mousemove', handleMouseMove as EventListener);
      window.removeEventListener('mouseup', handleMouseUp as EventListener);
    };
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [isDragging]);

  const displayRatio =
    isDragging && dragRatio !== null
      ? dragRatio
      : duration
      ? currentTime / duration
      : 0;

  const isSeekable = Boolean(onSeek && duration);

  return (
    <div className={`${styles.wrapper} ${positionTop ? styles.wrapperTop : ''}`} data-no-nav>
      <div
        ref={trackRef}
        className={`${styles.trackHitArea} ${isSeekable ? styles.trackSeekable : ''}`}
        onMouseDown={handleMouseDown}
        onMouseEnter={() => setIsHovered(true)}
        onMouseLeave={() => setIsHovered(false)}
        role={isSeekable ? 'slider' : 'progressbar'}
        aria-label="Video progress"
        aria-valuenow={Math.round(currentTime)}
        aria-valuemin={0}
        aria-valuemax={Math.round(duration) || 0}
        aria-valuetext={`${Math.round((currentTime / (duration || 1)) * 100)}%`}
        tabIndex={isSeekable ? 0 : -1}
        onKeyDown={isSeekable ? (e) => {
          if (!onSeek || !duration) return;
          const step = duration * 0.05; // 5% per keypress
          if (e.key === 'ArrowRight') { e.stopPropagation(); onSeek(Math.min(duration, currentTime + step)); }
          if (e.key === 'ArrowLeft')  { e.stopPropagation(); onSeek(Math.max(0, currentTime - step)); }
        } : undefined}
      >
        <div className={styles.track}>
          <div
            className={`${styles.fill} ${isDragging ? styles.fillDragging : ''}`}
            style={{ width: `${displayRatio * 100}%` }}
          >
            {isSeekable ? <div className={styles.thumb} style={{ opacity: isHovered || isDragging ? 1 : 0 }} /> : null}
          </div>
        </div>
      </div>
    </div>
  );
};

export default VideoDurationBar;

const styles = {
  wrapper: style({
    position: 'absolute',
    bottom: 0,
    left: 0,
    width: '100%',
    display: 'flex',
    alignItems: 'center',
    padding: '6px 0 0',
    boxSizing: 'border-box' as const,
    zIndex: 10,
  }),
  wrapperTop: style({
    bottom: 'unset',
    top: 0,
    padding: '0',
  }),
  /** Expanded hit area so small movements are easy to target */
  trackHitArea: style({
    flex: 1,
    padding: '6px 0',
    margin: '-6px 0',
    display: 'flex',
    alignItems: 'center',
    outline: 'none',
  }),
  trackSeekable: style({
    cursor: 'pointer',
  }),
  track: style({
    width: '100%',
    height: 5,
    borderRadius: 3,
    backgroundColor: 'rgba(255, 255, 255, 0.25)',
    overflow: 'visible',
    position: 'relative',
  }),
  fill: style({
    height: '100%',
    borderRadius: 3,
    backgroundColor: 'rgba(255, 255, 255, 0.9)',
    transition: 'width 0.25s linear',
    position: 'relative',
  }),
  fillDragging: style({
    // Disable the smooth transition while dragging for immediate feedback
    transition: 'none',
  }),
  thumb: style({
    position: 'absolute',
    right: -5,
    top: '50%',
    transform: 'translateY(-50%)',
    width: 10,
    height: 10,
    borderRadius: '50%',
    backgroundColor: 'white',
    transition: 'opacity 0.15s ease',
    pointerEvents: 'none',
  }),
};
