import React, { useEffect, useMemo, useState } from 'react';
import { Box } from '@mantine/core';
import type { SignParameters } from '@app/hooks/tools/sign/useSignParameters';
import { buildSignaturePreview, SignaturePreview } from '@app/utils/signaturePreview';
import { useSignature } from '@app/contexts/SignatureContext';
import {
  MAX_PREVIEW_WIDTH_RATIO,
  MAX_PREVIEW_HEIGHT_RATIO,
  MAX_PREVIEW_WIDTH_REM,
  MAX_PREVIEW_HEIGHT_REM,
  MIN_SIGNATURE_DIMENSION_REM,
  OVERLAY_EDGE_PADDING_REM,
} from '@app/constants/signConstants';

// Convert rem to pixels using browser's base font size (typically 16px)
const remToPx = (rem: number) => rem * parseFloat(getComputedStyle(document.documentElement).fontSize);

interface StampPlacementOverlayProps {
  containerRef: React.RefObject<HTMLElement | null>;
  isActive: boolean;
  signatureConfig: SignParameters | null;
}

export const StampPlacementOverlay: React.FC<StampPlacementOverlayProps> = ({
  containerRef,
  isActive,
  signatureConfig,
}) => {
  const [preview, setPreview] = useState<SignaturePreview | null>(null);
  const [cursor, setCursor] = useState<{ x: number; y: number } | null>(null);
  const { setPlacementPreviewSize } = useSignature();

  useEffect(() => {
    let cancelled = false;

    const buildPreview = async () => {
      try {
        const value = await buildSignaturePreview(signatureConfig ?? null);
        if (!cancelled) {
          setPreview(value);
        }
      } catch (error) {
        console.error('Failed to build signature preview:', error);
        if (!cancelled) {
          setPreview(null);
        }
      }
    };

    buildPreview();

    return () => {
      cancelled = true;
    };
  }, [signatureConfig]);

  useEffect(() => {
    const element = containerRef.current;
    if (!isActive || !element) {
      setCursor(null);
      return;
    }

    const handleMove = (event: MouseEvent) => {
      const rect = element.getBoundingClientRect();
      setCursor({
        x: event.clientX - rect.left,
        y: event.clientY - rect.top,
      });
    };

    const handleLeave = () => setCursor(null);

    element.addEventListener('mousemove', handleMove);
    element.addEventListener('mouseleave', handleLeave);

    return () => {
      element.removeEventListener('mousemove', handleMove);
      element.removeEventListener('mouseleave', handleLeave);
    };
  }, [containerRef, isActive]);

  const scaledSize = useMemo(() => {
    if (!preview || !containerRef.current) {
      return null;
    }

    const container = containerRef.current;
    const containerWidth = container.clientWidth || 1;
    const containerHeight = container.clientHeight || 1;

    const maxWidth = Math.min(containerWidth * MAX_PREVIEW_WIDTH_RATIO, remToPx(MAX_PREVIEW_WIDTH_REM));
    const maxHeight = Math.min(containerHeight * MAX_PREVIEW_HEIGHT_RATIO, remToPx(MAX_PREVIEW_HEIGHT_REM));

    const scale = Math.min(
      1,
      maxWidth / Math.max(preview.width, 1),
      maxHeight / Math.max(preview.height, 1)
    );

    return {
      width: Math.max(remToPx(MIN_SIGNATURE_DIMENSION_REM), preview.width * scale),
      height: Math.max(remToPx(MIN_SIGNATURE_DIMENSION_REM), preview.height * scale),
    };
  }, [preview, containerRef]);

  useEffect(() => {
    if (!isActive || !scaledSize) {
      setPlacementPreviewSize(null);
    } else {
      setPlacementPreviewSize(scaledSize);
    }
  }, [isActive, scaledSize, setPlacementPreviewSize]);

  useEffect(() => {
    return () => {
      setPlacementPreviewSize(null);
    };
  }, [setPlacementPreviewSize]);

  const display = useMemo(() => {
    if (!preview || !scaledSize || !cursor || !containerRef.current) {
      return null;
    }

    const container = containerRef.current;
    const containerWidth = container.clientWidth || 1;
    const containerHeight = container.clientHeight || 1;

    const width = scaledSize.width;
    const height = scaledSize.height;
    const edgePadding = remToPx(OVERLAY_EDGE_PADDING_REM);

    const clampedLeft = Math.max(edgePadding, Math.min(cursor.x - width / 2, containerWidth - width - edgePadding));
    const clampedTop = Math.max(edgePadding, Math.min(cursor.y - height / 2, containerHeight - height - edgePadding));

    return {
      left: clampedLeft,
      top: clampedTop,
      width,
      height,
      dataUrl: preview.dataUrl,
    };
  }, [preview, scaledSize, cursor, containerRef]);

  if (!isActive || !display || !preview) {
    return null;
  }

  return (
    <Box
      style={{
        position: 'absolute',
        pointerEvents: 'none',
        left: `${display.left}px`,
        top: `${display.top}px`,
        width: `${display.width}px`,
        height: `${display.height}px`,
        backgroundImage: `url(${display.dataUrl})`,
        backgroundSize: '100% 100%',
        backgroundRepeat: 'no-repeat',
        backgroundPosition: 'center',
        boxShadow: '0 0 0 1px rgba(30, 136, 229, 0.55), 0 6px 18px rgba(30, 136, 229, 0.25)',
        borderRadius: '4px',
        transition: 'transform 70ms ease-out',
        transform: 'translateZ(0)',
        opacity: 0.6,
      }}
    />
  );
};
