'use client';

import * as React from 'react';
import { cn } from '@/lib/utils/cn';
import {
  timeToPixel,
  pixelToTime,
  calculateTickInterval,
  formatTimeLabel,
  getVisibleTimeRange,
} from '@/lib/utils/timeline';

export interface TimeScaleProps {
  duration: number;
  zoom: number;
  currentTime: number;
  onSeek?: (time: number) => void;
  className?: string;
  height?: number;
  controlsWidth?: number;
  scrollRef?: React.MutableRefObject<HTMLDivElement | null>;
  onScroll?: () => void;
}

export function TimeScale({
  duration,
  zoom,
  currentTime,
  onSeek,
  className,
  height = 40,
  controlsWidth = 240,
  scrollRef: externalScrollRef,
  onScroll,
}: TimeScaleProps) {
  const localScrollRef = React.useRef<HTMLDivElement>(null);
  const scrollRef = externalScrollRef || localScrollRef;
  const canvasRef = React.useRef<HTMLCanvasElement>(null);
  const [viewportWidth, setViewportWidth] = React.useState(800);
  const [scrollLeft, setScrollLeft] = React.useState(0);
  const [hoverTime, setHoverTime] = React.useState<number | null>(null);

  // Calculate total timeline width (match waveform calculation)
  // Uses 5 pixels per second as base scale, multiplied by zoom
  // Always ensure minimum width is at least viewport width for full coverage
  const PIXELS_PER_SECOND_BASE = 5;
  const totalWidth = React.useMemo(() => {
    if (zoom >= 1) {
      const calculatedWidth = duration * zoom * PIXELS_PER_SECOND_BASE;
      // Ensure it's at least viewport width so timeline always fills
      return Math.max(calculatedWidth, viewportWidth);
    }
    return viewportWidth;
  }, [duration, zoom, viewportWidth]);

  // Update viewport width on resize
  React.useEffect(() => {
    const scroller = scrollRef.current;
    if (!scroller) return;

    const updateWidth = () => {
      setViewportWidth(scroller.clientWidth);
    };

    updateWidth();

    const resizeObserver = new ResizeObserver(updateWidth);
    resizeObserver.observe(scroller);

    return () => resizeObserver.disconnect();
  }, [scrollRef]);

  // Handle scroll - update scrollLeft and trigger onScroll callback
  const handleScroll = React.useCallback(() => {
    if (scrollRef.current) {
      setScrollLeft(scrollRef.current.scrollLeft);
    }
    if (onScroll) {
      onScroll();
    }
  }, [onScroll, scrollRef]);

  // Draw time scale - redraws on scroll and zoom
  React.useEffect(() => {
    const canvas = canvasRef.current;
    if (!canvas || duration === 0) return;

    const ctx = canvas.getContext('2d');
    if (!ctx) return;

    // Set canvas size to viewport width
    const dpr = window.devicePixelRatio || 1;
    canvas.width = viewportWidth * dpr;
    canvas.height = height * dpr;
    canvas.style.width = `${viewportWidth}px`;
    canvas.style.height = `${height}px`;
    ctx.scale(dpr, dpr);

    // Clear canvas
    ctx.fillStyle = getComputedStyle(canvas).getPropertyValue('--color-background') || '#ffffff';
    ctx.fillRect(0, 0, viewportWidth, height);

    // Calculate visible time range
    const visibleRange = getVisibleTimeRange(scrollLeft, viewportWidth, duration, zoom);
    const visibleDuration = visibleRange.end - visibleRange.start;

    // Calculate tick intervals based on visible duration
    const { major, minor } = calculateTickInterval(visibleDuration);

    // Calculate which ticks to draw (only visible ones)
    const startTick = Math.floor(visibleRange.start / minor) * minor;
    const endTick = Math.ceil(visibleRange.end / minor) * minor;

    // Set up text style for labels
    ctx.font = '12px -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif';
    ctx.textAlign = 'center';
    ctx.textBaseline = 'top';

    // Draw ticks and labels
    for (let time = startTick; time <= endTick; time += minor) {
      if (time < 0 || time > duration) continue;

      // Calculate x position using the actual totalWidth (not timeToPixel which recalculates)
      const x = (time / duration) * totalWidth - scrollLeft;
      if (x < 0 || x > viewportWidth) continue;

      const isMajor = Math.abs(time % major) < 0.001;

      if (isMajor) {
        // Major ticks - tall and prominent
        ctx.strokeStyle = getComputedStyle(canvas).getPropertyValue('--color-foreground') || '#000000';
        ctx.lineWidth = 2;
        ctx.beginPath();
        ctx.moveTo(x, height - 20);
        ctx.lineTo(x, height);
        ctx.stroke();

        // Major tick label
        ctx.fillStyle = getComputedStyle(canvas).getPropertyValue('--color-foreground') || '#000000';
        const label = formatTimeLabel(time, visibleDuration < 10);
        ctx.fillText(label, x, 6);
      } else {
        // Minor ticks - shorter and lighter
        ctx.strokeStyle = getComputedStyle(canvas).getPropertyValue('--color-muted-foreground') || '#9ca3af';
        ctx.lineWidth = 1;
        ctx.beginPath();
        ctx.moveTo(x, height - 10);
        ctx.lineTo(x, height);
        ctx.stroke();

        // Minor tick label (smaller and lighter)
        if (x > 20 && x < viewportWidth - 20) {
          ctx.fillStyle = getComputedStyle(canvas).getPropertyValue('--color-muted-foreground') || '#9ca3af';
          ctx.font = '10px -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif';
          const label = formatTimeLabel(time, visibleDuration < 10);
          ctx.fillText(label, x, 8);
          ctx.font = '12px -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif';
        }
      }
    }

    // Draw playhead indicator
    const playheadX = (currentTime / duration) * totalWidth - scrollLeft;
    if (playheadX >= 0 && playheadX <= viewportWidth) {
      ctx.strokeStyle = '#ef4444';
      ctx.lineWidth = 2;
      ctx.beginPath();
      ctx.moveTo(playheadX, 0);
      ctx.lineTo(playheadX, height);
      ctx.stroke();
    }

    // Draw hover indicator
    if (hoverTime !== null) {
      const hoverX = (hoverTime / duration) * totalWidth - scrollLeft;
      if (hoverX >= 0 && hoverX <= viewportWidth) {
        ctx.strokeStyle = 'rgba(59, 130, 246, 0.5)';
        ctx.lineWidth = 1;
        ctx.setLineDash([3, 3]);
        ctx.beginPath();
        ctx.moveTo(hoverX, 0);
        ctx.lineTo(hoverX, height);
        ctx.stroke();
        ctx.setLineDash([]);
      }
    }
  }, [duration, zoom, currentTime, viewportWidth, scrollLeft, height, hoverTime, totalWidth]);

  // Handle click to seek
  const handleClick = React.useCallback(
    (e: React.MouseEvent<HTMLCanvasElement>) => {
      if (!onSeek) return;

      const rect = e.currentTarget.getBoundingClientRect();
      const x = e.clientX - rect.left;
      const pixelPos = x + scrollLeft;
      const time = (pixelPos / totalWidth) * duration;

      onSeek(Math.max(0, Math.min(duration, time)));
    },
    [onSeek, duration, totalWidth, scrollLeft]
  );

  // Handle mouse move for hover
  const handleMouseMove = React.useCallback(
    (e: React.MouseEvent<HTMLCanvasElement>) => {
      const rect = e.currentTarget.getBoundingClientRect();
      const x = e.clientX - rect.left;
      const pixelPos = x + scrollLeft;
      const time = (pixelPos / totalWidth) * duration;

      setHoverTime(Math.max(0, Math.min(duration, time)));
    },
    [duration, totalWidth, scrollLeft]
  );

  const handleMouseLeave = React.useCallback(() => {
    setHoverTime(null);
  }, []);

  return (
    <div className={cn('relative bg-background', className)} style={{ paddingLeft: '240px', paddingRight: '240px' }}>
      <div
        ref={scrollRef}
        className="w-full bg-background overflow-x-auto overflow-y-hidden custom-scrollbar"
        style={{
          height: `${height}px`,
        }}
        onScroll={handleScroll}
      >
        {/* Spacer to create scrollable width */}
        <div style={{ width: `${totalWidth}px`, height: `${height}px`, position: 'relative' }}>
          <canvas
            ref={canvasRef}
            onClick={handleClick}
            onMouseMove={handleMouseMove}
            onMouseLeave={handleMouseLeave}
            className="cursor-pointer"
            style={{
              position: 'sticky',
              left: 0,
              width: `${viewportWidth}px`,
              height: `${height}px`,
            }}
          />
        </div>
      </div>

      {/* Hover tooltip */}
      {hoverTime !== null && (
        <div
          className="absolute top-full mt-1 px-2 py-1 bg-popover border border-border rounded shadow-lg text-xs font-mono pointer-events-none z-10"
          style={{
            left: `${Math.min(
              viewportWidth - 60,
              Math.max(0, (hoverTime / duration) * totalWidth - scrollLeft - 30)
            )}px`,
          }}
        >
          {formatTimeLabel(hoverTime, true)}
        </div>
      )}
    </div>
  );
}
