import React, { ChangeEvent, useEffect, useRef, useState } from "react";
import DragableBox from "./DragableBox";
import { Coordinates } from "~/types";

type ContainerDimensions = {
  height: number;
  width: number;
}

export default function CropSelector() {
  const [firstDragable, setFirstDragable] = useState<Coordinates>({
    x: 0,
    y: 0
  });
  const [secondDragable, setSecondDragable] = useState<Coordinates>({
    x: 100,
    y: 100
  });
  const [selectorPosition, setSelectorPosition] = useState<Coordinates>({
    x: 0,
    y: 0
  });
  const [containerSize, setContainerSize] = useState<ContainerDimensions>({
    height: 0,
    width: 0
  });
  const [userInputs, setUserInputs] = useState<ContainerDimensions>({
    height: 100,
    width: 100
  });

  const containerRef = useRef<HTMLDivElement>(null);

  useEffect(() => {
    setSelectorPosition({
      x: Math.min(firstDragable.x, secondDragable.x),
      y: Math.min(firstDragable.y, secondDragable.y)
    });
  }, [firstDragable, secondDragable]);

  useEffect(() => {
    if (!containerRef.current) return;

    const resizeObserver = new ResizeObserver(entries => {
      const entry = entries[0];
      setContainerSize({
        width: entry.contentRect.width,
        height: entry.contentRect.height
      });
    });

    resizeObserver.observe(containerRef.current);

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

  const selectorWidth = Math.abs(secondDragable.x - firstDragable.x);
  const selectorHeight = Math.abs(secondDragable.y - firstDragable.y);

  const handleSelectorDrag = (newPosition: Coordinates) => {
    const deltaX = newPosition.x - selectorPosition.x;
    const deltaY = newPosition.y - selectorPosition.y;

    const newFirstX = Math.min(firstDragable.x, secondDragable.x) + deltaX;
    const newFirstY = Math.min(firstDragable.y, secondDragable.y) + deltaY;
    const newSecondX = Math.max(firstDragable.x, secondDragable.x) + deltaX;
    const newSecondY = Math.max(firstDragable.y, secondDragable.y) + deltaY;

    // Ensure the selector stays within container bounds
    if (newFirstX >= 0 && newSecondX <= containerSize.width &&
        newFirstY >= 0 && newSecondY <= containerSize.height) {
      setFirstDragable({
        x: newFirstX,
        y: newFirstY
      });
      setSecondDragable({
        x: newSecondX,
        y: newSecondY
      });
    }
  };

  const handleDimensionChange = (
    dimension: 'width' | 'height',
    event: React.ChangeEvent<HTMLInputElement>
  ) => {
    const value = Math.max(0, parseInt(event.target.value) || 0);
    const maxValue = dimension === 'width' ? containerSize.width : containerSize.height;
    const clampedValue = Math.min(value, maxValue);

    setUserInputs(prev => ({
      ...prev,
      [dimension]: clampedValue
    }));

    // Update selector dimensions
    if (dimension === 'width') {
      const newX = Math.min(firstDragable.x, containerSize.width - clampedValue);
      setFirstDragable(prev => ({ ...prev, x: newX }));
      setSecondDragable(prev => ({ ...prev, x: newX + clampedValue }));
    } else {
      const newY = Math.min(firstDragable.y, containerSize.height - clampedValue);
      setFirstDragable(prev => ({ ...prev, y: newY }));
      setSecondDragable(prev => ({ ...prev, y: newY + clampedValue }));
    }
  };

  // Update user inputs when dragging
  useEffect(() => {
    setUserInputs({
      width: Math.round(selectorWidth),
      height: Math.round(selectorHeight)
    });
  }, [selectorWidth, selectorHeight]);

  return (
    <div className="flex flex-col h-screen w-screen justify-center items-center gap-4">
      <div ref={containerRef} className="relative w-1/3 h-1/3 border-black border">
        <DragableBox
          position={selectorPosition}
          mode="box"
          width={selectorWidth}
          height={selectorHeight}
          coordSetter={setSelectorPosition}
          onDrag={handleSelectorDrag}
          className="border border-black"
        />
        <DragableBox position={firstDragable} coordSetter={setFirstDragable} mode="handle">
          <div className="bg-red-600 h-2 w-2 rounded-full hover:scale-125" />
        </DragableBox>
        <DragableBox position={secondDragable} coordSetter={setSecondDragable} mode="handle">
          <div className="bg-red-600 h-2 w-2 rounded-full hover:scale-125" />
        </DragableBox>
      </div>
      
      <div className="flex gap-4">
        <div className="flex flex-col gap-2">
          <label htmlFor="width">Width (px)</label>
          <input
            id="width"
            type="number"
            min={0}
            max={containerSize.width}
            value={userInputs.width.toFixed()}
            onChange={(e: ChangeEvent<HTMLInputElement>) => handleDimensionChange('width', e)}
            className="w-24"
          />
        </div>
        <div className="flex flex-col gap-2">
          <label htmlFor="height">Height (px)</label>
          <input
            id="height"
            type="number"
            min={0}
            max={containerSize.height}
            value={userInputs.height.toFixed()}
            onChange={(e) => handleDimensionChange('height', e)}
            className="w-24"
          />
        </div>
      </div>
    </div>
  );
}
