import './styles/collect.scss';
import { createCollectFeedback } from './collect_feedback';

type GalleryItem = {
    kind: 'image' | 'video' | 'file';
    name: string;
    preview: string;
    download: string;
    publicId?: string;
    el: HTMLButtonElement;
};

const root = document.getElementById('collectGuestGallery');
const lightbox = document.getElementById('collectLightbox');
const mediaHost = document.getElementById('collectLightboxMedia');
const nameEl = document.getElementById('collectLightboxName');
const counterEl = document.getElementById('collectLightboxCounter');
const downloadBtn = document.getElementById('collectLightboxDownload') as HTMLAnchorElement | null;

const items: GalleryItem[] = Array.from(
    document.querySelectorAll<HTMLButtonElement>('.collect-gallery__item')
).map((el) => ({
    kind: (el.dataset.kind as GalleryItem['kind']) || 'file',
    name: el.dataset.name || '',
    preview: el.dataset.preview || '',
    download: el.dataset.download || '',
    publicId: el.dataset.publicId || undefined,
    el,
}));

const mediaItems = items.filter((i) => (i.kind === 'image' || i.kind === 'video') && i.preview);

const imageFeedback = root
    ? createCollectFeedback({
          urls: {
              feedback: root.dataset.feedbackUrl || '',
              rate: root.dataset.feedbackRateUrl || '',
              comment: root.dataset.feedbackCommentUrl || '',
              viewed: root.dataset.feedbackViewedUrl || '',
          },
          labels: {
              rate: root.dataset.feedbackRateLabel || 'Rate this image',
              average: root.dataset.feedbackAverageLabel || '%average% / 5 (%count%)',
              commentPlaceholder: root.dataset.feedbackCommentPlaceholder || '',
              commentSubmit: root.dataset.feedbackCommentSubmit || 'Send',
              noComments: root.dataset.feedbackNoComments || 'No comments yet',
              missingActor: root.dataset.feedbackMissingActor || 'Email required',
          },
          getCurrentItem: () => {
              const item = mediaItems[index];
              if (!item) return null;
              return { kind: item.kind, publicId: item.publicId };
          },
      })
    : { refresh: () => undefined };

let index = 0;
let zoom = 1;
let panX = 0;
let panY = 0;
let dragging = false;
let dragStartX = 0;
let dragStartY = 0;
let panStartX = 0;
let panStartY = 0;

const applyZoom = () => {
    const target = mediaHost?.querySelector<HTMLElement>('img, video');
    if (!target) return;
    target.style.transform = `translate(${panX}px, ${panY}px) scale(${zoom})`;
    target.classList.toggle('is-zoomed', zoom > 1);
};

const resetZoom = () => {
    zoom = 1;
    panX = 0;
    panY = 0;
    applyZoom();
};

const renderSlide = () => {
    if (!mediaHost || !lightbox || !mediaItems.length) return;
    const item = mediaItems[index];
    mediaHost.innerHTML = '';
    resetZoom();

    if (item.kind === 'video') {
        const video = document.createElement('video');
        video.src = item.preview;
        video.controls = true;
        video.playsInline = true;
        video.autoplay = true;
        video.className = 'collect-lightbox__video';
        mediaHost.appendChild(video);
    } else {
        const img = document.createElement('img');
        img.src = item.preview;
        img.alt = item.name;
        img.className = 'collect-lightbox__image';
        img.draggable = false;
        mediaHost.appendChild(img);
    }

    if (nameEl) nameEl.textContent = item.name;
    if (counterEl) counterEl.textContent = `${index + 1} / ${mediaItems.length}`;

    if (downloadBtn) {
        if (item.download) {
            downloadBtn.hidden = false;
            downloadBtn.href = item.download;
            downloadBtn.setAttribute('download', item.name);
        } else {
            downloadBtn.hidden = true;
            downloadBtn.removeAttribute('href');
        }
    }

    imageFeedback.refresh();
};

const openLightbox = (mediaIndex: number) => {
    if (!lightbox || !mediaItems.length) return;
    index = Math.max(0, Math.min(mediaIndex, mediaItems.length - 1));
    lightbox.hidden = false;
    document.body.classList.add('collect-lightbox-open');
    renderSlide();
};

const closeLightbox = () => {
    if (!lightbox) return;
    const video = mediaHost?.querySelector('video');
    video?.pause();
    lightbox.hidden = true;
    document.body.classList.remove('collect-lightbox-open');
    if (mediaHost) mediaHost.innerHTML = '';
};

const step = (delta: number) => {
    if (!mediaItems.length) return;
    index = (index + delta + mediaItems.length) % mediaItems.length;
    renderSlide();
};

items.forEach((item) => {
    item.el.addEventListener('click', () => {
        if ((item.kind === 'image' || item.kind === 'video') && item.preview) {
            const mediaIndex = mediaItems.indexOf(item);
            openLightbox(mediaIndex >= 0 ? mediaIndex : 0);
            return;
        }
        if (item.download) {
            window.location.href = item.download;
        }
    });
});

lightbox?.querySelectorAll('[data-lightbox-close]').forEach((el) => {
    el.addEventListener('click', closeLightbox);
});
lightbox?.querySelector('[data-lightbox-prev]')?.addEventListener('click', () => step(-1));
lightbox?.querySelector('[data-lightbox-next]')?.addEventListener('click', () => step(1));

document.getElementById('collectLightboxZoomIn')?.addEventListener('click', () => {
    zoom = Math.min(4, zoom + 0.25);
    applyZoom();
});
document.getElementById('collectLightboxZoomOut')?.addEventListener('click', () => {
    zoom = Math.max(1, zoom - 0.25);
    if (zoom === 1) {
        panX = 0;
        panY = 0;
    }
    applyZoom();
});
document.getElementById('collectLightboxZoomReset')?.addEventListener('click', resetZoom);

mediaHost?.addEventListener('wheel', (e) => {
    const item = mediaItems[index];
    if (!item || item.kind !== 'image') return;
    e.preventDefault();
    const next = e.deltaY < 0 ? zoom + 0.15 : zoom - 0.15;
    zoom = Math.min(4, Math.max(1, next));
    if (zoom === 1) {
        panX = 0;
        panY = 0;
    }
    applyZoom();
}, { passive: false });

mediaHost?.addEventListener('dblclick', () => {
    const item = mediaItems[index];
    if (!item || item.kind !== 'image') return;
    if (zoom > 1) {
        resetZoom();
    } else {
        zoom = 2;
        applyZoom();
    }
});

mediaHost?.addEventListener('pointerdown', (e) => {
    const item = mediaItems[index];
    if (!item || item.kind !== 'image' || zoom <= 1) return;
    const target = e.target as HTMLElement;
    if (target.tagName !== 'IMG') return;
    dragging = true;
    dragStartX = e.clientX;
    dragStartY = e.clientY;
    panStartX = panX;
    panStartY = panY;
    mediaHost.setPointerCapture(e.pointerId);
});

mediaHost?.addEventListener('pointermove', (e) => {
    if (!dragging) return;
    panX = panStartX + (e.clientX - dragStartX);
    panY = panStartY + (e.clientY - dragStartY);
    applyZoom();
});

mediaHost?.addEventListener('pointerup', () => {
    dragging = false;
});
mediaHost?.addEventListener('pointercancel', () => {
    dragging = false;
});

document.addEventListener('keydown', (e) => {
    if (!lightbox || lightbox.hidden) return;
    if (e.key === 'Escape') closeLightbox();
    if (e.key === 'ArrowLeft') step(-1);
    if (e.key === 'ArrowRight') step(1);
    if (e.key === '+' || e.key === '=') {
        zoom = Math.min(4, zoom + 0.25);
        applyZoom();
    }
    if (e.key === '-') {
        zoom = Math.max(1, zoom - 0.25);
        if (zoom === 1) {
            panX = 0;
            panY = 0;
        }
        applyZoom();
    }
});

// Upload (guest)
const uploadRoot = document.getElementById('collectUpload');
if (uploadRoot) {
    const input = document.getElementById('collectFileInput') as HTMLInputElement | null;
    const list = document.getElementById('collectUploadList');
    const url = uploadRoot.dataset.uploadUrl;

    const uploadFile = async (file: File) => {
        if (!url) return;
        const item = document.createElement('li');
        item.textContent = `${file.name} …`;
        list?.appendChild(item);
        const body = new FormData();
        body.append('file', file);
        try {
            const res = await fetch(url, { method: 'POST', body, credentials: 'same-origin' });
            const data = await res.json();
            item.textContent = data.success ? `${file.name} ✓` : `${file.name} ✗`;
            if (data.success) {
                window.setTimeout(() => window.location.reload(), 600);
            }
        } catch {
            item.textContent = `${file.name} ✗`;
        }
    };

    input?.addEventListener('change', () => {
        Array.from(input.files || []).forEach((file) => void uploadFile(file));
        input.value = '';
    });
}

// Silence unused root in builds without gallery
void root;
