'use client';

import { useCallback, useMemo, useRef, useState } from 'react';
import { cn } from '@/lib/utils';
import { AutomationPoint } from '@/types/audio';

interface AutomationLaneProps {
  label: string;
  icon?: React.ReactNode;
  points: AutomationPoint[];
  durationBars: number;
  pixelsPerBar: number;
  height?: number;
  onAddPoint: (bar: number, beat: number, value: number) => void;
  onUpdatePoint: (id: string, bar: number, beat: number, value: number) => void;
  onDeletePoint: (id: string) => void;
  className?: string;
}

export function AutomationLane({
  label,
  icon,
  points,
  durationBars,
  pixelsPerBar,
  height = 48,
  onAddPoint,
  onUpdatePoint,
  onDeletePoint,
  className,
}: AutomationLaneProps) {
  const containerRef = useRef<HTMLDivElement>(null);
  const [draggingId, setDraggingId] = useState<string | null>(null);
  const [selectedId, setSelectedId] = useState<string | null>(null);

  const pixelsPerBeat = pixelsPerBar / 4;
  const width = durationBars * pixelsPerBar;

  const sortedPoints = useMemo(() => {
    return [...points].sort((a, b) => {
      if (a.bar !== b.bar) return a.bar - b.bar;
      return a.beat - b.beat;
    });
  }, [points]);

  const pathD = useMemo(() => {
    if (sortedPoints.length === 0) return '';

    const toX = (bar: number, beat: number) => bar * pixelsPerBar + beat * pixelsPerBeat;
    const toY = (value: number) => height - value * height;

    let d = `M 0 ${toY(sortedPoints[0]?.value ?? 0.5)}`;

    if (sortedPoints.length > 0) {
      d = `M ${toX(sortedPoints[0].bar, sortedPoints[0].beat)} ${toY(sortedPoints[0].value)}`;

      for (let i = 1; i < sortedPoints.length; i++) {
        const p = sortedPoints[i];
        d += ` L ${toX(p.bar, p.beat)} ${toY(p.value)}`;
      }
    }

    return d;
  }, [sortedPoints, pixelsPerBar, pixelsPerBeat, height]);

  const handleContainerClick = useCallback(
    (e: React.MouseEvent<HTMLDivElement>) => {
      if (draggingId) return;

      const rect = e.currentTarget.getBoundingClientRect();
      const x = e.clientX - rect.left;
      const y = e.clientY - rect.top;

      const totalBeats = x / pixelsPerBeat;
      const bar = Math.floor(totalBeats / 4);
      const beat = Math.floor(totalBeats % 4);
      const value = Math.max(0, Math.min(1, 1 - y / height));

      if (bar >= 0 && bar < durationBars) {
        onAddPoint(bar, beat, value);
      }
    },
    [draggingId, pixelsPerBeat, height, durationBars, onAddPoint]
  );

  const handlePointMouseDown = useCallback(
    (point: AutomationPoint, e: React.MouseEvent) => {
      e.preventDefault();
      e.stopPropagation();
      setDraggingId(point.id);
      setSelectedId(point.id);

      const handleMouseMove = (e: MouseEvent) => {
        if (!containerRef.current) return;

        const rect = containerRef.current.getBoundingClientRect();
        const x = e.clientX - rect.left;
        const y = e.clientY - rect.top;

        const totalBeats = Math.max(0, x / pixelsPerBeat);
        const bar = Math.min(durationBars - 1, Math.floor(totalBeats / 4));
        const beat = Math.floor(totalBeats % 4);
        const value = Math.max(0, Math.min(1, 1 - y / height));

        onUpdatePoint(point.id, bar, beat, value);
      };

      const handleMouseUp = () => {
        setDraggingId(null);
        document.removeEventListener('mousemove', handleMouseMove);
        document.removeEventListener('mouseup', handleMouseUp);
      };

      document.addEventListener('mousemove', handleMouseMove);
      document.addEventListener('mouseup', handleMouseUp);
    },
    [pixelsPerBeat, height, durationBars, onUpdatePoint]
  );

  const handlePointContextMenu = useCallback(
    (point: AutomationPoint, e: React.MouseEvent) => {
      e.preventDefault();
      e.stopPropagation();
      onDeletePoint(point.id);
    },
    [onDeletePoint]
  );

  return (
    <div className={cn('relative', className)}>
      <div className="absolute left-0 top-0 bottom-0 w-20 flex items-center gap-1.5 px-2 bg-card/50 border-r border-border/50 z-10">
        {icon}
        <span className="text-xs font-medium text-muted-foreground truncate">
          {label}
        </span>
      </div>

      <div
        ref={containerRef}
        className="ml-20 bg-muted/10 border-b border-border/30 cursor-crosshair relative"
        style={{ width, height }}
        onClick={handleContainerClick}
      >
        {Array.from({ length: durationBars }, (_, i) => (
          <div
            key={i}
            className={cn(
              'absolute top-0 bottom-0 border-l',
              i % 4 === 0 ? 'border-border/30' : 'border-border/10'
            )}
            style={{ left: i * pixelsPerBar }}
          />
        ))}

        <svg
          className="absolute inset-0 pointer-events-none"
          width={width}
          height={height}
        >
          {pathD && (
            <path
              d={pathD}
              fill="none"
              stroke="var(--lofi-orange)"
              strokeWidth={2}
              strokeLinecap="round"
              strokeLinejoin="round"
            />
          )}
        </svg>

        {sortedPoints.map((point) => {
          const x = point.bar * pixelsPerBar + point.beat * pixelsPerBeat;
          const y = height - point.value * height;

          return (
            <div
              key={point.id}
              className={cn(
                'absolute w-3 h-3 rounded-full cursor-move',
                'transform -translate-x-1/2 -translate-y-1/2',
                'border-2 transition-transform',
                selectedId === point.id
                  ? 'bg-lofi-orange border-white scale-125'
                  : 'bg-lofi-orange/80 border-lofi-orange hover:scale-110',
                draggingId === point.id && 'scale-125'
              )}
              style={{ left: x, top: y }}
              onMouseDown={(e) => handlePointMouseDown(point, e)}
              onContextMenu={(e) => handlePointContextMenu(point, e)}
            />
          );
        })}
      </div>
    </div>
  );
}
