// ============================================================
// MediaPreview — 全屏/灯箱预览
//
// 双击 MediaCard 时弹出，显示大图/视频/音频。
// - 图片：全屏显示原图（4096px LOD）
// - 视频：HTML5 <video> 播放器
// - 音频：HTML5 <audio> 播放器
//
// 文件加载：通过 local-media:// 自定义协议加载本地文件，
// 主进程 protocol.handle 拦截并返回文件内容。
// ============================================================

import { useState, useEffect, useMemo, useRef, useCallback } from 'react';
import { Button } from 'antd';
import { CloseOutlined, LeftOutlined, RightOutlined, ZoomInOutlined, ZoomOutOutlined } from '@ant-design/icons';
import { useCanvasStore } from '../../stores/useCanvasStore';

interface MediaPreviewProps {
    itemId: number | null;
    onClose: () => void;
}

/** 将文件路径转为 local-media:// URL（通过自定义协议安全加载本地文件） */
function toMediaUrl(filePath: string): string {
    // 优先通过 preload 注入的 canvas.getMediaUrl
    if (typeof window.canvas?.getMediaUrl === 'function') {
        return window.canvas.getMediaUrl(filePath);
    }
    // 回退（非 Electron 环境，一般不可用）
    return `file://${filePath.replace(/\\/g, '/')}`;
}

export function MediaPreview({ itemId, onClose }: MediaPreviewProps) {
    const items = useCanvasStore((s) => s.items);
    const [currentId, setCurrentId] = useState(itemId);

    // 同步外部 itemId 变化
    useEffect(() => {
        setCurrentId(itemId);
    }, [itemId]);

    // ⚠️ useMemo 必须在所有条件 return 之前调用（Rules of Hooks）
    const navigate = useMemo(() => {
        return (direction: -1 | 1) => {
            const idx = items.findIndex((i) => i.id === currentId);
            const next = idx + direction;
            if (next >= 0 && next < items.length) {
                setCurrentId(items[next].id);
            }
        };
    }, [items, currentId]);

    // ── 缩放 & 拖拽状态 ──
    const [previewZoom, setPreviewZoom] = useState(1);
    const [previewPan, setPreviewPan] = useState({ x: 0, y: 0 });
    const [isPanning, setIsPanning] = useState(false);
    const imgContainerRef = useRef<HTMLDivElement>(null);
    const videoRef = useRef<HTMLVideoElement>(null);
    const audioRef = useRef<HTMLAudioElement>(null);
    const panStartRef = useRef({ x: 0, y: 0, panX: 0, panY: 0 });
    // ref 版 zoom（供稳定闭包的 native wheel listener 读取）
    const previewZoomRef = useRef(previewZoom);
    useEffect(() => { previewZoomRef.current = previewZoom; }, [previewZoom]);

    // 切换图片时重置缩放/平移
    useEffect(() => {
        setPreviewZoom(1);
        setPreviewPan({ x: 0, y: 0 });
    }, [currentId]);

    // 预览内滚轮缩放（随 currentId 变化重新绑定，解决首次挂载时 ref 为 null 的问题）
    useEffect(() => {
        const el = imgContainerRef.current;
        if (!el) return;
        const handler = (e: WheelEvent) => {
            e.preventDefault();
            e.stopPropagation();
            const delta = -e.deltaY * 0.002;
            const cur = previewZoomRef.current;
            const newZoom = Math.max(0.1, Math.min(8.0, cur + delta));
            setPreviewZoom(newZoom);
        };
        el.addEventListener('wheel', handler, { passive: false });
        return () => el.removeEventListener('wheel', handler);
    }, [currentId]);

    // ── 拖拽平移（仅在预览内）──
    const handlePreviewMouseDown = useCallback((e: React.MouseEvent) => {
        if (e.button !== 0) return;
        const target = e.target as HTMLElement;
        if (target.closest('button')) return;
        e.stopPropagation(); // 阻止冒泡到 CanvasViewport
        setIsPanning(true);
        panStartRef.current = {
            x: e.clientX,
            y: e.clientY,
            panX: previewPan.x,
            panY: previewPan.y,
        };
    }, [previewPan]);

    const handlePreviewMouseMove = useCallback((e: React.MouseEvent) => {
        if (!isPanning) return;
        e.stopPropagation();
        const dx = e.clientX - panStartRef.current.x;
        const dy = e.clientY - panStartRef.current.y;
        setPreviewPan({
            x: panStartRef.current.panX + dx,
            y: panStartRef.current.panY + dy,
        });
    }, [isPanning]);

    const handlePreviewMouseUp = useCallback((e: React.MouseEvent) => {
        e.stopPropagation();
        setIsPanning(false);
    }, []);

    // 全局 mouseup（拖拽到预览外释放）
    useEffect(() => {
        const handler = () => setIsPanning(false);
        window.addEventListener('mouseup', handler);
        return () => window.removeEventListener('mouseup', handler);
    }, []);

    // ── 键盘媒体控制 ──
    // 所有按键在 capture 阶段拦截，优先于原生 <video controls>：
    //   空格     → 暂停/播放（stopPropagation 阻止原生二次触发）
    //   ← / →   → 快退/快进 0.5 秒（直接设 currentTime）
    //   ↑ / ↓   → 透传到原生 controls 处理音量
    useEffect(() => {
        if (currentId == null) return;

        const handler = (e: KeyboardEvent) => {
            const target = e.target as HTMLElement;
            if (target.tagName === 'INPUT' || target.tagName === 'TEXTAREA') return;

            const video = videoRef.current;
            const audio = audioRef.current;
            const media = video || audio;
            if (!media) return;

            // 空格 → 暂停/播放
            if (e.key === ' ') {
                e.preventDefault();
                e.stopPropagation();
                if (media.paused) void media.play();
                else media.pause();
                return;
            }

            // ← / → → 快退/快进 0.5 秒
            if (e.key === 'ArrowLeft' || e.key === 'ArrowRight') {
                e.preventDefault();
                e.stopPropagation();
                const delta = e.key === 'ArrowLeft' ? -0.5 : 0.5;
                media.currentTime = Math.max(0, media.currentTime + delta);
                return;
            }

            // ↑ / ↓ → 不拦截，透传给原生 controls（原生音量 ±10%）
        };
        // capture: true → 在原生 video controls 之前拦截
        window.addEventListener('keydown', handler, true);
        return () => window.removeEventListener('keydown', handler, true);
    }, [currentId]);

    // 媒体元素挂载后自动聚焦（确保原生 controls 能接收 ↑/↓ 音量事件）
    useEffect(() => {
        const timer = setTimeout(() => {
            if (videoRef.current) videoRef.current.focus();
            else if (audioRef.current) audioRef.current.focus();
        }, 100);
        return () => clearTimeout(timer);
    }, [currentId]);

    if (currentId == null) return null;

    const currentItem = items.find((i) => i.id === currentId);
    if (!currentItem) return null;

    const isImage = ['jpg', 'jpeg', 'png', 'webp', 'bmp', 'gif'].includes(
        currentItem.ext,
    );
    const isVideo = ['mp4', 'webm', 'mov', 'avi', 'mkv'].includes(
        currentItem.ext,
    );
    const isAudio = ['mp3', 'wav', 'ogg', 'flac', 'aac', 'm4a'].includes(
        currentItem.ext,
    );

    const mediaUrl = toMediaUrl(currentItem.path);

    return (
        <div
            style={{
                position: 'fixed',
                top: 0,
                left: 0,
                width: '100vw',
                height: '100vh',
                zIndex: 9999,
                background: 'rgba(0, 0, 0, 0.92)',
                display: 'flex',
                flexDirection: 'column',
                alignItems: 'center',
                justifyContent: 'center',
            }}
            onClick={(e) => {
                if (e.target === e.currentTarget) onClose();
            }}
        >
            {/* 顶栏 */}
            <div
                style={{
                    position: 'absolute',
                    top: 0,
                    left: 0,
                    right: 0,
                    height: 48,
                    display: 'flex',
                    alignItems: 'center',
                    padding: '0 16px',
                    background: 'rgba(0,0,0,0.5)',
                }}
            >
                <span style={{ color: '#fff', fontSize: 13, flex: 1, overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' }}>
                    {currentItem.fileName}
                </span>
                <Button
                    type="text"
                    icon={<CloseOutlined />}
                    onClick={onClose}
                    style={{ color: '#fff' }}
                />
            </div>

            {/* 内容 */}
            <div style={{ flex: 1, display: 'flex', alignItems: 'center', justifyContent: 'center', padding: 48 }}>
                {isImage && (
                    <div
                        ref={imgContainerRef}
                        style={{
                            maxWidth: '90vw',
                            maxHeight: '85vh',
                            overflow: 'hidden',
                            display: 'flex',
                            alignItems: 'center',
                            justifyContent: 'center',
                            cursor: isPanning ? 'grabbing' : previewZoom > 1 ? 'grab' : 'default',
                        }}
                        onMouseDown={handlePreviewMouseDown}
                        onMouseMove={handlePreviewMouseMove}
                        onMouseUp={handlePreviewMouseUp}
                    >
                        <img
                            src={mediaUrl}
                            alt={currentItem.fileName}
                            draggable={false}
                            style={{
                                maxWidth: previewZoom === 1 ? '100%' : 'none',
                                maxHeight: previewZoom === 1 ? '100%' : 'none',
                                objectFit: 'contain',
                                borderRadius: 4,
                                transform: `translate(${previewPan.x}px, ${previewPan.y}px) scale(${previewZoom})`,
                                transformOrigin: 'center center',
                                userSelect: 'none',
                            }}
                            onLoad={(e) => {
                                // 预留：naturalWidth/Height 可用于智能初始缩放
                                void e.currentTarget.naturalWidth;
                            }}
                        />
                    </div>
                )}
                {isVideo && (
                    <video
                        ref={videoRef}
                        src={mediaUrl}
                        controls
                        autoPlay
                        tabIndex={0}
                        style={{ maxWidth: '90vw', maxHeight: '85vh', borderRadius: 4, outline: 'none' }}
                    />
                )}
                {isAudio && (
                    <div style={{ textAlign: 'center', color: '#fff' }}>
                        <div style={{ fontSize: 48, marginBottom: 16 }}>🎵</div>
                        <div style={{ fontSize: 16, marginBottom: 12 }}>{currentItem.fileName}</div>
                        <audio ref={audioRef} src={mediaUrl} controls autoPlay />
                    </div>
                )}
            </div>

            {/* 导航按钮 */}
            <Button
                type="text"
                icon={<LeftOutlined />}
                onClick={() => navigate(-1)}
                style={{
                    position: 'absolute',
                    left: 16,
                    top: '50%',
                    transform: 'translateY(-50%)',
                    color: '#fff',
                    fontSize: 24,
                    width: 48,
                    height: 48,
                }}
            />
            <Button
                type="text"
                icon={<RightOutlined />}
                onClick={() => navigate(1)}
                style={{
                    position: 'absolute',
                    right: 16,
                    top: '50%',
                    transform: 'translateY(-50%)',
                    color: '#fff',
                    fontSize: 24,
                    width: 48,
                    height: 48,
                }}
            />

            {/* 缩放指示器（仅图片模式显示） */}
            {isImage && (
                <div
                    style={{
                        position: 'absolute',
                        bottom: 48,
                        right: 16,
                        display: 'flex',
                        alignItems: 'center',
                        gap: 2,
                        padding: '2px 6px',
                        borderRadius: 8,
                        background: 'rgba(0, 0, 0, 0.6)',
                        backdropFilter: 'blur(4px)',
                        boxShadow: '0 2px 8px rgba(0,0,0,0.3)',
                    }}
                >
                    <Button
                        type="text"
                        size="small"
                        icon={<ZoomOutOutlined />}
                        disabled={previewZoom <= 0.1}
                        onClick={() => setPreviewZoom(Math.max(0.1, previewZoom - 0.25))}
                        style={{ color: '#fff' }}
                    />
                    <span
                        style={{
                            color: '#fff',
                            fontSize: 12,
                            fontWeight: 600,
                            minWidth: 44,
                            textAlign: 'center',
                            cursor: 'pointer',
                            userSelect: 'none',
                        }}
                        onClick={() => {
                            setPreviewZoom(1);
                            setPreviewPan({ x: 0, y: 0 });
                        }}
                        title="重置缩放 (100%)"
                    >
                        {Math.round(previewZoom * 100)}%
                    </span>
                    <Button
                        type="text"
                        size="small"
                        icon={<ZoomInOutlined />}
                        disabled={previewZoom >= 8.0}
                        onClick={() => setPreviewZoom(Math.min(8.0, previewZoom + 0.25))}
                        style={{ color: '#fff' }}
                    />
                </div>
            )}

            {/* 底栏信息 */}
            <div
                style={{
                    position: 'absolute',
                    bottom: 0,
                    left: 0,
                    right: 0,
                    height: 36,
                    display: 'flex',
                    alignItems: 'center',
                    justifyContent: 'center',
                    background: 'rgba(0,0,0,0.5)',
                    color: '#aaa',
                    fontSize: 11,
                }}
            >
                {currentItem.groupKey} · {currentItem.stage} · {items.findIndex((i) => i.id === currentId) + 1} / {items.length}
            </div>
        </div>
    );
}
