"use client";

import React, { useState, useRef, useCallback } from "react";
import ReactCrop, {
  centerCrop,
  makeAspectCrop,
  Crop,
  PixelCrop,
  convertToPixelCrop,
} from "react-image-crop";
import { Button } from "@/shared/common/ui/button";
import { Input } from "@/shared/common/ui/input";
import { Label } from "@/shared/common/ui/label";
import { RotateCw, RotateCcw, Rotate3D } from "lucide-react";
import { canvasPreview } from "./canvasPreview";
import { useDebounceEffect } from "./useDebounceEffect";
import "react-image-crop/dist/ReactCrop.css";

interface ImageCropperProps {
  file: File;
  onCropComplete: (croppedFile: File) => void;
  aspectRatio?: number;
}

export function ImageCropper({
  file,
  onCropComplete,
  aspectRatio = 3 / 4,
}: ImageCropperProps) {
  const [imgSrc, setImgSrc] = useState("");
  const previewCanvasRef = useRef<HTMLCanvasElement>(null);
  const imgRef = useRef<HTMLImageElement>(null);
  const [crop, setCrop] = useState<Crop>();
  const [completedCrop, setCompletedCrop] = useState<PixelCrop>();
  const [scale, setScale] = useState(1);
  const [rotate, setRotate] = useState(0);

  const rotateClockwise = useCallback(() => {
    setRotate((prev) => (prev + 90) % 360);
  }, []);

  const rotateCounterClockwise = useCallback(() => {
    setRotate((prev) => (prev - 90) % 360);
  }, []);

  const rotateSmall = useCallback((degrees: number) => {
    setRotate((prev) => (prev + degrees) % 360);
  }, []);

  React.useEffect(() => {
    const reader = new FileReader();
    reader.addEventListener("load", () => {
      setImgSrc(reader.result?.toString() || "");
    });
    reader.readAsDataURL(file);
  }, [file]);

  function onImageLoad(e: React.SyntheticEvent<HTMLImageElement>) {
    const { width, height } = e.currentTarget;
    setCrop(centerAspectCrop(width, height, aspectRatio));
  }

  function centerAspectCrop(
    mediaWidth: number,
    mediaHeight: number,
    aspect: number
  ) {
    return centerCrop(
      makeAspectCrop(
        {
          unit: "%",
          width: 90,
        },
        aspect,
        mediaWidth,
        mediaHeight
      ),
      mediaWidth,
      mediaHeight
    );
  }

  async function handleCropComplete() {
    const image = imgRef.current;
    const previewCanvas = previewCanvasRef.current;
    if (!image || !previewCanvas || !completedCrop) {
      throw new Error("Crop canvas does not exist");
    }

    const scaleX = image.naturalWidth / image.width;
    const scaleY = image.naturalHeight / image.height;

    const offscreen = new OffscreenCanvas(
      completedCrop.width * scaleX,
      completedCrop.height * scaleY
    );
    const ctx = offscreen.getContext("2d");
    if (!ctx) {
      throw new Error("No 2d context");
    }

    ctx.drawImage(
      previewCanvas,
      0,
      0,
      previewCanvas.width,
      previewCanvas.height,
      0,
      0,
      offscreen.width,
      offscreen.height
    );

    const blob = await offscreen.convertToBlob({
      type: file.type || "image/png",
    });

    const croppedFile = new File([blob], file.name, {
      type: blob.type,
      lastModified: Date.now(),
    });

    onCropComplete(croppedFile);
  }

  useDebounceEffect(
    async () => {
      if (
        completedCrop?.width &&
        completedCrop?.height &&
        imgRef.current &&
        previewCanvasRef.current
      ) {
        canvasPreview(
          imgRef.current,
          previewCanvasRef.current,
          completedCrop,
          scale,
          rotate
        );
      }
    },
    100,
    [completedCrop, scale, rotate]
  );

  return (
    <div className="flex flex-col gap-4">
      {!!imgSrc && (
        <ReactCrop
          crop={crop}
          onChange={(_, percentCrop) => setCrop(percentCrop)}
          onComplete={(c) => setCompletedCrop(c)}
          aspect={aspectRatio}
          minHeight={100}>
          <img
            ref={imgRef}
            alt="Crop me"
            src={imgSrc}
            style={{ transform: `rotate(${rotate}deg)` }}
            onLoad={onImageLoad}
            className="max-h-[400px] object-contain"
          />
        </ReactCrop>
      )}

      <div className="flex items-center gap-2">
        <Label htmlFor="rotate-input">Rotate:</Label>
        <Button
          variant="outline"
          size="sm"
          onClick={rotateCounterClockwise}
          title="Rotate counter-clockwise">
          <RotateCcw className="h-4 w-4" />
        </Button>
        <Input
          id="rotate-input"
          type="number"
          value={rotate}
          min="-180"
          max="180"
          onChange={(e) => setRotate(Number(e.target.value))}
          className="w-16"
        />
        <Button
          variant="outline"
          size="sm"
          onClick={rotateClockwise}
          title="Rotate clockwise">
          <RotateCw className="h-4 w-4" />
        </Button>
        <Button
          variant="outline"
          size="sm"
          onClick={() => rotateSmall(15)}
          title="Rotate 15° clockwise">
          <Rotate3D className="h-4 w-4 mr-1" /> 15°
        </Button>
        <Button
          variant="outline"
          size="sm"
          onClick={() => rotateSmall(-15)}
          title="Rotate 15° counter-clockwise">
          <Rotate3D className="h-4 w-4 mr-1 transform scale-x-[-1]" /> 15°
        </Button>
      </div>

      <Button
        onClick={handleCropComplete}
        disabled={!completedCrop}
        className="self-start">
        Apply Crop
      </Button>

      <canvas
        ref={previewCanvasRef}
        style={{
          display: "none",
          border: "1px solid black",
          objectFit: "contain",
          width: completedCrop?.width,
          height: completedCrop?.height,
        }}
      />
    </div>
  );
}
