// LightboxModal.tsx
import React, { useEffect, useRef, useState } from 'react';
import {
    Dialog,
    IconButton,
    Box,
    Typography,
    Tooltip,
    CircularProgress,
} from '@mui/material';
import CloseIcon from '@mui/icons-material/Close';
import ArrowBackIosNewIcon from '@mui/icons-material/ArrowBackIosNew';
import ArrowForwardIosIcon from '@mui/icons-material/ArrowForwardIos';
import DownloadIcon from '@mui/icons-material/Download';
// import ZoomOutMapIcon from '@mui/icons-material/ZoomOutMap';
import AddIcon from '@mui/icons-material/Add';
import RemoveIcon from '@mui/icons-material/Remove';
import FitScreenIcon from '@mui/icons-material/FitScreen';

export type LightboxPhoto = {
    id: number | string;
    url: string;
    title?: string;
    filename?: string;
    created_at?: string;
    naturalWidth?: number;
    naturalHeight?: number;
};

type Props = {
    open: boolean;
    photos: LightboxPhoto[];
    startIndex?: number;
    onClose: () => void;
    startIndexCallback?: (idx: number) => void;
};

const SWIPE_THRESHOLD = 40;
const MIN_SCALE = 0.1;
const MAX_SCALE = 5;
const SCALE_STEP = 0.25;

export default function LightboxModal({
    open,
    photos,
    startIndex = 0,
    onClose,
    startIndexCallback,
}: Props) {
    const [index, setIndex] = useState<number>(startIndex);
    const [scale, setScale] = useState<number>(1);
    const [translate, setTranslate] = useState<{ x: number; y: number }>({ x: 0, y: 0 });
    const [isPanning, setIsPanning] = useState(false);
    const [isLoading, setIsLoading] = useState(true);
    const [imageDimensions, setImageDimensions] = useState<{ width: number; height: number } | null>(null);
    const panStart = useRef<{ x: number; y: number } | null>(null);
    const lastTranslate = useRef<{ x: number; y: number }>({ x: 0, y: 0 });

    const touchStartX = useRef<number | null>(null);
    const touchDeltaX = useRef(0);

    // For pinch
    const pinchStartDist = useRef<number | null>(null);
    const pinchStartScale = useRef<number>(1);
    const imageRef = useRef<HTMLImageElement>(null);

    useEffect(() => setIndex(startIndex), [startIndex, open]);

    useEffect(() => {
        window.addEventListener('keydown', onKey);
        return () => window.removeEventListener('keydown', onKey);
        // eslint-disable-next-line react-hooks/exhaustive-deps
    }, [open, index, scale]);

    useEffect(() => startIndexCallback?.(index), [index]);

    useEffect(() => {
        // reset scale/translate when changing image or closing/opening
        setScale(1);
        setTranslate({ x: 0, y: 0 });
        lastTranslate.current = { x: 0, y: 0 };
        setIsLoading(true);
        setImageDimensions(null);
    }, [index, open]);

    const onKey = (e: KeyboardEvent) => {
        if (!open) return;
        if (e.key === 'Escape') onClose();
        if (e.key === 'ArrowLeft') prev();
        if (e.key === 'ArrowRight') next();
        if (e.key === '+' || (e.ctrlKey && e.key === '=')) zoomIn();
        if (e.key === '-') zoomOut();
        if (e.key === '0') fitToScreen();
    };

    const prev = () => setIndex((i) => (i - 1 + photos.length) % photos.length);
    const next = () => setIndex((i) => (i + 1) % photos.length);

    // Preload neighbors
    useEffect(() => {
        if (!photos?.length) return;
        const a = new Image();
        a.src = photos[(index - 1 + photos.length) % photos.length]?.url;
        const b = new Image();
        b.src = photos[(index + 1) % photos.length]?.url;
    }, [index, photos]);

    const photo = photos && photos.length ? photos[index] : null;

    // Handle image load
    const handleImageLoad = (e: React.SyntheticEvent<HTMLImageElement>) => {
        setIsLoading(false);
        const img = e.currentTarget;
        setImageDimensions({
            width: img.naturalWidth,
            height: img.naturalHeight
        });
    };

    const handleImageError = () => {
        setIsLoading(false);
        setImageDimensions(null);
    };

    if (!photo) return null;

    /* ============================
       Zoom / Pan Controls
    ============================ */
    const setScaleClamped = (s: number) => {
        const clamped = Math.max(MIN_SCALE, Math.min(MAX_SCALE, s));
        setScale(clamped);
        if (clamped === 1) {
            // reset translate when fully fit
            setTranslate({ x: 0, y: 0 });
            lastTranslate.current = { x: 0, y: 0 };
        }
    };

    const zoomIn = () => setScaleClamped(scale + SCALE_STEP);
    const zoomOut = () => setScaleClamped(scale - SCALE_STEP);
    const fitToScreen = () => setScaleClamped(1);
    // eslint-disable-next-line @typescript-eslint/no-unused-vars
    const handleDoubleClick = (_e: React.MouseEvent) => {
        if (scale === 1) setScaleClamped(2);
        else setScaleClamped(1);
    };

    /* ============================
       Panning (pointer / touch)
    ============================ */
    const onPointerDown = (e: React.PointerEvent) => {
        if (scale <= 1) return;
        (e.target as Element).setPointerCapture?.(e.pointerId);
        setIsPanning(true);
        panStart.current = { x: e.clientX, y: e.clientY };
    };

    const onPointerMove = (e: React.PointerEvent) => {
        if (!isPanning || !panStart.current) return;
        const dx = e.clientX - panStart.current.x;
        const dy = e.clientY - panStart.current.y;
        const TX = lastTranslate.current.x + dx;
        const TY = lastTranslate.current.y + dy;
        setTranslate({ x: TX, y: TY });
    };

    const onPointerUp = (e: React.PointerEvent) => {
        if (!isPanning) return;
        setIsPanning(false);
        if (panStart.current) {
            const dx = e.clientX - panStart.current.x;
            const dy = e.clientY - panStart.current.y;
            lastTranslate.current = { x: lastTranslate.current.x + dx, y: lastTranslate.current.y + dy };
            panStart.current = null;
        }
        try {
            (e.target as Element).releasePointerCapture?.(e.pointerId);
        } catch {
            //ignore
        }
    };

    const onWheel = (e: React.WheelEvent) => {
        if (!open) return;
        e.preventDefault();
        const delta = -e.deltaY;
        const step = delta > 0 ? SCALE_STEP : -SCALE_STEP;
        setScaleClamped(scale + step);
    };

    /* ============================
       Touch handlers for swipe + pinch
       Note: use React.Touch types here to satisfy TS
    ============================ */
    const onTouchStart = (e: React.TouchEvent) => {
        touchDeltaX.current = 0;
        if (e.touches.length === 1) {
            touchStartX.current = e.touches[0].clientX;
            if (scale > 1) {
                panStart.current = { x: e.touches[0].clientX, y: e.touches[0].clientY };
                setIsPanning(true);
            }
        } else if (e.touches.length === 2) {
            pinchStartDist.current = getDistance(e.touches[0], e.touches[1]);
            pinchStartScale.current = scale;
            setIsPanning(false);
        }
    };

    const onTouchMove = (e: React.TouchEvent) => {
        if (e.touches.length === 1 && scale > 1 && isPanning && panStart.current) {
            const dx = e.touches[0].clientX - panStart.current.x;
            const dy = e.touches[0].clientY - panStart.current.y;
            setTranslate({ x: lastTranslate.current.x + dx, y: lastTranslate.current.y + dy });
            e.preventDefault();
        } else if (e.touches.length === 2 && pinchStartDist.current != null) {
            const dist = getDistance(e.touches[0], e.touches[1]);
            const ratio = dist / (pinchStartDist.current || dist);
            setScaleClamped(pinchStartScale.current * ratio);
            e.preventDefault();
        } else if (e.touches.length === 1) {
            const x = e.touches[0].clientX;
            touchDeltaX.current = x - (touchStartX.current ?? x);
        }
    };
    // eslint-disable-next-line @typescript-eslint/no-unused-vars
    const onTouchEnd = (_e: React.TouchEvent) => {
        if (isPanning) {
            setIsPanning(false);
            lastTranslate.current = { ...translate };
            panStart.current = null;
        }

        if (pinchStartDist.current != null) {
            pinchStartDist.current = null;
            pinchStartScale.current = scale;
        }

        if (Math.abs(touchDeltaX.current) > SWIPE_THRESHOLD && Math.abs(translate.x) < 10 && !isPanning) {
            if (touchDeltaX.current < 0) next();
            else prev();
        }

        touchDeltaX.current = 0;
        touchStartX.current = null;
    };

    // Helper accepting React.Touch (TS-friendly)
    function getDistance(a: React.Touch, b: React.Touch) {
        const dx = a.clientX - b.clientX;
        const dy = a.clientY - b.clientY;
        return Math.sqrt(dx * dx + dy * dy);
    }

    // Calculate image display size based on original dimensions
    const getImageDisplayStyle = () => {
        if (!imageDimensions) return {};

        const windowWidth = window.innerWidth;
        const windowHeight = window.innerHeight;
        const { width: imgWidth, height: imgHeight } = imageDimensions;

        // Calculate the maximum dimensions to fit in the viewport
        const maxWidth = windowWidth * 0.9; // 90% of window width
        const maxHeight = windowHeight * 0.8; // 80% of window height

        let displayWidth = imgWidth;
        let displayHeight = imgHeight;

        // If image is larger than max dimensions, scale it down
        if (imgWidth > maxWidth || imgHeight > maxHeight) {
            const widthRatio = maxWidth / imgWidth;
            const heightRatio = maxHeight / imgHeight;
            const ratio = Math.min(widthRatio, heightRatio);

            displayWidth = imgWidth * ratio;
            displayHeight = imgHeight * ratio;
        }

        return {
            width: `${displayWidth}px`,
            height: `${displayHeight}px`,
            maxWidth: '90vw',
            maxHeight: '80vh',
        };
    };

    /* ============================
       Render
    ============================ */
    return (
        <Dialog
            open={open}
            onClose={onClose}
            fullScreen
            PaperProps={{
                sx: {
                    m: 0,
                    p: 0,
                    height: '100vh',
                    backgroundColor: 'rgba(0,0,0,0.95)',
                    overflow: 'hidden',
                    '& .MuiDialog-container': {
                        alignItems: 'center',
                        justifyContent: 'center',
                    }
                },
            }}
        >
            <Box
                sx={{
                    width: '100%',
                    height: '100%',
                    position: 'relative',
                    boxSizing: 'border-box',
                    display: 'flex',
                    alignItems: 'center',
                    justifyContent: 'center',
                    userSelect: isPanning ? 'none' : 'auto',
                    touchAction: 'none',
                }}
                onWheel={onWheel}
                onTouchStart={onTouchStart}
                onTouchMove={onTouchMove}
                onTouchEnd={onTouchEnd}
                onClick={(e) => {
                    if (e.target === e.currentTarget) onClose();
                }}
            >
                {/* Loading indicator */}
                {isLoading && (
                    <Box sx={{
                        position: 'absolute',
                        top: '50%',
                        left: '50%',
                        transform: 'translate(-50%, -50%)',
                        zIndex: 10
                    }}>
                        <CircularProgress sx={{ color: 'rgba(255,255,255,0.7)' }} />
                    </Box>
                )}

                {/* Top right controls */}
                <Box sx={{
                    position: 'absolute',
                    top: 16,
                    right: 16,
                    zIndex: 60,
                    display: 'flex',
                    gap: 1,
                    background: 'rgba(0,0,0,0.5)',
                    borderRadius: 2,
                    p: 0.5,
                    backdropFilter: 'blur(10px)',
                }}>
                    <Tooltip title="Zoom Out">
                        <IconButton
                            size="small"
                            onClick={(ev) => {
                                ev.stopPropagation();
                                zoomOut();
                            }}
                            sx={{
                                bgcolor: 'rgba(255,255,255,0.1)',
                                color: 'white',
                                '&:hover': { bgcolor: 'rgba(255,255,255,0.2)' }
                            }}
                        >
                            <RemoveIcon />
                        </IconButton>
                    </Tooltip>

                    <Tooltip title="Fit to screen">
                        <IconButton
                            size="small"
                            onClick={(ev) => {
                                ev.stopPropagation();
                                fitToScreen();
                            }}
                            sx={{
                                bgcolor: 'rgba(255,255,255,0.1)',
                                color: 'white',
                                '&:hover': { bgcolor: 'rgba(255,255,255,0.2)' }
                            }}
                        >
                            <FitScreenIcon />
                        </IconButton>
                    </Tooltip>

                    <Tooltip title="Zoom In">
                        <IconButton
                            size="small"
                            onClick={(ev) => {
                                ev.stopPropagation();
                                zoomIn();
                            }}
                            sx={{
                                bgcolor: 'rgba(255,255,255,0.1)',
                                color: 'white',
                                '&:hover': { bgcolor: 'rgba(255,255,255,0.2)' }
                            }}
                        >
                            <AddIcon />
                        </IconButton>
                    </Tooltip>

                    <Tooltip title="Download">
                        <IconButton
                            size="small"
                            onClick={(ev) => {
                                ev.stopPropagation();
                                try {
                                    const a = document.createElement('a');
                                    a.href = photo.url;
                                    a.download = `${photo.filename ?? photo.title ?? 'image'}`;
                                    document.body.appendChild(a);
                                    a.click();
                                    a.remove();
                                } catch (err) {
                                    console.error('download', err);
                                }
                            }}
                            sx={{
                                bgcolor: 'rgba(255,255,255,0.1)',
                                color: 'white',
                                '&:hover': { bgcolor: 'rgba(255,255,255,0.2)' }
                            }}
                        >
                            <DownloadIcon />
                        </IconButton>
                    </Tooltip>

                    <Tooltip title="Close (Esc)">
                        <IconButton
                            size="small"
                            onClick={(ev) => {
                                ev.stopPropagation();
                                onClose();
                            }}
                            sx={{
                                bgcolor: 'rgba(255,255,255,0.1)',
                                color: 'white',
                                '&:hover': { bgcolor: 'rgba(255,255,255,0.2)' }
                            }}
                        >
                            <CloseIcon />
                        </IconButton>
                    </Tooltip>
                </Box>

                {/* Prev / Next arrows */}
                <IconButton
                    onClick={(ev) => {
                        ev.stopPropagation();
                        prev();
                    }}
                    sx={{
                        position: 'absolute',
                        left: 16,
                        zIndex: 50,
                        color: 'white',
                        bgcolor: 'rgba(0,0,0,0.5)',
                        backdropFilter: 'blur(10px)',
                        '&:hover': { bgcolor: 'rgba(0,0,0,0.7)' }
                    }}
                >
                    <ArrowBackIosNewIcon />
                </IconButton>

                <IconButton
                    onClick={(ev) => {
                        ev.stopPropagation();
                        next();
                    }}
                    sx={{
                        position: 'absolute',
                        right: 16,
                        zIndex: 50,
                        color: 'white',
                        bgcolor: 'rgba(0,0,0,0.5)',
                        backdropFilter: 'blur(10px)',
                        '&:hover': { bgcolor: 'rgba(0,0,0,0.7)' }
                    }}
                >
                    <ArrowForwardIosIcon />
                </IconButton>

                {/* Image container */}
                <Box
                    sx={{
                        width: '100%',
                        height: '100%',
                        px: 2,
                        boxSizing: 'border-box',
                        display: 'flex',
                        alignItems: 'center',
                        justifyContent: 'center',
                        overflow: 'hidden',
                    }}
                    onPointerDown={onPointerDown}
                    onPointerMove={onPointerMove}
                    onPointerUp={onPointerUp}
                    onPointerCancel={onPointerUp}
                    onDoubleClick={handleDoubleClick}
                >
                    <Box
                        sx={{
                            display: 'flex',
                            alignItems: 'center',
                            justifyContent: 'center',
                            touchAction: 'none',
                            position: 'relative',
                        }}
                    >
                        <img
                            ref={imageRef}
                            src={photo.url}
                            alt={photo.title ?? photo.filename}
                            onLoad={handleImageLoad}
                            onError={handleImageError}
                            style={{
                                display: isLoading ? 'none' : 'block',
                                width: 'auto',
                                height: 'auto',
                                maxWidth: '90vw',
                                maxHeight: '80vh',
                                objectFit: 'contain',
                                transform: `translate(${translate.x}px, ${translate.y}px) scale(${scale})`,
                                transition: isPanning ? 'none' : 'transform 120ms ease',
                                cursor: scale > 1 ? (isPanning ? 'grabbing' : 'grab') : 'default',
                                borderRadius: 4,
                                boxShadow: '0 10px 30px rgba(0,0,0,0.6)',
                                touchAction: 'none',
                                ...getImageDisplayStyle(),
                            }}
                            draggable={false}
                        />
                    </Box>
                </Box>

                {/* Caption */}
                <Box sx={{
                    position: 'absolute',
                    bottom: 16,
                    left: 16,
                    right: 16,
                    textAlign: 'center',
                    zIndex: 50,
                    background: 'rgba(0,0,0,0.5)',
                    backdropFilter: 'blur(10px)',
                    borderRadius: 2,
                    p: 1.5,
                    maxWidth: '600px',
                    mx: 'auto',
                }}>
                    <Typography variant="subtitle1" color="white" noWrap sx={{ fontWeight: 500 }}>
                        {photo.title ?? photo.filename}
                    </Typography>
                    <Typography variant="caption" color="rgba(255,255,255,0.85)" sx={{ display: 'block', mt: 0.5 }}>
                        {index + 1} of {photos.length}
                        {photo.created_at && ` • ${new Date(photo.created_at).toLocaleDateString('en-US', {
                            year: 'numeric',
                            month: 'long',
                            day: 'numeric'
                        })}`}
                        {imageDimensions && ` • ${imageDimensions.width}×${imageDimensions.height}`}
                    </Typography>
                </Box>

                {/* Zoom level indicator */}
                {scale !== 1 && (
                    <Box sx={{
                        position: 'absolute',
                        top: 16,
                        left: 16,
                        zIndex: 50,
                        background: 'rgba(0,0,0,0.5)',
                        backdropFilter: 'blur(10px)',
                        borderRadius: 2,
                        p: 1,
                        color: 'white',
                        fontSize: '0.875rem',
                        fontWeight: 500,
                    }}>
                        {Math.round(scale * 100)}%
                    </Box>
                )}
            </Box>
        </Dialog>
    );
}