import { memo, useCallback, useState } from "react";
import type { Area } from "react-easy-crop";
import Cropper from "react-easy-crop";

import { Button } from "@ax/components";

import * as S from "./style";

const MIN_ZOOM = 1;
const MAX_ZOOM = 3;
const ZOOM_STEP = 0.1;

const CropStep = (props: IProps) => {
	const { imageSrc, onConfirm, onCancel } = props;

	const [crop, setCrop] = useState({ x: 0, y: 0 });
	const [zoom, setZoom] = useState(1);
	const [croppedAreaPixels, setCroppedAreaPixels] = useState<Area | null>(null);
	const [objectFit, setObjectFit] = useState<"vertical-cover" | "horizontal-cover">("vertical-cover");

	const onCropComplete = useCallback((_: Area, pixels: Area) => {
		setCroppedAreaPixels(pixels);
	}, []);

	const onMediaLoaded = useCallback((mediaSize: { width: number; height: number }) => {
		const isPortrait = mediaSize.height > mediaSize.width;
		setObjectFit(isPortrait ? "vertical-cover" : "horizontal-cover");
	}, []);

	const handleConfirm = () => {
		if (croppedAreaPixels) onConfirm(croppedAreaPixels);
	};

	const handleZoomIn = () => setZoom((z) => Math.min(z + ZOOM_STEP, MAX_ZOOM));
	const handleZoomOut = () => setZoom((z) => Math.max(z - ZOOM_STEP, MIN_ZOOM));

	return (
		<S.Wrapper>
			<S.CropArea>
				<S.CropContent>
					<S.CropContainer>
						<Cropper
							image={imageSrc}
							crop={crop}
							zoom={zoom}
							aspect={1}
							cropShape="round"
							showGrid={false}
							onCropChange={setCrop}
							onZoomChange={setZoom}
							onCropComplete={onCropComplete}
							onMediaLoaded={onMediaLoaded}
							objectFit={objectFit}
						/>
					</S.CropContainer>
					<S.ZoomControls>
						<S.ZoomButton type="button" onClick={handleZoomIn} aria-label="Zoom in">
							+
						</S.ZoomButton>
						<S.ZoomSlider
							type="range"
							min={MIN_ZOOM}
							max={MAX_ZOOM}
							step={ZOOM_STEP}
							value={zoom}
							onChange={(e) => setZoom(Number(e.target.value))}
							aria-label="Zoom"
						/>
						<S.ZoomButton type="button" onClick={handleZoomOut} aria-label="Zoom out">
							{"\u2212"}
						</S.ZoomButton>
					</S.ZoomControls>
				</S.CropContent>
			</S.CropArea>
			<S.CancelButtonContainer>
				<Button type="button" buttonStyle="minimal" icon="refresh" onClick={onCancel}>
					Upload new image
				</Button>
			</S.CancelButtonContainer>
			<S.Actions>
				<Button type="button" buttonStyle="solid" onClick={handleConfirm}>
					Done
				</Button>
			</S.Actions>
		</S.Wrapper>
	);
};

interface IProps {
	imageSrc: string;
	onConfirm: (croppedAreaPixels: Area) => void;
	onCancel: () => void;
}

export default memo(CropStep);
