(function() {
  'use strict';

  // Internal state
  let currentPhotoIndex = 0;
  let photosData = [];
  let isOpen = false;
  let exifData = {};
  let options = {
    swipeEnabled: true,
    keyboardEnabled: true,
    extractEXIF: true,
    onOpen: null,
    onClose: null,
  };

  // Lightbox DOM elements (created on first init)
  let lightboxModal = null;
  let lightboxImage = null;
  let lightboxCaption = null;
  let lightboxSidebar = null;

  /**
   * Initialize lightbox for a photo collection
   * @param {string} containerSelector - CSS selector for photo container
   * @param {Array} photos - Array of photo objects: {src, alt, caption, location}
   * @param {Object} opts - Options: {swipeEnabled, keyboardEnabled, extractEXIF, onOpen, onClose}
   * @returns {Object} - {openLightbox, closeLightbox}
   */
  function initLightbox(containerSelector, photos, opts = {}) {
    photosData = photos;
    options = { ...options, ...opts };

    // Merge options with defaults
    const container = document.querySelector(containerSelector);
    if (!container) {
      console.error('Photo container not found:', containerSelector);
      return { openLightbox: () => {}, closeLightbox: () => {} };
    }

    // Attach click listeners to all figures in the container
    const figures = container.querySelectorAll('figure[data-photo-index]');
    figures.forEach((figure) => {
      figure.addEventListener('click', () => {
        const index = parseInt(figure.dataset.photoIndex, 10);
        openLightbox(index);
      });
    });

    // Return public API
    return {
      openLightbox,
      closeLightbox,
    };
  }

  /**
   * Open lightbox to a specific photo
   * @param {number} photoIndex - 0-based index into photosData array
   */
  function openLightbox(photoIndex) {
    if (photoIndex < 0 || photoIndex >= photosData.length) {
      console.warn('Invalid photo index:', photoIndex);
      return;
    }

    currentPhotoIndex = photoIndex;
    isOpen = true;

    // Create lightbox DOM if it doesn't exist
    if (!lightboxModal) {
      createLightboxDOM();
    }

    // Populate lightbox with current photo
    updateLightboxContent();

    // Show modal
    lightboxModal.classList.add('visible');
    document.body.style.overflow = 'hidden';

    // Extract EXIF if enabled
    if (options.extractEXIF) {
      extractEXIFForCurrentPhoto();
    }

    // Attach event listeners
    attachEventListeners();

    // Callback
    if (options.onOpen) {
      options.onOpen(photoIndex);
    }
  }

  /**
   * Close lightbox
   */
  function closeLightbox() {
    if (!isOpen || !lightboxModal) return;

    isOpen = false;
    lightboxModal.classList.remove('visible');
    document.body.style.overflow = '';

    // Detach event listeners
    detachEventListeners();

    // Callback
    if (options.onClose) {
      options.onClose();
    }
  }

  /**
   * Create lightbox HTML structure and inject into DOM
   */
  function createLightboxDOM() {
    lightboxModal = document.createElement('div');
    lightboxModal.className = 'photo-lightbox';

    lightboxModal.innerHTML = `
      <div class="photo-lightbox-backdrop"></div>
      <div class="photo-lightbox-container">
        <button class="photo-lightbox-close" aria-label="Close lightbox">×</button>

        <button class="photo-lightbox-prev" aria-label="Previous photo">←</button>

        <div class="photo-lightbox-content">
          <img class="photo-lightbox-image" src="" alt="">
          <div class="photo-lightbox-caption"></div>
        </div>

        <button class="photo-lightbox-next" aria-label="Next photo">→</button>

        <div class="photo-lightbox-sidebar">
          <div class="photo-lightbox-sidebar-content"></div>
        </div>
      </div>
    `;

    document.body.appendChild(lightboxModal);

    // Cache element references
    lightboxImage = lightboxModal.querySelector('.photo-lightbox-image');
    lightboxCaption = lightboxModal.querySelector('.photo-lightbox-caption');
    lightboxSidebar = lightboxModal.querySelector('.photo-lightbox-sidebar-content');

    // Attach close button and backdrop click
    lightboxModal.querySelector('.photo-lightbox-close').addEventListener('click', closeLightbox);
    lightboxModal.querySelector('.photo-lightbox-backdrop').addEventListener('click', closeLightbox);

    // Attach navigation buttons
    lightboxModal.querySelector('.photo-lightbox-prev').addEventListener('click', () => navigate(-1));
    lightboxModal.querySelector('.photo-lightbox-next').addEventListener('click', () => navigate(1));
  }

  /**
   * Update lightbox content with current photo
   */
  function updateLightboxContent() {
    const photo = photosData[currentPhotoIndex];
    if (!photo) return;

    lightboxImage.src = photo.src;
    lightboxImage.alt = photo.alt || '';

    // Caption
    if (photo.caption) {
      lightboxCaption.textContent = photo.caption;
      lightboxCaption.style.display = 'block';
    } else {
      lightboxCaption.style.display = 'none';
    }

    // Update prev/next button states
    const prevBtn = lightboxModal.querySelector('.photo-lightbox-prev');
    const nextBtn = lightboxModal.querySelector('.photo-lightbox-next');
    prevBtn.disabled = currentPhotoIndex === 0;
    nextBtn.disabled = currentPhotoIndex === photosData.length - 1;
  }

  /**
   * Navigate to previous or next photo
   * @param {number} direction - -1 for prev, 1 for next
   */
  function navigate(direction) {
    const newIndex = currentPhotoIndex + direction;
    if (newIndex >= 0 && newIndex < photosData.length) {
      currentPhotoIndex = newIndex;
      updateLightboxContent();

      // Reset EXIF data and re-extract if enabled
      exifData = {};
      if (options.extractEXIF) {
        extractEXIFForCurrentPhoto();
      }
    }
  }

  /**
   * Extract EXIF data from current photo image element
   */
  function extractEXIFForCurrentPhoto() {
    extractEXIF(lightboxImage).then((data) => {
      exifData = data;
      updateSidebarContent();
    });
  }

  /**
   * Update sidebar with EXIF and location data
   */
  function updateSidebarContent() {
    const photo = photosData[currentPhotoIndex];
    let sidebarHTML = '';

    // Always show location if provided
    if (photo.location) {
      sidebarHTML += `
        <div class="photo-metadata-field">
          <div class="photo-metadata-label">Location</div>
          <div class="photo-metadata-value">${photo.location}</div>
        </div>
      `;
    }

    // Show EXIF fields if available
    if (Object.keys(exifData).length > 0) {
      sidebarHTML += `
        <div class="photo-metadata-divider"></div>
        <div class="photo-metadata-label">Camera</div>
      `;

      if (exifData.camera) {
        sidebarHTML += `
          <div class="photo-metadata-value">${exifData.camera}</div>
        `;
      }
      if (exifData.lens) {
        sidebarHTML += `
          <div class="photo-metadata-field">
            <div class="photo-metadata-label">Lens</div>
            <div class="photo-metadata-value">${exifData.lens}</div>
          </div>
        `;
      }
      if (exifData.focalLength) {
        sidebarHTML += `
          <div class="photo-metadata-field">
            <div class="photo-metadata-label">Focal Length</div>
            <div class="photo-metadata-value">${exifData.focalLength}</div>
          </div>
        `;
      }
      if (exifData.aperture) {
        sidebarHTML += `
          <div class="photo-metadata-field">
            <div class="photo-metadata-label">Aperture</div>
            <div class="photo-metadata-value">${exifData.aperture}</div>
          </div>
        `;
      }
      if (exifData.shutterSpeed) {
        sidebarHTML += `
          <div class="photo-metadata-field">
            <div class="photo-metadata-label">Shutter Speed</div>
            <div class="photo-metadata-value">${exifData.shutterSpeed}</div>
          </div>
        `;
      }
      if (exifData.iso) {
        sidebarHTML += `
          <div class="photo-metadata-field">
            <div class="photo-metadata-label">ISO</div>
            <div class="photo-metadata-value">${exifData.iso}</div>
          </div>
        `;
      }
      if (exifData.dateTaken) {
        sidebarHTML += `
          <div class="photo-metadata-field">
            <div class="photo-metadata-label">Date Taken</div>
            <div class="photo-metadata-value">${exifData.dateTaken}</div>
          </div>
        `;
      }
    }

    // Show or hide sidebar based on whether there's content
    const sidebarContainer = lightboxModal.querySelector('.photo-lightbox-sidebar');
    if (sidebarHTML) {
      lightboxSidebar.innerHTML = sidebarHTML;
      sidebarContainer.classList.add('visible');
    } else {
      sidebarContainer.classList.remove('visible');
    }
  }

  /**
   * Extract EXIF data from an image element using exif-js library
   * @param {HTMLImageElement} imageElement - Image to read EXIF from
   * @returns {Promise} - Resolves to {camera, lens, iso, aperture, shutterSpeed, focalLength, dateTaken}
   */
  function extractEXIF(imageElement) {
    return new Promise((resolve) => {
      // If exif-js is not loaded, return empty object
      if (typeof EXIF === 'undefined') {
        console.warn('exif-js library not loaded');
        resolve({});
        return;
      }

      EXIF.getData(imageElement, function() {
        const data = {
          camera: EXIF.getTag(this, 'Model'),
          lens: EXIF.getTag(this, 'LensModel'),
          iso: EXIF.getTag(this, 'ISOSpeedRatings'),
          aperture: formatAperture(EXIF.getTag(this, 'FNumber')),
          shutterSpeed: formatShutterSpeed(EXIF.getTag(this, 'ExposureTime')),
          focalLength: formatFocalLength(EXIF.getTag(this, 'FocalLength')),
          dateTaken: EXIF.getTag(this, 'DateTime'),
        };

        // Filter out undefined values
        Object.keys(data).forEach(key => {
          if (data[key] === undefined) {
            delete data[key];
          }
        });

        resolve(data);
      });
    });
  }

  /**
   * Format aperture value (f-number)
   */
  function formatAperture(value) {
    if (!value) return null;
    if (typeof value === 'object' && value.numerator !== undefined) {
      return `f/${(value.numerator / value.denominator).toFixed(1)}`;
    }
    return `f/${value}`;
  }

  /**
   * Format shutter speed (exposure time)
   */
  function formatShutterSpeed(value) {
    if (!value) return null;
    if (typeof value === 'object' && value.numerator !== undefined) {
      const speed = value.numerator / value.denominator;
      if (speed >= 1) {
        return `${speed.toFixed(1)}s`;
      }
      return `1/${Math.round(1 / speed)}`;
    }
    return value;
  }

  /**
   * Format focal length
   */
  function formatFocalLength(value) {
    if (!value) return null;
    if (typeof value === 'object' && value.numerator !== undefined) {
      return `${(value.numerator / value.denominator).toFixed(0)}mm`;
    }
    return `${value}mm`;
  }

  /**
   * Attach event listeners (swipe, keyboard, etc.)
   */
  function attachEventListeners() {
    if (options.swipeEnabled) {
      attachSwipeListeners();
    }
    if (options.keyboardEnabled) {
      attachKeyboardListeners();
    }
  }

  /**
   * Detach event listeners to prevent memory leaks
   */
  function detachEventListeners() {
    if (options.swipeEnabled) {
      detachSwipeListeners();
    }
    if (options.keyboardEnabled) {
      detachKeyboardListeners();
    }
  }

  /**
   * Touch swipe event listeners
   */
  let swipeStartX = 0;
  let swipeStartY = 0;

  function onTouchStart(e) {
    swipeStartX = e.touches[0].clientX;
    swipeStartY = e.touches[0].clientY;
  }

  function onTouchEnd(e) {
    const swipeEndX = e.changedTouches[0].clientX;
    const swipeEndY = e.changedTouches[0].clientY;
    const diffX = swipeEndX - swipeStartX;
    const diffY = swipeEndY - swipeStartY;

    // Only consider horizontal swipe if delta-x > delta-y
    if (Math.abs(diffX) > Math.abs(diffY) && Math.abs(diffX) > 50) {
      if (diffX > 0) {
        // Swiped right: go to previous
        navigate(-1);
      } else {
        // Swiped left: go to next
        navigate(1);
      }
    }
  }

  function attachSwipeListeners() {
    lightboxModal.addEventListener('touchstart', onTouchStart, false);
    lightboxModal.addEventListener('touchend', onTouchEnd, false);
  }

  function detachSwipeListeners() {
    lightboxModal.removeEventListener('touchstart', onTouchStart, false);
    lightboxModal.removeEventListener('touchend', onTouchEnd, false);
  }

  /**
   * Keyboard event listeners
   */
  function onKeyDown(e) {
    if (!isOpen) return;

    switch (e.key) {
      case 'ArrowLeft':
        navigate(-1);
        e.preventDefault();
        break;
      case 'ArrowRight':
        navigate(1);
        e.preventDefault();
        break;
      case 'Escape':
        closeLightbox();
        e.preventDefault();
        break;
      default:
        break;
    }
  }

  function attachKeyboardListeners() {
    document.addEventListener('keydown', onKeyDown);
  }

  function detachKeyboardListeners() {
    document.removeEventListener('keydown', onKeyDown);
  }

  // Expose public API
  window.PhotoUtils = {
    initLightbox,
    extractEXIF,
    openLightbox,
    closeLightbox,
  };
})();
