import { CropIcon } from "@icons/CropIcon";
import { ResetIcon } from "@icons/ResetIcon";
import {
    Box,
    Button,
    IconButton,
    Modal,
    Slider,
    SxProps,
    Theme,
    Typography,
    useMediaQuery,
    useTheme,
} from "@mui/material";
import { FC, useMemo, useRef, useState } from "react";
import ReactCrop, { Crop, PixelCrop } from "react-image-crop";
import "react-image-crop/dist/ReactCrop.css";
import { canvasPreview } from "./utils/canvasPreview";


const styleSlider: SxProps<Theme> = {
    color: "#7E2AEA",
    height: "12px",
    "& .MuiSlider-track": {
        border: "none",
    },
    "& .MuiSlider-rail": {
        backgroundColor: "#F2F3F7",
        border: `1px solid #9A9AAF`,
    },
    "& .MuiSlider-thumb": {
        height: 26,
        width: 26,
        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 {
    isOpen: boolean;
    imageBlob: Blob | null;
    originalImageUrl: string | null;
    setCropModalImageBlob: (imageBlob: Blob) => void;
    onClose: () => void;
    onSaveImageClick: (imageBlob: Blob) => void;
}

export const CropModal: FC<Props> = ({ isOpen, imageBlob, originalImageUrl, setCropModalImageBlob, onSaveImageClick, onClose }) => {
    const theme = useTheme();
    const [crop, setCrop] = useState<Crop>();
    const [completedCrop, setCompletedCrop] = useState<PixelCrop>();
    const [darken, setDarken] = useState(0);
    const [rotate, setRotate] = useState(0);
    const [width, setWidth] = useState<number>(240);
    const cropImageElementRef = useRef<HTMLImageElement>(null);
    const isMobile = useMediaQuery(theme.breakpoints.down(786));

    const imageUrl = useMemo(() => imageBlob && URL.createObjectURL(imageBlob), [imageBlob]);

    const handleCropClick = async () => {
        if (!completedCrop) throw new Error("No completed crop");
        if (!cropImageElementRef.current) throw new Error("No image");

        const canvasCopy = document.createElement("canvas");
        const ctx = canvasCopy.getContext("2d");
        if (!ctx) throw new Error("No 2d context");

        canvasCopy.width = completedCrop.width;
        canvasCopy.height = completedCrop.height;
        ctx.filter = `brightness(${100 - darken}%)`;

        await canvasPreview(cropImageElementRef.current, canvasCopy, completedCrop, rotate);

        canvasCopy.toBlob((blob) => {
            if (!blob) throw new Error("Failed to create blob");

            setCropModalImageBlob(blob);
            setCrop(undefined);
            setCompletedCrop(undefined);
        });
    };

    function handleSaveClick() {
        if (imageBlob) onSaveImageClick?.(imageBlob);
        setCrop(undefined);
        setCompletedCrop(undefined);
        onClose();
    }

    async function handleLoadOriginalImage() {
        if (!originalImageUrl) return;

        const response = await fetch(originalImageUrl);
        const blob = await response.blob();

        setCropModalImageBlob(blob);
        setCrop(undefined);
        setCompletedCrop(undefined);
    }

    const getImageSize = () => {
        if (cropImageElementRef.current) {
            const imageWidth = cropImageElementRef.current.naturalWidth;
            const imageHeight = cropImageElementRef.current.naturalHeight;

            const aspect = imageWidth / imageHeight;

            if (aspect <= 1.333) {
                setWidth(240);
            }
            if (aspect >= 1.5) {
                setWidth(580);
            }
            if (aspect >= 1.778) {
                setWidth(580);
            }
        }
    };

    return (
        <Modal
            open={isOpen}
            onClose={onClose}
            aria-labelledby="modal-modal-title"
            aria-describedby="modal-modal-description"
        >
            <Box sx={{
                position: "absolute",
                top: "50%",
                left: "50%",
                transform: "translate(-50%, -50%)",
                bgcolor: "background.paper",
                boxShadow: 24,
                padding: "20px",
                borderRadius: "8px",
                width: isMobile ? "343px" : "620px",
            }}>
                <Box
                    sx={{
                        height: "320px",
                        padding: "10px",
                        backgroundSize: "cover",
                        backgroundRepeat: "no-repeat",
                        display: "flex",
                        alignItems: "center",
                        justifyContent: "center",
                    }}
                >
                    {imageUrl && (
                        <ReactCrop
                            crop={crop}
                            onChange={(_, percentCrop) => setCrop(percentCrop)}
                            onComplete={(c) => setCompletedCrop(c)}
                            maxWidth={500}
                            minWidth={50}
                            maxHeight={320}
                            minHeight={50}
                        >
                            <img
                                onLoad={getImageSize}
                                ref={cropImageElementRef}
                                alt="Crop me"
                                src={imageUrl}
                                style={{
                                    filter: `brightness(${100 - darken}%)`,
                                    transform: ` rotate(${rotate}deg)`,
                                    maxWidth: "580px",
                                    maxHeight: "320px",
                                }}
                                width={width}
                            />
                        </ReactCrop>
                    )}
                </Box>
                <Box
                    sx={{
                        color: "#7E2AEA",
                        display: "flex",
                        alignItems: "center",
                        justifyContent: "center",
                        fontSize: "16xp",
                        fontWeight: "600",
                        marginBottom: "50px",
                    }}
                >
                    <Typography sx={{ color: "#7E2AEA", lineHeight: "0px" }}>
                        {crop?.width ? Math.round(crop.width) + "px" : ""}
                    </Typography>
                    <Typography sx={{ color: "#7E2AEA", lineHeight: "0px" }}>
                        {crop?.height ? Math.round(crop.height) + "px" : ""}
                    </Typography>
                </Box>

                <Box
                    sx={{
                        display: isMobile ? "block" : "flex",
                        alignItems: "end",
                        justifyContent: "space-between",
                    }}
                >
                    <IconButton onClick={() => setRotate(r => (r + 90) % 360)}>
                        <ResetIcon />
                    </IconButton>
                    <Box>
                        <Typography sx={{ color: "#9A9AAF", fontSize: "16px" }}>
                            Размер
                        </Typography>
                        <Slider
                            sx={[styleSlider, {
                                width: isMobile ? "350px" : "250px",
                            }]}
                            value={width}
                            min={50}
                            max={580}
                            step={1}
                            onChange={(_, newValue) => {
                                setWidth(newValue as number);
                            }}
                        />
                    </Box>
                    <Box>
                        <Typography sx={{ color: "#9A9AAF", fontSize: "16px" }}>
                            Затемнение
                        </Typography>
                        <Slider
                            sx={[styleSlider, {
                                width: isMobile ? "350px" : "250px",
                            }]}
                            value={darken}
                            min={0}
                            max={100}
                            step={1}
                            onChange={(_, newValue) => setDarken(newValue as number)}
                        />
                    </Box>
                </Box>
                <Box
                    sx={{
                        marginTop: "40px",
                        width: "100%",
                        display: "flex",
                    }}
                >
                    <Button
                        onClick={handleSaveClick}
                        disableRipple
                        data-cy="crop-modal-save-button"
                        sx={{
                            height: "48px",
                            color: "#7E2AEA",
                            borderRadius: "8px",
                            border: "1px solid #7E2AEA",
                            marginRight: "10px",
                            px: "20px",
                        }}
                    >Сохранить</Button>
                    <Button
                        onClick={handleLoadOriginalImage}
                        disableRipple
                        disabled={!originalImageUrl}
                        sx={{
                            width: "215px",
                            height: "48px",
                            color: "#7E2AEA",
                            borderRadius: "8px",
                            border: "1px solid #7E2AEA",
                            marginRight: "10px",
                            ml: "auto",
                        }}
                    >
                        Загрузить оригинал
                    </Button>
                    <Button
                        onClick={handleCropClick}
                        disableRipple
                        variant="contained"
                        disabled={!completedCrop}
                        sx={{
                            padding: "10px 20px",
                            borderRadius: "8px",
                            background: theme.palette.brightPurple.main,
                            fontSize: "18px",
                        }}
                    >
                        <CropIcon />
                        Обрезать
                    </Button>
                </Box>
            </Box>
        </Modal>
    );
};

export function useCropModalState(initialOpenState = false) {
    const [isCropModalOpen, setOpened] = useState(initialOpenState);
    const [imageBlob, setCropModalImageBlob] = useState<Blob | null>(null);
    const [originalImageUrl, setOriginalImageUrl] = useState<string | null>(null);

    const closeCropModal = () => {
        setOpened(false);
        setCropModalImageBlob(null);
        setOriginalImageUrl(null);
    };

    async function openCropModal(image: Blob | string, originalImageUrl: string | null | undefined = null) {
        if (typeof image === "string") {
            const response = await fetch(image);
            image = await response.blob();
        }

        setCropModalImageBlob(image);
        setOriginalImageUrl(originalImageUrl);
        setOpened(true);
    }

    return {
        isCropModalOpen,
        openCropModal,
        closeCropModal,
        imageBlob,
        setCropModalImageBlob,
        originalImageUrl,
    } as const;
}
