import React, { useRef, useCallback, useState } from 'react';
import { Box, Text, toRem, color } from 'folds';

/**
 * Props for the AngleSelector component
 */
export interface AngleSelectorProps {
  /** Current angle in degrees (0-360) */
  value: number;
  /** Callback when angle changes */
  onChange: (angle: number) => void;
  /** Size of the selector in pixels */
  size?: number;
  /** Whether the component is disabled */
  disabled?: boolean;
}

/**
 * A circular angle selector similar to Photoshop's drop shadow angle control.
 * Click or drag around the circle to set an angle in degrees.
 */
export function AngleSelector({
  value,
  onChange,
  size = 80,
  disabled = false,
}: AngleSelectorProps): JSX.Element {
  const containerRef = useRef<HTMLDivElement>(null);
  const [isDragging, setIsDragging] = useState(false);

  /**
   * Calculate angle from mouse/touch position relative to center
   */
  const calculateAngle = useCallback(
    (clientX: number, clientY: number) => {
      if (!containerRef.current) return value;

      const rect = containerRef.current.getBoundingClientRect();
      const centerX = rect.left + rect.width / 2;
      const centerY = rect.top + rect.height / 2;

      const deltaX = clientX - centerX;
      const deltaY = clientY - centerY;

      // Calculate angle in radians, then convert to degrees
      // atan2 returns angle from -PI to PI, where 0 is pointing right
      // We adjust so 0deg is pointing up (like CSS gradients)
      let angle = Math.atan2(deltaX, -deltaY) * (180 / Math.PI);

      // Normalize to 0-360 range
      if (angle < 0) angle += 360;

      return Math.round(angle);
    },
    [value]
  );

  /**
   * Handle mouse/touch start
   */
  const handlePointerDown = useCallback(
    (e: React.PointerEvent<HTMLDivElement>) => {
      if (disabled) return;
      e.preventDefault();
      setIsDragging(true);
      (e.target as HTMLElement).setPointerCapture(e.pointerId);
      const newAngle = calculateAngle(e.clientX, e.clientY);
      onChange(newAngle);
    },
    [disabled, calculateAngle, onChange]
  );

  /**
   * Handle mouse/touch move
   */
  const handlePointerMove = useCallback(
    (e: React.PointerEvent<HTMLDivElement>) => {
      if (!isDragging || disabled) return;
      const newAngle = calculateAngle(e.clientX, e.clientY);
      onChange(newAngle);
    },
    [isDragging, disabled, calculateAngle, onChange]
  );

  /**
   * Handle mouse/touch end
   */
  const handlePointerUp = useCallback(() => {
    setIsDragging(false);
  }, []);

  // Calculate line endpoint position
  const lineLength = (size / 2) - 8;
  const radians = ((value - 90) * Math.PI) / 180;
  const lineX = Math.cos(radians) * lineLength;
  const lineY = Math.sin(radians) * lineLength;

  return (
    <Box direction="Column" gap="100" alignItems="Center">
      <Box
        ref={containerRef}
        onPointerDown={handlePointerDown}
        onPointerMove={handlePointerMove}
        onPointerUp={handlePointerUp}
        onPointerLeave={handlePointerUp}
        style={{
          width: toRem(size),
          height: toRem(size),
          borderRadius: '50%',
          border: `${toRem(2)} solid ${color.Surface.ContainerLine}`,
          backgroundColor: color.Surface.Container,
          position: 'relative',
          cursor: disabled ? 'not-allowed' : 'pointer',
          opacity: disabled ? 0.5 : 1,
          touchAction: 'none',
          userSelect: 'none',
        }}
      >
        {/* Center dot */}
        <Box
          style={{
            position: 'absolute',
            top: '50%',
            left: '50%',
            transform: 'translate(-50%, -50%)',
            width: toRem(6),
            height: toRem(6),
            borderRadius: '50%',
            backgroundColor: color.Secondary.Main,
          }}
        />
        {/* Direction line */}
        <Box
          style={{
            position: 'absolute',
            top: '50%',
            left: '50%',
            width: toRem(2),
            height: toRem(lineLength),
            backgroundColor: color.Primary.Main,
            transformOrigin: 'center top',
            transform: `translate(-50%, 0) rotate(${value}deg)`,
            borderRadius: toRem(1),
          }}
        />
        {/* Angle indicator dot at end of line */}
        <Box
          style={{
            position: 'absolute',
            top: '50%',
            left: '50%',
            width: toRem(10),
            height: toRem(10),
            borderRadius: '50%',
            backgroundColor: color.Primary.Main,
            transform: `translate(calc(-50% + ${lineX}px), calc(-50% + ${lineY}px))`,
            boxShadow: `0 0 ${toRem(4)} ${color.Primary.Main}`,
          }}
        />
        {/* Cardinal direction markers */}
        {[0, 90, 180, 270].map((deg) => {
          const markerRadians = ((deg - 90) * Math.PI) / 180;
          const markerDist = (size / 2) - 3;
          const markerX = Math.cos(markerRadians) * markerDist;
          const markerY = Math.sin(markerRadians) * markerDist;
          return (
            <Box
              key={deg}
              style={{
                position: 'absolute',
                top: '50%',
                left: '50%',
                width: toRem(4),
                height: toRem(4),
                borderRadius: '50%',
                backgroundColor: color.Surface.OnContainer,
                opacity: 0.3,
                transform: `translate(calc(-50% + ${markerX}px), calc(-50% + ${markerY}px))`,
              }}
            />
          );
        })}
      </Box>
      <Text size="T200">{value}°</Text>
    </Box>
  );
}

export default AngleSelector;
