import { BaseParameters } from '@app/types/parameters';
import { useBaseParameters, BaseParametersHook } from '@app/hooks/tools/shared/useBaseParameters';
import { useCallback } from 'react';
import { Rectangle, PDFBounds, constrainCropAreaToPDF, createFullPDFCropArea, roundCropArea, isRectangle } from '@app/utils/cropCoordinates';
import { DEFAULT_CROP_AREA } from '@app/constants/cropConstants';

export interface CropParameters extends BaseParameters {
  cropArea: Rectangle;
}

export const defaultParameters: CropParameters = {
  cropArea: DEFAULT_CROP_AREA,
};

export type CropParametersHook = BaseParametersHook<CropParameters> & {
  /** Set crop area with PDF bounds validation */
  setCropArea: (cropArea: Rectangle, pdfBounds?: PDFBounds) => void;
  /** Get current crop area as CropArea object */
  getCropArea: () => Rectangle;
  /** Reset to full PDF dimensions */
  resetToFullPDF: (pdfBounds: PDFBounds) => void;
  /** Check if current crop area is valid for the PDF */
  isCropAreaValid: (pdfBounds?: PDFBounds) => boolean;
  /** Check if crop area covers the entire PDF */
  isFullPDFCrop: (pdfBounds?: PDFBounds) => boolean;
  /** Update crop area with constraints applied */
  updateCropAreaConstrained: (cropArea: Partial<Rectangle>, pdfBounds?: PDFBounds) => void;
};

export const useCropParameters = (): CropParametersHook => {
  const baseHook = useBaseParameters({
    defaultParameters,
    endpointName: 'crop',
    validateFn: (params) => {
      const rect = params.cropArea;
      // Basic validation - coordinates and dimensions must be positive
      return rect.x >= 0 &&
             rect.y >= 0 &&
             rect.width > 0 &&
             rect.height > 0;
    },
  });

  // Get current crop area as CropArea object
  const getCropArea = useCallback((): Rectangle => {
    return baseHook.parameters.cropArea;
  }, [baseHook.parameters]);

  // Set crop area with optional PDF bounds validation
  const setCropArea = useCallback((cropArea: Rectangle, pdfBounds?: PDFBounds) => {
    let finalCropArea = roundCropArea(cropArea);

    // Apply PDF bounds constraints if provided
    if (pdfBounds) {
      finalCropArea = constrainCropAreaToPDF(finalCropArea, pdfBounds);
    }
    baseHook.updateParameter('cropArea', finalCropArea);
  }, [baseHook]);

  // Reset to cover entire PDF
  const resetToFullPDF = useCallback((pdfBounds: PDFBounds) => {
    const fullCropArea = createFullPDFCropArea(pdfBounds);
    setCropArea(fullCropArea);
  }, [setCropArea]);

  // Check if current crop area is valid for the given PDF bounds
  const isCropAreaValid = useCallback((pdfBounds?: PDFBounds): boolean => {
    const cropArea = getCropArea();

    // Basic validation
    if (cropArea.x < 0 || cropArea.y < 0 || cropArea.width <= 0 || cropArea.height <= 0) {
      return false;
    }

    // PDF bounds validation if provided
    if (pdfBounds) {
      const tolerance = 0.01; // Small tolerance for floating point precision
      return cropArea.x + cropArea.width <= pdfBounds.actualWidth + tolerance &&
             cropArea.y + cropArea.height <= pdfBounds.actualHeight + tolerance;
    }

    return true;
  }, [getCropArea]);

  // Check if crop area covers the entire PDF
  const isFullPDFCrop = useCallback((pdfBounds?: PDFBounds): boolean => {
    if (!pdfBounds) return false;

    const cropArea = getCropArea();
    const tolerance = 0.5; // Allow 0.5 point tolerance for floating point precision

    return Math.abs(cropArea.x) < tolerance &&
           Math.abs(cropArea.y) < tolerance &&
           Math.abs(cropArea.width - pdfBounds.actualWidth) < tolerance &&
           Math.abs(cropArea.height - pdfBounds.actualHeight) < tolerance;
  }, [getCropArea]);

  // Update crop area with constraints applied
  const updateCropAreaConstrained = useCallback((
    partialCropArea: Partial<Rectangle>,
    pdfBounds?: PDFBounds
  ) => {
    const currentCropArea = getCropArea();
    const newCropArea = { ...currentCropArea, ...partialCropArea };
    setCropArea(newCropArea, pdfBounds);
  }, [getCropArea, setCropArea]);

  // Enhanced validation that considers PDF bounds
  const validateParameters = useCallback((pdfBounds?: PDFBounds): boolean => {
    return baseHook.validateParameters() && isCropAreaValid(pdfBounds);
  }, [baseHook, isCropAreaValid]);

  // Override updateParameter to ensure positive values
  const updateParameter = useCallback(<K extends keyof CropParameters>(
    parameter: K,
    value: CropParameters[K]
  ) => {

    if(isRectangle(value)) {
      value.x = Math.max(0.1, value.x); // Minimum 0.1 point
      value.x = Math.max(0.1, value.y); // Minimum 0.1 point
      value.width = Math.max(0, value.width); // Minimum 0 point
      value.height = Math.max(0, value.height); // Minimum 0 point
    }

    baseHook.updateParameter(parameter, value);
  }, [baseHook]);


  return {
    ...baseHook,
    updateParameter,
    validateParameters: () => validateParameters(),
    setCropArea,
    getCropArea,
    resetToFullPDF,
    isCropAreaValid,
    isFullPDFCrop,
    updateCropAreaConstrained,
  };
};
