"use client";

import {useCallback, useEffect, useMemo, useRef, useState} from "react";
import Cropper from "cropperjs";
import "cropperjs/dist/cropper.css";
import {toast} from "sonner";
import api from "@/api/axios";
import {getGuestUuid} from "@/utils/guestUuid";

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

type CropImageModalProps = {
    isOpen: boolean;
    file: File | null;
    imageId: number | string | null;
    productId: number | string | null;
    selectedImage?: any;
    calendarSlot?: string | null;

    aspect?: number;
    cropShape?: "rect" | "round";
    title?: string;
    saving?: boolean;
    onSaved?: (data: any) => void;
    onCancel: () => void;
    onClose?: () => void;
    variationSize?: VariationSize | null;
    isRegularPhotos?: boolean;
    variationId?: number | string | null;
    rotation?: number;
    setRotation?: (value: number) => void;
    onRotateLeft?: () => void;
    onRotateRight?: () => void;
};

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

const yearlyCalendarSlotSizes: Record<string, VariationSize> = {
    A: {
        width: 531,
        height: 531,
    },
    B: {
        width: 531,
        height: 383,
    },
    C: {
        width: 531,
        height: 383,
    },
    D: {
        width: 531,
        height: 531,
    },
    E: {
        width: 531,
        height: 792,
    },
    F: {
        width: 531,
        height: 946,
    },
    G: {
        width: 531,
        height: 383,
    },
};

function clampAspect(a?: number) {
    const n = Number(a);
    if (!Number.isFinite(n) || n <= 0) return 1;
    return Math.min(Math.max(n, 0.1), 10);
}

function getAspectRatioGCD(width: number, height: number): number {
    return height === 0 ? width : getAspectRatioGCD(height, width % height);
}

function getAspectRatioLikeOriginal(params: {
    width: number;
    height: number;
    fileWidth: number;
    fileHeight: number;
    isRegularPhotos: boolean;
    fallbackAspect: number;
}) {
    const {
        width: targetWidth,
        height: targetHeight,
        fallbackAspect,
    } = params;

    try {
        if (
            !Number.isFinite(targetWidth) ||
            !Number.isFinite(targetHeight) ||
            targetWidth <= 0 ||
            targetHeight <= 0
        ) {
            return fallbackAspect;
        }

        const width = targetWidth;
        const height = targetHeight;

        const gcd = getAspectRatioGCD(Math.round(width), Math.round(height));
        return width / gcd / (height / gcd);
    } catch {
        return fallbackAspect;
    }
}

export default function CropImageModal({
                                           isOpen,
                                           file,
                                           imageId,
                                           productId,
                                           selectedImage,
                                           calendarSlot = null,
                                           aspect = 1,
                                           title = "قص الصورة",
                                           saving: savingExternal,
                                           onSaved,
                                           onCancel,
                                           onClose,
                                           variationSize = null,
                                           isRegularPhotos = false,
                                           variationId = null,
                                           rotation = 0,
                                           setRotation,
                                           onRotateLeft,
                                           onRotateRight,
                                       }: CropImageModalProps) {
    const fallbackAspect = useMemo(() => clampAspect(aspect), [aspect]);

    const [savingInternal, setSavingInternal] = useState(false);
    const [isImageLoaded, setIsImageLoaded] = useState(false);
    const [mediaInfo, setMediaInfo] = useState<MediaInfo | null>(null);
    const [zoomValue, setZoomValue] = useState(1);
    const [minZoom, setMinZoom] = useState(1);

    const saving = savingExternal ?? savingInternal;

    const imageRef = useRef<HTMLImageElement | null>(null);
    const cropperRef = useRef<Cropper | null>(null);
    const cropperBoxRef = useRef<HTMLDivElement | null>(null);
    const raf1Ref = useRef<number | null>(null);
    const raf2Ref = useRef<number | null>(null);

    const imageSrc = useMemo(() => {
        if (!file) return "";
        return URL.createObjectURL(file);
    }, [file]);

    useEffect(() => {
        return () => {
            if (imageSrc) URL.revokeObjectURL(imageSrc);
        };
    }, [imageSrc]);

    const normalizedCalendarSlot = String(calendarSlot || "")
        .trim()
        .toUpperCase();

    const yearlySlotSize =
        Number(productId) === 1 && normalizedCalendarSlot
            ? yearlyCalendarSlotSizes[normalizedCalendarSlot] || null
            : null;

    const effectiveSize =
        yearlySlotSize ||
        variationSize ||
        null;

    const variationWidth = Number(effectiveSize?.width || 0);
    const variationHeight = Number(effectiveSize?.height || 0);

    /*const computedAspect = useMemo(() => {
      if (!mediaInfo) {
        if (variationWidth > 0 && variationHeight > 0) {
          return variationWidth / variationHeight;
        }
        return fallbackAspect;
      }

      return getAspectRatioLikeOriginal({
        width: variationWidth,
        height: variationHeight,
        fileWidth: mediaInfo.width,
        fileHeight: mediaInfo.height,
        isRegularPhotos,
        fallbackAspect,
      });
    }, [
      mediaInfo,
      variationWidth,
      variationHeight,
      isRegularPhotos,
      fallbackAspect,
    ]);*/
    //melo
    const computedAspect = useMemo(() => {
        if (!mediaInfo) return fallbackAspect;

        return getAspectRatioLikeOriginal({
            width: variationWidth,
            height: variationHeight,
            fileWidth: mediaInfo.width,
            fileHeight: mediaInfo.height,
            isRegularPhotos,
            fallbackAspect,
        });
    }, [
        mediaInfo,
        variationWidth,
        variationHeight,
        isRegularPhotos,
        fallbackAspect,
    ]);

    const isLandscapeImage = useMemo(() => {
        if (!mediaInfo) return false;
        return mediaInfo.width >= mediaInfo.height;
    }, [mediaInfo]);

    const destroyCropper = useCallback(() => {
        if (raf1Ref.current) {
            cancelAnimationFrame(raf1Ref.current);
            raf1Ref.current = null;
        }

        if (raf2Ref.current) {
            cancelAnimationFrame(raf2Ref.current);
            raf2Ref.current = null;
        }

        if (cropperRef.current) {
            cropperRef.current.destroy();
            cropperRef.current = null;
        }
    }, []);


    //melo
    const applyStableLayout = useCallback(
        (aspectRatio: number, naturalWidth: number, naturalHeight: number) => {
            const cropper = cropperRef.current;
            if (!cropper) return;

            const canvasData = cropper.getCanvasData();
            const imageData = cropper.getImageData();

            if (!canvasData.width || !canvasData.height) return;

            let cropWidth = canvasData.width;
            let cropHeight = cropWidth / aspectRatio;

            // إذا الارتفاع تجاوز canvas، نستخدم الارتفاع كمرجع
            if (cropHeight > canvasData.height) {
                cropHeight = canvasData.height;
                cropWidth = cropHeight * aspectRatio;
            }

            // مهم جدًا: مثل القديم
            // لا نوسّط crop box داخل canvas
            const left = canvasData.left;
            const top = canvasData.top;

            cropper.setCropBoxData({
                width: cropWidth,
                height: cropHeight,
            });

            const initialRatio =
                imageData.naturalWidth > 0
                    ? imageData.width / imageData.naturalWidth
                    : 1;

            setZoomValue(initialRatio);
            setMinZoom(initialRatio);
            setIsImageLoaded(true);

            cropper.setDragMode("move");
        },
        []
    );
    useEffect(() => {
        if (!isOpen || !file || !imageRef.current) return;

        setIsImageLoaded(false);
        setZoomValue(1);
        setMinZoom(1);
        destroyCropper();

        const img = imageRef.current;

        const handleLoad = () => {
            const naturalWidth = img.naturalWidth || 0;
            const naturalHeight = img.naturalHeight || 0;

            if (!naturalWidth || !naturalHeight) {
                setIsImageLoaded(true);
                return;
            }

            setMediaInfo({
                width: naturalWidth,
                height: naturalHeight,
            });

            //melo
            /*const aspectRatio = getAspectRatioLikeOriginal({
              width: variationWidth,
              height: variationHeight,
              fileWidth: naturalWidth,
              fileHeight: naturalHeight,
              isRegularPhotos,
              fallbackAspect,
            });*/

            const aspectRatio = getAspectRatioLikeOriginal({
                width: variationWidth,
                height: variationHeight,
                fileWidth: naturalWidth,
                fileHeight: naturalHeight,
                isRegularPhotos,
                fallbackAspect,
            });

            const instance = new Cropper(img, {
                /*imageSmoothingEnabled: true,*/
                viewMode: 1,
                dragMode: "move",
                cropBoxMovable: false,
                cropBoxResizable: false,
                background: false,
                autoCropArea: 1,
                aspectRatio,
                initialAspectRatio: aspectRatio,
                responsive: true,
                movable: true,
                zoomable: true,
                guides: true,
                center: true,
                highlight: true,
                modal: true,
                rotatable: true,

                ready() {
                    requestAnimationFrame(() => {
                        applyStableLayout(aspectRatio, naturalWidth, naturalHeight);
                    });
                },
            });

            cropperRef.current = instance;
        };

        if (img.complete && img.naturalWidth > 0) {
            handleLoad();
        } else {
            img.addEventListener("load", handleLoad, {once: true});
        }

        return () => {
            img.removeEventListener("load", handleLoad);
            destroyCropper();
        };
    }, [
        isOpen,
        file,
        destroyCropper,
        variationWidth,
        variationHeight,
        isRegularPhotos,
        fallbackAspect,
        applyStableLayout,
    ]);

    const handleZoomChange = (value: number) => {
        setZoomValue(value);

        const cropper = cropperRef.current;
        if (!cropper) return;

        cropper.zoomTo(value);
    };

    const rotationRef = useRef(0);

    useEffect(() => {
        if (isOpen) {
            rotationRef.current = 0;
            setRotation?.(0);
        }
    }, [isOpen, setRotation]);

    const handleRotate = (degree: number) => {
        const cropper = cropperRef.current;
        if (!cropper) return;

        const currentCropBox = cropper.getCropBoxData();

        const nextRotation = (rotationRef.current + degree + 360) % 360;

        rotationRef.current = nextRotation;
        setRotation?.(nextRotation);

        cropper.rotateTo(nextRotation);

        requestAnimationFrame(() => {
            cropper.setAspectRatio(computedAspect);

            cropper.setCropBoxData({
                left: currentCropBox.left,
                top: currentCropBox.top,
                width: currentCropBox.width,
                height: currentCropBox.height,
            });

            cropper.setDragMode("move");

            const imageData = cropper.getImageData();
            const currentZoom =
                imageData.naturalWidth > 0
                    ? imageData.width / imageData.naturalWidth
                    : zoomValue;

            setZoomValue(currentZoom);
        });
    };

    const handleDone = async () => {
        if (!file) {
            toast.error("لا توجد صورة");
            return;
        }

        if (!imageId || !productId) {
            toast.error("imageId أو productId ناقص");
            return;
        }

        const cropper = cropperRef.current;
        if (!cropper) {
            toast.error("Cropper غير جاهز");
            return;
        }

        try {
            setSavingInternal(true);

            const canvas = cropper.getCroppedCanvas({
                maxWidth: 4096,
                maxHeight: 4096,
                fillColor: "#FFFFFF",
                imageSmoothingEnabled: true,
                imageSmoothingQuality: "high",
            });

            if (!canvas) {
                throw new Error("فشل إنشاء canvas");
            }

            const isPng = file.type === "image/png";
            const mime = isPng ? "image/png" : "image/jpeg";
            const ext = isPng ? "png" : "jpg";

            const croppedFile = await new Promise<File>((resolve, reject) => {
                canvas.toBlob(
                    (blob) => {
                        if (!blob) {
                            reject(new Error("Canvas is empty"));
                            return;
                        }

                        resolve(new File([blob], `cropped.${ext}`, {type: mime}));
                    },
                    mime,
                    0.95
                );
            });

            const guestUuid = getGuestUuid();
            const formData = new FormData();
            formData.append("cropped_image", croppedFile);
            formData.append("image_id", String(imageId));
            formData.append("product_id", String(productId));
            if (Number(productId) === 1 && normalizedCalendarSlot) {
                formData.append("calendar_slot", normalizedCalendarSlot);
            }
            formData.append("guest_uuid", guestUuid);
            if (variationId) {
                formData.append("variation_id", String(variationId));
            }
            if (effectiveSize && variationWidth > 0 && variationHeight > 0) {
                formData.append("variation_width", String(variationWidth));
                formData.append("variation_height", String(variationHeight));
            }

            const res = await api.post("account-images/crop/save", formData, {
                headers: {
                    Accept: "application/json",
                    "X-Guest-Uuid": guestUuid,
                },
            });

            toast.success("تم حفظ الصورة");
            const payload = res?.data?.data ?? res?.data;

            onSaved?.(payload);

            if (typeof window !== "undefined") {
                window.dispatchEvent(new CustomEvent("crop-completed", {detail: payload}));
            }


            onClose?.();
        } catch (e: any) {
            console.error(e);
            toast.error(e?.response?.data?.message || "فشل قص الصورة");
        } finally {
            setSavingInternal(false);
        }
    };

    useEffect(() => {
        if (!isOpen) {
            destroyCropper();
            setMediaInfo(null);
            setIsImageLoaded(false);
            setZoomValue(1);
            setMinZoom(1);
        }
    }, [isOpen, destroyCropper]);

    useEffect(() => {
        if (!isOpen) return;

        const oldOverflow = document.body.style.overflow;
        document.body.style.overflow = "hidden";

        return () => {
            document.body.style.overflow = oldOverflow;
        };
    }, [isOpen]);

    if (!isOpen) return null;

    const modalStyle = isLandscapeImage
        ? {maxHeight: "620px", maxWidth: "660px"}
        : {maxWidth: "560px"};

    const cropperBoxStyle = isLandscapeImage
        ? {
            height: "360px",
            maxWidth: "800px",
        }
        : {
            width: "100%",
            maxWidth: "420px",
            height: "450px",
        };

    return (
        <div className="fixed inset-0 z-[9999] bg-[#1b1b1b] text-white overflow-hidden">
            {/* Header مثل الموقع القديم */}
            <div className="cropper-header relative h-[40px] border-b border-white/20 flex items-center justify-center">
                <span className="text-sm font-medium">{title}</span>

                <button
                    onClick={onClose ? onClose : onCancel}
                    className="absolute right-5 top-1/2 -translate-y-1/2 text-2xl text-white/60 hover:text-white"
                    disabled={saving}
                    type="button"
                >
                    ×
                </button>
            </div>

            {!file ? (
                <div className="h-[calc(100vh-42px)] flex items-center justify-center text-white/70">
                    لا توجد صورة
                </div>
            ) : (
                <>
                    {/* Cropper Area - أهم جزء */}
                    <div
                        ref={cropperBoxRef}
                        className="relative w-screen bg-black overflow-hidden"
                        style={{
                            height: "calc(100vh - 100px)",
                        }}
                    >
                        {!isImageLoaded && (
                            <div className="absolute inset-0 z-20 flex items-center justify-center bg-[#1b1b1b]">
                                <div className="text-center">
                                    <div className="w-8 h-8 border-2 border-white/40 border-t-white rounded-full animate-spin mx-auto"></div>
                                    <p className="text-sm text-white/70 mt-2">جاري تجهيز الصورة...</p>
                                </div>
                            </div>
                        )}

                        <img
                            ref={imageRef}
                            src={imageSrc}
                            alt="cropper"
                            className="block"
                            style={{
                                maxWidth: "100%",
                                visibility: "visible",
                            }}
                        />
                    </div>

                    {/* Footer مثل الموقع القديم */}
                    <div className="cropper-footer h-[60px] border-t border-white/20 bg-[#1b1b1b] flex items-center justify-center gap-4 px-4">
                        <button
                            type="button"
                            onClick={handleDone}
                            disabled={saving || !isImageLoaded}
                            className="w-[68px] h-[46px] bg-white text-black rounded flex items-center justify-center disabled:opacity-50"
                            title="حفظ"
                        >
                            {saving ? (
                                <div className="w-4 h-4 border-2 border-black/30 border-t-black rounded-full animate-spin"></div>
                            ) : (
                                "💾"
                            )}
                        </button>

                        <button
                            type="button"
                            onClick={() => handleRotate(-90)}
                            className="w-[68px] h-[46px] bg-white text-black rounded flex items-center justify-center disabled:opacity-50"
                            disabled={saving || !isImageLoaded}
                            title="تدوير لليسار"
                        >
                            ↶
                        </button>

                        <button
                            type="button"
                            onClick={() => handleRotate(90)}
                            className="w-[68px] h-[46px] bg-white text-black rounded flex items-center justify-center disabled:opacity-50"
                            disabled={saving || !isImageLoaded}
                            title="تدوير لليمين"
                        >
                            ↷
                        </button>

                        <button
                            type="button"
                            onClick={() => handleZoomChange(Math.max(minZoom, zoomValue - 0.1))}
                            className="w-[68px] h-[46px] bg-white text-black rounded flex items-center justify-center disabled:opacity-50"
                            disabled={saving || !isImageLoaded}
                            title="تصغير"
                        >
                            🔍-
                        </button>

                        <button
                            type="button"
                            onClick={() => handleZoomChange(Math.min(5, zoomValue + 0.1))}
                            className="w-[68px] h-[46px] bg-white text-black rounded flex items-center justify-center disabled:opacity-50"
                            disabled={saving || !isImageLoaded}
                            title="تكبير"
                        >
                            🔍+
                        </button>
                    </div>
                </>
            )}
        </div>
    );
}