{% extends "base.html" %}

{% block extra_head %}
<style>
  /* Immersive Discovery Feed */
  body {
    background-color: #000;
  }
  
  #image-grid {
    column-count: 2;
    column-gap: 8px;
    padding: 8px;
  }
  @media (min-width: 640px) { #image-grid { column-count: 3; } }
  @media (min-width: 1024px) { #image-grid { column-count: 4; } }
  @media (min-width: 1536px) { #image-grid { column-count: 5; } }

  .grid-item {
    break-inside: avoid;
    margin-bottom: 8px;
    border-radius: 12px;
    overflow: hidden;
    position: relative;
    background: #1a1a1a;
    cursor: pointer;
    transition: transform 0.2s ease;
  }
  .grid-item:active {
    transform: scale(0.98);
  }
  .grid-item img {
    width: 100%;
    height: auto;
    display: block;
    opacity: 0;
    transition: opacity 0.4s ease;
  }
  .grid-item img.loaded {
    opacity: 1;
  }

  #img-loading {
    text-align: center;
    color: #666;
    padding: 40px;
    font-size: 14px;
  }

  /* Modal Overlay */
  #modal {
    position: fixed;
    inset: 0;
    z-index: 200;
    background: rgba(0,0,0,0.95);
    display: none;
    align-items: center;
    justify-content: center;
    backdrop-filter: blur(10px);
  }
  #modal.active {
    display: flex;
  }
  #modal img {
    max-width: 100%;
    max-height: 100%;
    object-fit: contain;
    border-radius: 8px;
    transition: opacity 0.2s ease;
  }
  /* Floating Toolbar */
  .toolbar {
    position: fixed;
    bottom: 20px;
    right: 20px;
    display: flex;
    gap: 12px;
    z-index: 220;
    align-items: center;
    transition: opacity 0.2s ease, transform 0.2s ease;
  }
  .tool-btn {
    width: 44px;
    height: 44px;
    border-radius: 50%;
    background: rgba(255, 255, 255, 0.1);
    backdrop-filter: blur(10px);
    display: flex;
    align-items: center;
    justify-content: center;
    color: white;
    transition: all 0.2s ease;
    cursor: pointer;
    border: 1px solid rgba(255,255,255,0.1);
    position: relative;
  }
  .tool-btn:active { transform: scale(0.95); }
  .tool-btn.active {
    background: rgba(255, 255, 255, 0.25);
    color: white;
    border-color: white;
    box-shadow: 0 0 20px rgba(255,255,255,0.4);
    transform: scale(1.1);
  }

  /* Zoom Options (Pop-up) */
  .zoom-options {
    position: absolute;
    bottom: 60px; /* Above the toolbar */
    right: 0; 
    display: flex;
    flex-direction: column;
    gap: 8px;
    opacity: 0;
    pointer-events: none;
    transform: translateY(10px);
    transition: all 0.2s ease;
  }
  .zoom-options.show {
    opacity: 1;
    pointer-events: auto;
    transform: translateY(0);
  }
  .zoom-btn {
    width: 44px;
    height: 44px;
    border-radius: 50%;
    background: rgba(0, 0, 0, 0.6);
    backdrop-filter: blur(5px);
    color: rgba(255,255,255,0.6);
    font-size: 11px;
    font-weight: bold;
    display: flex;
    align-items: center;
    justify-content: center;
    border: 1px solid rgba(255,255,255,0.15);
    cursor: pointer;
    transition: all 0.2s ease;
  }
  .zoom-btn.active {
    background: rgba(255, 255, 255, 0.2);
    color: white;
    border-color: white;
    box-shadow: 0 0 10px rgba(255,255,255,0.3);
  }

  /* Magnifier */
  .magnifier {
    position: absolute;
    width: 220px;
    height: 220px;
    border-radius: 50%;
    border: 3px solid rgba(255, 255, 255, 0.9);
    box-shadow: 0 10px 40px rgba(0,0,0,0.6);
    background-repeat: no-repeat;
    background-color: #000;
    cursor: grab;
    z-index: 210;
    display: none;
    transform: translate(-50%, -50%) scale(0); 
    transition: transform 0.3s cubic-bezier(0.175, 0.885, 0.32, 1.275), width 0.3s ease, height 0.3s ease;
  }
  .magnifier.magnifier-large {
    width: 300px;
    height: 300px;
  }
  .magnifier.active {
    display: block;
    transform: translate(-50%, -50%) scale(1);
  }
  .magnifier:active {
    cursor: grabbing;
    transform: translate(-50%, -50%) scale(1.02);
  }
  /* Zoom Level Badge inside Lens */
  .mag-badge {
    position: absolute;
    bottom: 10px;
    left: 50%;
    transform: translateX(-50%);
    background: rgba(0,0,0,0.5);
    color: white;
    font-size: 10px;
    padding: 2px 6px;
    border-radius: 10px;
    pointer-events: none;
    opacity: 0;
    transition: opacity 0.2s;
  }
  .magnifier.active .mag-badge { opacity: 1; }

  .modal-close {
    position: absolute;
    top: 20px;
    right: 20px;
    color: white;
    background: rgba(255,255,255,0.1);
    border-radius: 50%;
    padding: 10px;
    cursor: pointer;
  }

  /* Caption Panel */
  .caption-panel {
    position: fixed;
    left: 20px;
    bottom: 90px;
    max-width: min(70vw, 420px);
    padding: 14px 16px;
    background: rgba(0, 0, 0, 0.55);
    border: 1px solid rgba(255, 255, 255, 0.12);
    border-radius: 14px;
    color: white;
    backdrop-filter: blur(10px);
    z-index: 215;
    display: flex;
    flex-direction: column;
    gap: 8px;
    transition: opacity 0.2s ease, transform 0.2s ease;
  }
  .caption-title {
    font-size: 14px;
    line-height: 1.4;
    font-weight: 600;
  }
  .caption-tags {
    display: flex;
    flex-wrap: wrap;
    gap: 6px;
  }
  .caption-tag {
    display: inline-flex;
    align-items: center;
    padding: 4px 8px;
    border-radius: 999px;
    background: rgba(255, 255, 255, 0.12);
    border: 1px solid rgba(255, 255, 255, 0.15);
    font-size: 11px;
    color: rgba(255, 255, 255, 0.85);
  }
  .caption-panel.is-hidden {
    display: none;
  }
  #modal.ui-hidden .caption-panel:not(.is-hidden) {
    opacity: 0;
    pointer-events: none;
    transform: translateY(12px);
  }

  #caption-btn.is-loading::after {
    content: '';
    position: absolute;
    inset: 7px;
    border-radius: 999px;
    border: 1.5px solid rgba(255, 255, 255, 0.7);
    border-top-color: transparent;
    animation: caption-spin 0.9s linear infinite;
  }
  #caption-btn.is-loading i {
    opacity: 0.35;
  }
  #caption-btn.is-error::after {
    content: '';
    position: absolute;
    inset: 7px;
    border-radius: 999px;
    border: 1.5px solid rgba(248, 113, 113, 0.9);
  }
  @keyframes caption-spin {
    to { transform: rotate(360deg); }
  }
</style>
{% endblock %}

{% block content %}
<div class="container mx-auto">
    <!-- Discover Grid -->
    <div id="image-grid"></div>
    <div id="img-loading">正在探索新内容...</div>
</div>

<!-- Simple Lightbox Modal -->
<div id="modal">
    <div class="modal-close" id="modal-close">
        <i data-feather="x"></i>
    </div>
    <img id="modal-img" src="" alt="">
    
    <div class="magnifier" id="magnifier">
        <div class="mag-badge" id="mag-badge">2.5x</div>
    </div>

    <div class="caption-panel is-hidden" id="caption-panel">
        <div class="caption-title" id="caption-title"></div>
        <div class="caption-tags" id="caption-tags"></div>
    </div>

    <!-- Toolbar & Controls -->
    <div class="toolbar">
        <button id="caption-btn" class="tool-btn" title="生成标题">
            <i data-feather="zap"></i>
        </button>
        <a id="modal-info" href="#" class="tool-btn">
            <i data-feather="info"></i>
        </a>
        <div style="position: relative;">
            <div class="zoom-options" id="zoom-options">
                <div class="zoom-btn" onclick="setZoom(5.0)">5x</div>
                <div class="zoom-btn active" onclick="setZoom(2.5)">2.5x</div>
            </div>
            <button id="magnifier-toggle" class="tool-btn">
                <i data-feather="search"></i>
            </button>
        </div>
    </div>
</div>
{% endblock %}

{% block extra_body %}
<script src="{{ url_for('static', filename='hammer.min.js') }}"></script>
<script>
  (() => {
    const grid = document.getElementById('image-grid');
    const loading = document.getElementById('img-loading');
    const modal = document.getElementById('modal');
    const modalImg = document.getElementById('modal-img');
    const modalClose = document.getElementById('modal-close');
    const modalInfo = document.getElementById('modal-info');
    const magnifier = document.getElementById('magnifier');
    const magToggle = document.getElementById('magnifier-toggle');
    const zoomOptions = document.getElementById('zoom-options');
    const magBadge = document.getElementById('mag-badge');
    const captionBtn = document.getElementById('caption-btn');
    const captionPanel = document.getElementById('caption-panel');
    const captionTitle = document.getElementById('caption-title');
    const captionTags = document.getElementById('caption-tags');

    let page = 1;
    let seed = null;
    let hasMore = true;
    let isLoading = false;
    let allImages = [];      
    let currentIndex = -1;
    let isMagnifying = false;
    let isUiHidden = false;
    let zoomLevel = 2.5; // Current Zoom Level
    let currentCaption = null;
    
    // Magnifier State
    let magX = 0;
    let magY = 0;

    async function loadImages() {
      if (isLoading || !hasMore) return;
      isLoading = true;
      loading.style.display = 'block';

      try {
        const url = `/api/random-images?page=${page}&size=30${seed ? '&seed=' + seed : ''}`;
        const res = await fetch(url);
        const data = await res.json();

        if (!seed) seed = data.seed;
        hasMore = data.has_more;

        data.images.forEach(uri => {
          allImages.push(uri);  
          const div = document.createElement('div');
          div.className = 'grid-item';
          div.innerHTML = `
            <img src="/media?uri=${encodeURIComponent(uri)}" loading="lazy"
                 onload="this.classList.add('loaded')"
                 onclick="openModal('${encodeURIComponent(uri)}')">
          `;
          grid.appendChild(div);
        });

        page++;
      } catch (err) {
        console.error('Failed to load images:', err);
      } finally {
        isLoading = false;
        loading.style.display = hasMore ? 'block' : 'none';
      }
    }

    window.openModal = (uri) => {
        const decodedUri = decodeURIComponent(uri);
        currentIndex = allImages.indexOf(decodedUri); 
        if (currentIndex === -1) {
            currentIndex = allImages.length;
            allImages.push(decodedUri);
        }
        showImage(currentIndex);
        setUiHidden(false);
        modal.classList.add('active');
        document.body.style.overflow = 'hidden';
    };

    const showImage = (newIndex) => {
        if (newIndex < 0 || newIndex >= allImages.length) return;
        currentIndex = newIndex;
        const uri = encodeURIComponent(allImages[currentIndex]);
        modalImg.src = `/media?uri=${uri}`;
        modalInfo.href = `/image?uri=${uri}`;
        loadCaption(allImages[currentIndex]);
        
        // Reset state
        setUiHidden(false);
        toggleMagnifier(false);

        preloadImage(currentIndex - 1);
        preloadImage(currentIndex + 1);

        if (currentIndex >= allImages.length - 5 && hasMore && !isLoading) {
            loadImages();
        }
    };

    const preloadImage = (idx) => {
        if (idx < 0 || idx >= allImages.length) return;
        const img = new Image();
        img.src = `/media?uri=${encodeURIComponent(allImages[idx])}`;
    };

    const closeModal = () => {
        modal.classList.remove('active');
        modalImg.style.transform = '';
        modalImg.style.transition = '';
        modal.style.backgroundColor = '';
        modal.style.transition = '';
        
        modalImg.src = '';
        setUiHidden(false);
        toggleMagnifier(false);
        clearCaption();
        document.body.style.overflow = '';
    };

    const setUiHidden = (hidden) => {
        isUiHidden = hidden;
        modal.classList.toggle('ui-hidden', hidden);
    };

    const toggleUi = () => {
        setUiHidden(!isUiHidden);
    };

    // Zoom Level Control
    window.setZoom = (level) => {
        zoomLevel = level;
        magBadge.innerText = level + 'x';
        
        // Update active state of zoom buttons (Fix: avoid partial matches like '2.5' in '5')
        document.querySelectorAll('.zoom-btn').forEach(btn => {
            const btnLevel = parseFloat(btn.innerText);
            btn.classList.toggle('active', btnLevel === level);
        });

        // Dynamic Sizing: 5x zoom gets a larger lens
        if (level >= 5.0) {
            magnifier.classList.add('magnifier-large');
        } else {
            magnifier.classList.remove('magnifier-large');
        }

        if (isMagnifying) {
            // Re-render content as size changed
            setTimeout(updateMagnifierContent, 50); // Small delay to allow CSS width change
        }
    };

    // Toggle Magnifier Mode
    const toggleMagnifier = (active) => {
        isMagnifying = active;
        if (isMagnifying) {
            magToggle.classList.add('active');
            zoomOptions.classList.add('show');
            
            magnifier.classList.add('active');
            
            // Initial Position: Center of screen
            magX = window.innerWidth / 2;
            magY = window.innerHeight / 2;
            
            updateMagnifierPosition();
            updateMagnifierContent();
        } else {
            magToggle.classList.remove('active');
            zoomOptions.classList.remove('show');
            magnifier.classList.remove('active');
        }
    };
    
    magToggle.addEventListener('click', (e) => {
        e.stopPropagation(); 
        toggleMagnifier(!isMagnifying);
    });

    const clearCaption = () => {
        currentCaption = null;
        captionTitle.textContent = '';
        captionTitle.classList.add('hidden');
        captionTags.innerHTML = '';
        captionPanel.classList.add('is-hidden');
    };

    const renderCaption = (data) => {
        currentCaption = data || null;
        if (!data) {
            clearCaption();
            return;
        }
        const title = data.title || '';
        const tags = Array.isArray(data.tags) ? data.tags : [];
        if (!title && tags.length === 0) {
            clearCaption();
            return;
        }
        captionPanel.classList.remove('is-hidden');
        captionTitle.textContent = title;
        captionTitle.classList.toggle('hidden', !title);
        captionTags.innerHTML = '';
        tags.forEach(tag => {
            const chip = document.createElement('span');
            chip.className = 'caption-tag';
            chip.textContent = tag;
            captionTags.appendChild(chip);
        });
    };

    const setCaptionLoading = (loading) => {
        captionBtn.disabled = loading;
        captionBtn.classList.toggle('is-loading', loading);
    };

    const loadCaption = async (uri) => {
        clearCaption();
        try {
            const res = await fetch(`/api/image/metadata?uri=${encodeURIComponent(uri)}`);
            const data = await res.json();
            if (data.success) {
                renderCaption(data.data);
            } else {
                captionBtn.title = data.error || '读取失败';
                captionBtn.classList.add('is-error');
                setTimeout(() => captionBtn.classList.remove('is-error'), 1500);
            }
        } catch (err) {
            captionBtn.title = '读取失败';
            captionBtn.classList.add('is-error');
            setTimeout(() => captionBtn.classList.remove('is-error'), 1500);
        }
    };

    const generateCaption = async (uri, force = false) => {
        if (currentCaption && !force) {
            const ok = window.confirm('已存在标题，是否覆盖？');
            if (!ok) return;
            force = true;
        }
        setCaptionLoading(true);
        try {
            const res = await fetch('/api/image/metadata', {
                method: 'POST',
                headers: { 'Content-Type': 'application/json' },
                body: JSON.stringify({ uri, force })
            });
            const data = await res.json();
            if (data.success) {
                renderCaption(data.data);
            } else {
                captionBtn.title = data.error || '生成失败';
                captionBtn.classList.add('is-error');
                setTimeout(() => captionBtn.classList.remove('is-error'), 1500);
            }
        } catch (err) {
            captionBtn.title = '生成失败';
            captionBtn.classList.add('is-error');
            setTimeout(() => captionBtn.classList.remove('is-error'), 1500);
        } finally {
            setCaptionLoading(false);
        }
    };

    captionBtn.addEventListener('click', (e) => {
        e.preventDefault();
        if (currentIndex < 0) return;
        generateCaption(allImages[currentIndex]);
    });

    modalImg.addEventListener('click', (e) => {
        e.stopPropagation();
        if (isMagnifying) return;
        toggleUi();
    });

    // Update Magnifier DOM Position
    const updateMagnifierPosition = () => {
        magnifier.style.left = magX + 'px';
        magnifier.style.top = magY + 'px';
    };

    // Update Magnifier Background (The Zoom Effect)
    const updateMagnifierContent = () => {
        const rect = modalImg.getBoundingClientRect();
        
        const relX = (magX - rect.left) / rect.width;
        const relY = (magY - rect.top) / rect.height;
        
        magnifier.style.backgroundImage = `url('${modalImg.src}')`;
        magnifier.style.backgroundSize = `${rect.width * zoomLevel}px ${rect.height * zoomLevel}px`;
        
        const magWidth = magnifier.offsetWidth;
        const magHeight = magnifier.offsetHeight;

        const bgX = - (relX * rect.width * zoomLevel - magWidth / 2);
        const bgY = - (relY * rect.height * zoomLevel - magHeight / 2);
        
        magnifier.style.backgroundPosition = `${bgX}px ${bgY}px`;
    };

    modalClose.addEventListener('click', closeModal);
    // Click outside logic
    modal.addEventListener('click', (e) => { 
        // If click is on toolbar or its children, do nothing (handled by stopPropagation usually)
        if (e.target.closest('.toolbar')) return;

        if(e.target === modal) {
            if (isMagnifying) {
                toggleMagnifier(false);
            } else {
                closeModal(); 
            }
        }
    });

    // Hammer.js Setup for Modal (Swipe/Close)
    const modalHammer = new Hammer(modal);
    modalHammer.get('swipe').set({ direction: Hammer.DIRECTION_HORIZONTAL });
    modalHammer.get('pan').set({ direction: Hammer.DIRECTION_ALL, threshold: 10 });

    // Gestures
    modalHammer.on('swipeleft', () => !isMagnifying && showImage(currentIndex + 1));
    modalHammer.on('swiperight', () => !isMagnifying && showImage(currentIndex - 1));

    modalHammer.on('panstart', (e) => {
        if (isMagnifying) return; 
        modalImg.style.transition = 'none';
        modal.style.transition = 'none';
    });

    modalHammer.on('panmove', (e) => {
        if (isMagnifying) return;

        if (Math.abs(e.deltaY) > Math.abs(e.deltaX)) {
            const deltaY = e.deltaY;
            const percent = Math.min(Math.abs(deltaY) / window.innerHeight, 1);
            modalImg.style.transform = `translateY(${deltaY}px) scale(${1 - percent * 0.4})`;
            modal.style.backgroundColor = `rgba(0,0,0,${0.95 * (1 - percent)})`;
        }
    });

    modalHammer.on('panend', (e) => {
        if (isMagnifying) return;

        const shouldClose = Math.abs(e.deltaY) > 150 || Math.abs(e.velocityY) > 0.5;
        const isVertical = Math.abs(e.deltaY) > Math.abs(e.deltaX);
        
        if (shouldClose && isVertical) {
            closeModal();
        } else {
            modalImg.style.transition = 'transform 0.3s ease';
            modal.style.transition = 'background-color 0.3s ease';
            modalImg.style.transform = '';
            modal.style.backgroundColor = '';
        }
    });

    // Dedicated Hammer for Magnifier Draggable
    const magHammer = new Hammer(magnifier);
    magHammer.get('pan').set({ direction: Hammer.DIRECTION_ALL, threshold: 0 });

    let startX = 0, startY = 0;

    magHammer.on('panstart', (e) => {
        startX = magX;
        startY = magY;
        magnifier.style.transition = 'none'; 
    });

    magHammer.on('panmove', (e) => {
        magX = startX + e.deltaX;
        magY = startY + e.deltaY;
        updateMagnifierPosition();
        updateMagnifierContent();
    });

    magHammer.on('panend', (e) => {
        magnifier.style.transition = 'transform 0.3s cubic-bezier(0.175, 0.885, 0.32, 1.275)'; 
    });

    window.addEventListener('scroll', () => {
      if (window.innerHeight + window.scrollY >= document.body.offsetHeight - 800) {
        loadImages();
      }
    });

    // 增强键盘支持
    document.addEventListener('keydown', (e) => {
        if (!modal.classList.contains('active')) return;
        if (e.key === 'Escape') closeModal();
        if (e.key === 'ArrowLeft') showImage(currentIndex - 1);
        if (e.key === 'ArrowRight') showImage(currentIndex + 1);
        if (e.key === 'i' || e.key === 'I') {
            if (isMagnifying) return;
            toggleUi();
        }
    });

    // Init
    loadImages();
  })();
</script>
{% endblock %}
