import React, { useEffect, useRef, useState } from "react";

const PointBlurImageComponent = ({ imageSrc, blurredRegions, loaded, setLoaded, reloading, setReloading, setInfoImage, listLabel = [] }) => {
	const points = useRef([]);
	const canvasRef = useRef(null);
	const isImageLoaded = useRef(false);
	const [draggingPointIndex, setDraggingPointIndex] = useState(null);
	const [movingRegionIndex, setMovingRegionIndex] = useState(null);
	const [offset, setOffset] = useState({ x: 0, y: 0 });
	const [info, setInfo] = useState({});
	const [isOpen, setIsOpen] = useState(false);

	useEffect(() => {
		const canvas = canvasRef.current;
		const ctx = canvas.getContext("2d");
		const image = new Image();

		image.onload = () => {
			canvas.width = image.width;
			canvas.height = image.height;
			ctx.drawImage(image, 0, 0);
			isImageLoaded.current = true;
			setInfoImage({ width: image.width, height: image.height });
		};

		image.crossOrigin = "anonymous";
		image.src = imageSrc;
		setInfo({});
		setIsOpen(false);
		points.current = []; // Clear points after blurring
		setReloading((pre) => !pre);
	}, [imageSrc]);

	useEffect(() => {
		if (blurredRegions?.current?.length > 0) {
			redrawCanvas();
			setLoaded(true);
		}
	}, [blurredRegions?.current, reloading]);

	useEffect(() => {
		const canvas = canvasRef.current;

		const handleCanvasClick = (event) => {
			if (!isImageLoaded.current) return;
			const { x, y } = getMousePos(canvas, event);

			// Check if a delete button is clicked
			for (let i = 0; i < blurredRegions.current.length; i++) {
				const region = blurredRegions.current[i];
				const buttonX = (region[0].x + region[1].x) / 2;
				const buttonY = Math.min(region[0].y, region[1].y, region[2].y, region[3].y) - 20;
				if (Math.abs(buttonX - x) < 30 && Math.abs(buttonY - y) < 10) {
					// blurredRegions.current.splice(i, 1);
					if (info?.index === i) {
						setInfo({});
						setIsOpen(false);
						return;
					}
					setInfo({ index: i, value: blurredRegions.current[i] });
					setIsOpen(true);
					redrawCanvas(i);
					return;
				}
			}
			if (isOpen) return;
			const arrLabel = (listLabel[0]?.name || ["logo.cisco"])?.split(".");
			const label = arrLabel?.length > 1 ? arrLabel[1] : arrLabel[0];
			const subLabel = arrLabel?.length > 1 ? arrLabel[0] : null;
			points.current.push({ x, y, label: label, subLabel: subLabel });
			drawRedPoint(canvas, x, y);

			if (points.current.length === 4) {
				blurredRegions.current.push([...points.current]);
				points.current = []; // Clear points after blurring
				setReloading((pre) => !pre);
			}
		};

		const handleCanvasMouseDown = (event) => {
			const { x, y } = getMousePos(canvas, event);

			for (let i = 0; i < blurredRegions.current.length; i++) {
				// Check if we clicked on an existing point
				for (let j = 0; j < blurredRegions.current[i].length; j++) {
					const point = blurredRegions.current[i][j];
					if (Math.abs(point.x - x) < 5 && Math.abs(point.y - y) < 5) {
						setDraggingPointIndex({ regionIndex: i, pointIndex: j });
						setOffset({ x: point.x - x, y: point.y - y });
						return;
					}
				}

				// Check if we clicked inside a region
				const region = blurredRegions.current[i];
				if (isPointInRegion(x, y, region)) {
					// Check if a delete button is clicked
					for (let i = 0; i < blurredRegions.current.length; i++) {
						const region = blurredRegions.current[i];
						const buttonX = (region[0].x + region[1].x) / 2;
						const buttonY = Math.min(region[0].y, region[1].y, region[2].y, region[3].y) - 20;
						if (Math.abs(buttonX - x) < 30 && Math.abs(buttonY - y) < 10) {
							// blurredRegions.current.splice(i, 1);
							if (info?.index === i) {
								setInfo({});
								setIsOpen(false);
								return;
							}
							setInfo({ index: i, value: blurredRegions.current[i] });
							setIsOpen(true);
							redrawCanvas(i);
							return;
						}
					}
					if (isOpen) return;
					setMovingRegionIndex(i);
					setOffset({ x: region[0].x - x, y: region[0].y - y });
					return;
				}
			}

			handleCanvasClick(event);
		};

		const handleCanvasMouseUp = () => {
			setDraggingPointIndex(null);
			setMovingRegionIndex(null);
			redrawCanvas(info?.index);
		};

		const handleCanvasMouseMove = (event) => {
			if (draggingPointIndex === null && movingRegionIndex === null) return;

			const { x, y } = getMousePos(canvas, event);

			if (draggingPointIndex !== null) {
				const { regionIndex, pointIndex } = draggingPointIndex;
				blurredRegions.current[regionIndex][pointIndex] = {
					x: x + offset.x,
					y: y + offset.y,
					label: blurredRegions.current[regionIndex][pointIndex]?.label,
					subLabel: blurredRegions.current[regionIndex][pointIndex]?.subLabel,
				};
				redrawCanvas();
			} else if (movingRegionIndex !== null) {
				const region = blurredRegions.current[movingRegionIndex];
				const dx = x + offset.x - region[0].x;
				const dy = y + offset.y - region[0].y;

				for (let i = 0; i < region.length; i++) {
					region[i].x += dx;
					region[i].y += dy;
				}
				redrawCanvas();
			}
		};

		canvas.addEventListener("mousedown", handleCanvasMouseDown);
		canvas.addEventListener("mouseup", handleCanvasMouseUp);
		canvas.addEventListener("mousemove", handleCanvasMouseMove);

		return () => {
			canvas.removeEventListener("mousedown", handleCanvasMouseDown);
			canvas.removeEventListener("mouseup", handleCanvasMouseUp);
			canvas.removeEventListener("mousemove", handleCanvasMouseMove);
		};
	}, [draggingPointIndex, movingRegionIndex, offset, isOpen, info]);

	const getMousePos = (canvas, event) => {
		const rect = canvas.getBoundingClientRect();
		return {
			x: event.clientX - rect.left,
			y: event.clientY - rect.top,
		};
	};

	const isPointInRegion = (x, y, region) => {
		const [A, B, C, D] = region;

		const sign = (p1, p2, p3) => (p1.x - p3.x) * (p2.y - p3.y) - (p2.x - p3.x) * (p1.y - p3.y);
		const d1 = sign({ x, y }, A, B);
		const d2 = sign({ x, y }, B, C);
		const d3 = sign({ x, y }, C, D);
		const d4 = sign({ x, y }, D, A);

		const hasNeg = d1 < 0 || d2 < 0 || d3 < 0 || d4 < 0;
		const hasPos = d1 > 0 || d2 > 0 || d3 > 0 || d4 > 0;

		return !(hasNeg && hasPos);
	};

	const drawRedPoint = (canvas, x, y) => {
		const ctx = canvas.getContext("2d");
		ctx.save();
		ctx.beginPath();
		ctx.arc(x, y, 5, 0, 2 * Math.PI);
		ctx.fillStyle = "red";
		ctx.fill();
		ctx.restore();
	};

	const drawBorder = (canvas, points) => {
		const ctx = canvas.getContext("2d");
		ctx.save();
		ctx.beginPath();
		points.forEach((point, index) => {
			if (index === 0) {
				ctx.moveTo(point.x, point.y);
			} else {
				ctx.lineTo(point.x, point.y);
			}
		});
		ctx.closePath();
		ctx.lineWidth = 2;
		ctx.strokeStyle = "blue";
		ctx.stroke();
		ctx.restore();

		points.forEach((point) => drawRedPoint(canvas, point.x, point.y));
	};

	const drawDeleteButton = (canvas, region, isSelected) => {
		const ctx = canvas.getContext("2d");
		const buttonX = (region[0].x + region[1].x) / 2;
		const buttonY = Math.min(region[0].y, region[1].y, region[2].y, region[3].y) - 20;

		ctx.save();
		ctx.fillStyle = isSelected ? "rgb(196, 194, 61, 0.5)" : "rgb(2, 101, 182, 0.5)";
		ctx.fillRect(buttonX - 30, buttonY - 10, Math.max(region[0]?.label?.length * 6 + 20, region[0]?.subLabel?.length * 5 + 10), 25);
		ctx.fillStyle = "rgb(255, 255, 255)";
		ctx.font = "9px Arial";
		ctx.textAlign = "center";
		ctx.fillText(region[0]?.subLabel, buttonX - 10, buttonY);
		ctx.font = "11px Arial";
		ctx.textAlign = "center";
		ctx.fillText(region[0]?.label, buttonX, buttonY + 10);
		ctx.restore();
	};

	const redrawCanvas = (index) => {
		const canvas = canvasRef.current;
		const ctx = canvas.getContext("2d");
		const image = new Image();

		image.onload = () => {
			ctx.clearRect(0, 0, canvas.width, canvas.height);
			ctx.drawImage(image, 0, 0);

			blurredRegions.current.forEach((region, i) => {
				drawBorder(canvas, region);
				drawDeleteButton(canvas, region, index === i);
			});

			points.current.forEach((point) => {
				drawRedPoint(canvas, point.x, point.y);
			});
		};

		image.crossOrigin = "anonymous";
		image.src = imageSrc;
	};

	return (
		<div style={{ position: "relative" }}>
			<canvas ref={canvasRef} />
			{isOpen && (
				<div
					style={{
						backgroundColor: "#FFF",
						position: "absolute",
						top: info?.value[0].y - 30,
						left: info?.value[0].x < 200 ? info?.value[0].x + 50 : info?.value[0].x - 170,
						zIndex: 9999,
					}}>
					<div>
						<span style={{ color: "#000", fontSize: "18px", fontWeight: "bold" }}>Select label</span>
					</div>
					{listLabel?.map((el, i) => (
						<div key={i}>
							<button
								onClick={() => {
									const arrLabel = el?.name?.split(".");
									const label = arrLabel?.length > 1 ? arrLabel[1] : arrLabel[0];
									const subLabel = arrLabel?.length > 1 ? arrLabel[0] : null;
									const newList = info?.value?.map((pre) => ({ ...pre, label: label, subLabel: subLabel }));
									blurredRegions.current[info?.index] = newList;
									setInfo({});
									setIsOpen(false);
									redrawCanvas();
								}}
								style={{ backgroundColor: "#ccc", width: "150px", color: "#000" }}>
								{el?.name}
							</button>
						</div>
					))}
					<div>
						<button
							onClick={() => {
								blurredRegions.current.splice(info?.index, 1);
								setInfo({});
								setIsOpen(false);
								redrawCanvas();
							}}
							style={{ backgroundColor: "#ff0000", marginBottom: "10px", width: "150px", color: "#fff" }}>
							Delete
						</button>
					</div>
				</div>
			)}
		</div>
	);
};

export default PointBlurImageComponent;
