import { FC, useCallback, useEffect, useRef, useState } from "react";
import { enqueueSnackbar } from "notistack";
import ReactCrop, {
    PercentCrop,
    centerCrop,
    convertToPixelCrop,
    makeAspectCrop,
    type Crop
} from "react-image-crop";
import {
    getModifiedImageBlob,
    getRotatedImageBlob,
} from "./utils/imageManipulation";

import {
    Box,
    IconButton,
    Slider,
    SxProps,
    Theme,
    Typography,
    useMediaQuery,
    useTheme,
} from "@mui/material";
import { ResetIcon } from "@icons/ResetIcon";
import "react-image-crop/dist/ReactCrop.css";
import { EditedImagesChangeType } from "./CropModal";
import { CropAspectRatio, DEFAULTCROPRULES, EditedImage } from "@/model/CropModal/CropModal";
import { devlog } from "@frontend/kitui";

const styleSlider: SxProps<Theme> = {
    color: "#7E2AEA",
    height: "10px",
    p: "18px 0",
    "& .MuiSlider-track": {
        border: "none",
    },
    "& .MuiSlider-rail": {
        backgroundColor: "#F2F3F7",
        border: `1px solid #9A9AAF`,
    },
    "& .MuiSlider-thumb": {
        height: 24,
        width: 24,
        border: `6px solid #7E2AEA`,
        backgroundColor: "white",
        boxShadow: `0px 0px 0px 3px white,
                0px 4px 4px 3px #C3C8DD`,
        "&:focus, &:hover, &.Mui-active, &.Mui-focusVisible": {
            boxShadow: `0px 0px 0px 3px white,
                    0px 4px 4px 3px #C3C8DD`,
        },
    },
};

interface Props {
    editedImage: EditedImage;
    cropAspectRatio: CropAspectRatio;
    editedImagesChange: EditedImagesChangeType;
};

export const CropGeneral: FC<Props> = ({
    editedImage,
    cropAspectRatio,
    editedImagesChange,
}) => {
    const theme = useTheme();
    const isMobile = useMediaQuery(theme.breakpoints.down(786));

    const { crop, darken } = editedImage.newRules;

    const cropImageElementRef = useRef<HTMLImageElement>(null);

    const [imageWidth, setImageWidth] = useState<number | null>(null);
    const [imageHeight, setImageHeight] = useState<number | null>(null);

    async function handleRotateClick() {

        if (cropImageElementRef.current !== null) {
            try {
                const blob = await getRotatedImageBlob(cropImageElementRef.current);

                editedImagesChange((old) => {
                    const newRotate = old.newRules.rotate + 90;

                    return {
                        newRules: {
                            ...old.newRules,
                            rotate: newRotate > 360 ? 0 : newRotate
                        },
                        url: (URL.createObjectURL(blob))
                    };
                });
            } catch (error) {
                devlog("getRotatedImageBlob error", error);
                enqueueSnackbar("Не удалось изменить изображение");
            }
        }

    }

    function handleSizeChange(value: number) {
        editedImagesChange((old) => {
            if (!imageWidth || !imageHeight) return old;

            const crop = makeAspectCrop(
                {
                    unit: "%",
                    width: value,
                    x: 0,
                    y: 0,
                },
                cropAspectRatio ? cropAspectRatio.width / cropAspectRatio.height : 1,
                imageWidth,
                imageHeight,
            );

            //Хз зачем это было нужно, как будет работать - перетещу

            // if (!old.newRules.crop || old.newRules.crop.height === 0 || old.newRules.crop.width === 0) {
            //     return centerCrop(crop, imageWidth, imageHeight);
            // }

            crop.x = Math.min(
                100 - crop.width,
                Math.max(0, old.newRules.crop.x + (old.newRules.crop.width - crop.width) / 2),
            );
            crop.y = Math.min(
                100 - crop.height,
                Math.max(0, old.newRules.crop.y + (old.newRules.crop.height - crop.height) / 2),
            );

            return {
                newRules: {
                    ...old.newRules,
                    crop
                }
            };
        });
    }

    const calcCrop = () => {
        if (cropImageElementRef.current) {
            editedImagesChange((old) => ({
                newRules: {
                    ...old.newRules,
                    crop: getInitialCrop(
                        cropImageElementRef.current?.width,
                        cropImageElementRef.current?.height,
                        cropAspectRatio
                            ? cropAspectRatio.width / cropAspectRatio.height
                            : 2,
                    )
                }
            }))
        }
    }
    
    useEffect(() => {
        if (!crop.width && !crop.height) { calcCrop() }
    }, [crop])


    return (
        <>
            <Box
                sx={{
                    height: "320px",
                    backgroundSize: "cover",
                    backgroundRepeat: "no-repeat",
                    display: "flex",
                    alignItems: "center",
                    justifyContent: "center",
                    padding: "0 20px",
                    marginTop: isMobile ? "19px" : "20px",
                }}
            >
                <ReactCrop
                    crop={crop}
                    onChange={(_, percentCrop) => editedImagesChange((old) => {
                        return ({
                            newRules: {
                                ...old.newRules,
                                crop: percentCrop
                            }
                        })
                    }
                    )}

                    minWidth={5}
                    minHeight={5}
                    locked
                    aspect={
                        cropAspectRatio
                            ? cropAspectRatio.width / cropAspectRatio.height
                            : undefined
                    }
                >
                    <img
                        id="imgid"
                        onLoad={(e) => {
                            setImageWidth(e.currentTarget.naturalWidth);
                            setImageHeight(e.currentTarget.naturalHeight);

                            calcCrop()
                        }}
                        ref={cropImageElementRef}
                        alt="Crop me"
                        src={editedImage.url}
                        style={{
                            filter: `brightness(${100 - editedImage.newRules.darken}%)`,
                            maxWidth: "100%",
                            height: "320px",
                            maxHeight: "320px",
                            display: "block",
                            objectFit: "contain",
                        }}
                        crossOrigin = 'anonymous'
                    />
                </ReactCrop>
            </Box>
            <Box
                sx={{
                    mt: isMobile ? "20px" : "48px",
                    display: "flex",
                    alignItems: "end",
                    justifyContent: "space-between",
                    padding: "0 20px",
                    flexDirection: isMobile ? "column" : "",


                }}
            >
                <IconButton onClick={handleRotateClick}
                    sx={{
                        mb: "11px",
                        p: "0",

                    }}
                >
                    <ResetIcon />
                </IconButton>
                <Box
                    sx={{
                        display: "flex",
                        justifyContent: "space-between",
                        flexDirection: isMobile ? "column" : "",
                        width: isMobile ? "100%" : "auto",
                        gap: "24px",
                    }}
                >
                    <Box>
                        <Typography sx={{ color: "#9A9AAF", fontSize: "16px" }}>
                            Размер
                        </Typography>
                        <Slider
                            sx={[
                                styleSlider,
                                {
                                    width: isMobile ? undefined : "248px",
                                },
                            ]}
                            value={crop.width}
                            min={1}
                            max={100}
                            step={0.1}
                            onChange={(_, newValue) => {
                                if (typeof newValue === "number") handleSizeChange(newValue);
                            }}
                        />
                    </Box>
                    <Box>
                        <Typography sx={{ color: "#9A9AAF", fontSize: "16px", ml: "-1px", }}>
                            Затемнение
                        </Typography>
                        <Slider
                            sx={[
                                styleSlider,
                                {

                                    width: isMobile ? undefined : "248px",
                                },
                            ]}
                            value={darken}
                            min={0}
                            max={100}
                            step={1}
                            onChange={(_, newValue) => editedImagesChange((old) => ({
                                newRules: {
                                    ...old.newRules,
                                    darken: newValue as number
                                }
                            }))}
                        />
                    </Box>
                </Box>
            </Box>
        </>

    )
};

function getInitialCrop(
    imageWidth: number | null | undefined,
    imageHeight: number | null | undefined,
    aspectRatio: number,
): PercentCrop {
    if (!imageHeight || !imageWidth) return DEFAULTCROPRULES.crop
    const imageAspectRatio = imageWidth / imageHeight;

    return centerCrop(
        {
            width:
                imageAspectRatio < aspectRatio
                    ? 100
                    : (100 * aspectRatio) / imageAspectRatio,
            height:
                imageAspectRatio < aspectRatio
                    ? (100 * imageAspectRatio) / aspectRatio
                    : 100,
            unit: "%",
            x: 0,
            y: 0,
        },
        imageWidth,
        imageHeight,
    );
}
