/**
 * GalleryCarouselOverlay Component
 *
 * Fullscreen carousel overlay for gallery elements.
 * Shows images in a slideshow with navigation buttons.
 * In constructor mode, buttons are draggable for positioning.
 */

import React, { useState, useEffect, useCallback, useRef } from 'react';
import Icon from '@mdi/react';
import { mdiChevronLeft, mdiChevronRight, mdiArrowLeft } from '@mdi/js';
import type { GalleryCard } from '../../types/constructor';
import { resolveAssetPlaybackUrl } from '../../lib/assetUrl';

interface GalleryCarouselOverlayProps {
  cards: GalleryCard[];
  initialIndex: number;
  onClose: () => void;
  resolveUrl?: (url: string | undefined) => string;
  // Button icons (MDI fallback if not set)
  prevIconUrl?: string;
  nextIconUrl?: string;
  backIconUrl?: string;
  backLabel?: string;
  // Button positions (percentage-based, like canvas elements)
  prevX?: number;
  prevY?: number;
  nextX?: number;
  nextY?: number;
  backX?: number;
  backY?: number;
  // Button dimensions (CSS values like '48px', '3rem')
  // When set with custom icon, button renders like NavigationElement (icon fills full button)
  prevWidth?: string;
  prevHeight?: string;
  nextWidth?: string;
  nextHeight?: string;
  backWidth?: string;
  backHeight?: string;
  // Constructor mode: buttons draggable
  isEditMode?: boolean;
  onButtonPositionChange?: (
    button: 'prev' | 'next' | 'back',
    x: number,
    y: number,
  ) => void;
}

const clamp = (value: number, min: number, max: number) =>
  Math.min(Math.max(value, min), max);

const GalleryCarouselOverlay: React.FC<GalleryCarouselOverlayProps> = ({
  cards,
  initialIndex,
  onClose,
  resolveUrl,
  prevIconUrl,
  nextIconUrl,
  backIconUrl,
  backLabel = 'BACK',
  prevX = 5,
  prevY = 50,
  nextX = 95,
  nextY = 50,
  backX = 5,
  backY = 90,
  prevWidth,
  prevHeight,
  nextWidth,
  nextHeight,
  backWidth,
  backHeight,
  isEditMode = false,
  onButtonPositionChange,
}) => {
  const resolve = resolveUrl ?? resolveAssetPlaybackUrl;
  const [currentIndex, setCurrentIndex] = useState(initialIndex);
  const [draggingButton, setDraggingButton] = useState<
    'prev' | 'next' | 'back' | null
  >(null);
  const [positions, setPositions] = useState({
    prevX,
    prevY,
    nextX,
    nextY,
    backX,
    backY,
  });
  const overlayRef = useRef<HTMLDivElement>(null);
  const touchStartRef = useRef<{ x: number; y: number } | null>(null);
  const positionsRef = useRef(positions);
  positionsRef.current = positions;

  // Update positions when props change (e.g., when element is re-selected)
  useEffect(() => {
    setPositions({ prevX, prevY, nextX, nextY, backX, backY });
  }, [prevX, prevY, nextX, nextY, backX, backY]);

  // Navigation handlers
  const goToPrev = useCallback(() => {
    if (cards.length === 0) return;
    setCurrentIndex((prev) => (prev - 1 + cards.length) % cards.length);
  }, [cards.length]);

  const goToNext = useCallback(() => {
    if (cards.length === 0) return;
    setCurrentIndex((prev) => (prev + 1) % cards.length);
  }, [cards.length]);

  // Keyboard navigation
  useEffect(() => {
    const handleKeyDown = (e: KeyboardEvent) => {
      if (e.key === 'Escape') {
        onClose();
      } else if (e.key === 'ArrowLeft') {
        goToPrev();
      } else if (e.key === 'ArrowRight') {
        goToNext();
      }
    };

    window.addEventListener('keydown', handleKeyDown);
    return () => window.removeEventListener('keydown', handleKeyDown);
  }, [onClose, goToPrev, goToNext]);

  // Touch swipe handling
  const handleTouchStart = (e: React.TouchEvent) => {
    if (isEditMode) return;
    touchStartRef.current = {
      x: e.touches[0].clientX,
      y: e.touches[0].clientY,
    };
  };

  const handleTouchEnd = (e: React.TouchEvent) => {
    if (isEditMode || !touchStartRef.current) return;

    const touchEnd = {
      x: e.changedTouches[0].clientX,
      y: e.changedTouches[0].clientY,
    };

    const deltaX = touchEnd.x - touchStartRef.current.x;
    const threshold = 50;

    if (Math.abs(deltaX) > threshold) {
      if (deltaX > 0) {
        goToPrev();
      } else {
        goToNext();
      }
    }

    touchStartRef.current = null;
  };

  // Draggable button handling (constructor mode only)
  const handleButtonDragStart = (
    button: 'prev' | 'next' | 'back',
    e: React.MouseEvent,
  ) => {
    if (!isEditMode) return;
    e.preventDefault();
    e.stopPropagation();
    setDraggingButton(button);
  };

  useEffect(() => {
    if (!isEditMode || !draggingButton) return;

    const handleMove = (e: MouseEvent) => {
      const x = (e.clientX / window.innerWidth) * 100;
      const y = (e.clientY / window.innerHeight) * 100;
      const clampedX = clamp(x, 2, 98);
      const clampedY = clamp(y, 2, 98);

      setPositions((prev) => {
        // Prev and next buttons share the same Y coordinate
        if (draggingButton === 'prev' || draggingButton === 'next') {
          return {
            ...prev,
            [`${draggingButton}X`]: clampedX,
            prevY: clampedY,
            nextY: clampedY,
          };
        }
        // Back button has independent position
        return {
          ...prev,
          [`${draggingButton}X`]: clampedX,
          [`${draggingButton}Y`]: clampedY,
        };
      });
    };

    const handleUp = () => {
      if (onButtonPositionChange && draggingButton) {
        const currentPositions = positionsRef.current;
        const posKey = `${draggingButton}X` as keyof typeof positions;
        const posKeyY = `${draggingButton}Y` as keyof typeof positions;
        onButtonPositionChange(
          draggingButton,
          currentPositions[posKey],
          currentPositions[posKeyY],
        );
        // For prev/next, also update the other button's Y position
        if (draggingButton === 'prev') {
          onButtonPositionChange('next', currentPositions.nextX, currentPositions.prevY);
        } else if (draggingButton === 'next') {
          onButtonPositionChange('prev', currentPositions.prevX, currentPositions.nextY);
        }
      }
      setDraggingButton(null);
    };

    window.addEventListener('mousemove', handleMove);
    window.addEventListener('mouseup', handleUp);
    return () => {
      window.removeEventListener('mousemove', handleMove);
      window.removeEventListener('mouseup', handleUp);
    };
  }, [isEditMode, draggingButton, onButtonPositionChange]);

  // Convert numeric value to rem CSS value
  const toRem = (value?: string): string | undefined => {
    if (!value || value.trim() === '') return undefined;
    const num = parseFloat(value);
    if (!Number.isFinite(num) || num <= 0) return undefined;
    return `${num}rem`;
  };

  // Render navigation button
  // When custom icon is set, render like NavigationElement (icon fills full button, no backdrop)
  // Otherwise, use MDI fallback with backdrop styling
  const renderNavButton = (
    type: 'prev' | 'next' | 'back',
    x: number,
    y: number,
    iconUrl?: string,
    defaultIcon?: string,
    label?: string,
    buttonWidth?: string,
    buttonHeight?: string,
  ) => {
    const isDragging = draggingButton === type;
    const isNavButton = type === 'prev' || type === 'next';
    const hasCustomIcon = iconUrl && iconUrl.trim() !== '';
    const widthRem = toRem(buttonWidth);
    const heightRem = toRem(buttonHeight);

    // Navigation-style rendering: custom icon fills full button (like NavigationElement)
    // When custom icon is set, always use navigation style (icon only, no backdrop)
    const useNavigationStyle = hasCustomIcon;

    return (
      <button
        type='button'
        className={`absolute flex items-center justify-center transition-transform ${
          isEditMode
            ? 'cursor-move hover:scale-110'
            : 'cursor-pointer hover:scale-105'
        } ${isDragging ? 'scale-110 z-[60]' : ''}`}
        style={{
          left: `${x}%`,
          top: `${y}%`,
          transform: 'translate(-50%, -50%)',
          // Apply dimensions when set
          ...(widthRem && { width: widthRem }),
          ...(heightRem && { height: heightRem }),
        }}
        onClick={(e) => {
          e.stopPropagation();
          if (isEditMode) return;
          if (type === 'prev') goToPrev();
          else if (type === 'next') goToNext();
          else onClose();
        }}
        onMouseDown={(e) => handleButtonDragStart(type, e)}
      >
        {useNavigationStyle ? (
          // Navigation-style: icon fills full button, no backdrop, no label
          // eslint-disable-next-line @next/next/no-img-element
          <img
            src={resolve(iconUrl)}
            alt=''
            style={{
              width: '100%',
              height: '100%',
              objectFit: 'contain',
            }}
            draggable={false}
          />
        ) : (
          // Default style: MDI icon with backdrop
          <div
            className={`flex items-center gap-2 ${
              isNavButton
                ? 'rounded-full bg-black/40 p-3 backdrop-blur-sm'
                : 'rounded-lg bg-black/40 px-4 py-2 backdrop-blur-sm'
            }`}
          >
            {defaultIcon && (
              <Icon
                path={defaultIcon}
                size={isNavButton ? 1.5 : 1}
                className='text-white'
              />
            )}
            {label && (
              <span className='text-sm font-medium text-white'>{label}</span>
            )}
          </div>
        )}
      </button>
    );
  };

  const currentCard = cards[currentIndex];
  const imageUrl = currentCard?.imageUrl ? resolve(currentCard.imageUrl) : '';

  return (
    <div
      ref={overlayRef}
      className='fixed inset-0 z-50 overflow-hidden bg-black'
      onClick={(e) => {
        // Only close if clicking the background, not buttons
        if (e.target === overlayRef.current && !isEditMode) {
          onClose();
        }
      }}
      onTouchStart={handleTouchStart}
      onTouchEnd={handleTouchEnd}
    >
      {/* Fullscreen image */}
      {imageUrl && (
        // eslint-disable-next-line @next/next/no-img-element
        <img
          src={imageUrl}
          alt={currentCard?.title || ''}
          className='absolute inset-0 h-full w-full object-cover'
          draggable={false}
        />
      )}

      {/* Prev button */}
      {renderNavButton(
        'prev',
        positions.prevX,
        positions.prevY,
        prevIconUrl,
        mdiChevronLeft,
        undefined,
        prevWidth,
        prevHeight,
      )}

      {/* Next button */}
      {renderNavButton(
        'next',
        positions.nextX,
        positions.nextY,
        nextIconUrl,
        mdiChevronRight,
        undefined,
        nextWidth,
        nextHeight,
      )}

      {/* Back button */}
      {renderNavButton(
        'back',
        positions.backX,
        positions.backY,
        backIconUrl,
        mdiArrowLeft,
        backLabel,
        backWidth,
        backHeight,
      )}

    </div>
  );
};

export default GalleryCarouselOverlay;
