"use client";

import { useRef, useEffect, useCallback, RefObject } from "react";
import { useReviewStore } from "@/hooks/use-review-player";
import { frameToPosition } from "@/lib/frame-utils";
import type { CommentWithReplies } from "@/types";

interface FrameTimelineProps {
  fps: number;
  comments: CommentWithReplies[];
  annotations?: { frameNumber: number }[];
  videoRef: RefObject<HTMLVideoElement | null>;
  onSeek: (frame: number) => void;
}

export function FrameTimeline({ fps, comments, annotations = [], videoRef, onSeek }: FrameTimelineProps) {
  const canvasRef = useRef<HTMLCanvasElement>(null);
  const isDragging = useRef(false);
  const { currentFrame, totalFrames } = useReviewStore();

  const draw = useCallback(() => {
    const canvas = canvasRef.current;
    if (!canvas) return;
    const ctx = canvas.getContext("2d");
    if (!ctx) return;

    const W = canvas.width;
    const H = canvas.height;
    ctx.clearRect(0, 0, W, H);

    // Background
    ctx.fillStyle = "hsl(0 0% 6%)";
    ctx.fillRect(0, 0, W, H);

    // Frame ruler ticks
    if (totalFrames > 0) {
      const tickInterval = Math.max(1, Math.floor(totalFrames / (W / 40)));

      ctx.strokeStyle = "hsl(0 0% 20%)";
      ctx.lineWidth = 1;
      ctx.fillStyle = "hsl(0 0% 35%)";
      ctx.font = "9px monospace";
      ctx.textAlign = "center";

      for (let f = 0; f <= totalFrames; f += tickInterval) {
        const x = Math.round((f / totalFrames) * W);
        const isMajor = f % (tickInterval * 5) === 0 || tickInterval > 20;

        ctx.strokeStyle = isMajor ? "hsl(0 0% 22%)" : "hsl(0 0% 16%)";
        ctx.beginPath();
        ctx.moveTo(x, isMajor ? 0 : H / 2);
        ctx.lineTo(x, H);
        ctx.stroke();

        if (isMajor && f > 0) {
          ctx.fillStyle = "hsl(0 0% 35%)";
          ctx.fillText(String(f), x, 11);
        }
      }
    }

    // Annotation markers — amber diamonds at top
    const seenAnnotationFrames = new Set<number>();
    annotations.forEach((ann) => {
      if (totalFrames === 0) return;
      if (seenAnnotationFrames.has(ann.frameNumber)) return;
      seenAnnotationFrames.add(ann.frameNumber);
      const x = Math.round(frameToPosition(ann.frameNumber, totalFrames) * W);
      // Amber diamond
      ctx.fillStyle = "hsl(38 92% 50%)";
      ctx.beginPath();
      ctx.moveTo(x, 2);
      ctx.lineTo(x + 4, 7);
      ctx.lineTo(x, 12);
      ctx.lineTo(x - 4, 7);
      ctx.closePath();
      ctx.fill();
    });

    // Comment markers — blue triangles pointing down from top
    comments.forEach((comment) => {
      if (totalFrames === 0) return;
      const x = Math.round(frameToPosition(comment.frameNumber, totalFrames) * W);

      if (comment.isResolved) {
        ctx.fillStyle = "hsl(142 71% 45% / 0.7)";
      } else {
        ctx.fillStyle = "hsl(213 94% 68%)";
      }

      // Triangle marker pointing down from top
      ctx.beginPath();
      ctx.moveTo(x - 4, 0);
      ctx.lineTo(x + 4, 0);
      ctx.lineTo(x, 8);
      ctx.closePath();
      ctx.fill();
    });

    // Playhead
    if (totalFrames > 0) {
      const playheadX = Math.round(
        frameToPosition(currentFrame, totalFrames) * W
      );

      // Red line
      ctx.strokeStyle = "hsl(0 72% 51%)";
      ctx.lineWidth = 2;
      ctx.beginPath();
      ctx.moveTo(playheadX, 0);
      ctx.lineTo(playheadX, H);
      ctx.stroke();

      // Red diamond at top
      ctx.fillStyle = "hsl(0 72% 51%)";
      ctx.beginPath();
      ctx.moveTo(playheadX, H - 4);
      ctx.lineTo(playheadX - 5, H - 10);
      ctx.lineTo(playheadX, H - 16);
      ctx.lineTo(playheadX + 5, H - 10);
      ctx.closePath();
      ctx.fill();
    }
  }, [currentFrame, totalFrames, comments, annotations]);

  // Resize observer to match canvas to container
  useEffect(() => {
    const canvas = canvasRef.current;
    if (!canvas) return;

    const observer = new ResizeObserver(() => {
      canvas.width = canvas.offsetWidth;
      canvas.height = canvas.offsetHeight;
      draw();
    });
    observer.observe(canvas);
    return () => observer.disconnect();
  }, [draw]);

  useEffect(() => {
    draw();
  }, [draw]);

  // Seek on click/drag
  const getFrameFromEvent = useCallback(
    (e: React.MouseEvent | MouseEvent): number => {
      const canvas = canvasRef.current;
      if (!canvas || totalFrames === 0) return 0;
      const rect = canvas.getBoundingClientRect();
      const x = Math.max(0, Math.min(e.clientX - rect.left, rect.width));
      return Math.round((x / rect.width) * totalFrames);
    },
    [totalFrames]
  );

  const handleMouseDown = (e: React.MouseEvent) => {
    isDragging.current = true;
    onSeek(getFrameFromEvent(e));
  };

  const handleMouseMove = useCallback(
    (e: MouseEvent) => {
      if (!isDragging.current) return;
      onSeek(getFrameFromEvent(e));
    },
    [getFrameFromEvent, onSeek]
  );

  const handleMouseUp = useCallback(() => {
    isDragging.current = false;
  }, []);

  useEffect(() => {
    window.addEventListener("mousemove", handleMouseMove);
    window.addEventListener("mouseup", handleMouseUp);
    return () => {
      window.removeEventListener("mousemove", handleMouseMove);
      window.removeEventListener("mouseup", handleMouseUp);
    };
  }, [handleMouseMove, handleMouseUp]);

  return (
    <canvas
      ref={canvasRef}
      className="frame-timeline w-full cursor-ew-resize"
      style={{ height: 48 }}
      onMouseDown={handleMouseDown}
    />
  );
}
