/**
 * Page Transitions and Smooth Navigation
 * Handles page loading, transitions, and history management
 */

class PageTransitions {
  constructor() {
    this.transitionDuration = 300;
    this.isTransitioning = false;
    this.init();
  }

  init() {
    // Wait for body to exist
    if (!document.body) return;

    // Add transition wrapper if it doesn't exist
    if (!document.getElementById("page-transition")) {
      const wrapper = document.createElement("div");
      wrapper.id = "page-transition";
      wrapper.className = "page-transition";

      // Wrap main content
      const main = document.querySelector("main") || document.body;
      const parent = main.parentNode;
      parent.insertBefore(wrapper, main);
      wrapper.appendChild(main);
    }

    // Add fade-in on page load
    this.fadeIn();

    // Intercept navigation clicks
    this.setupLinkInterception();

    // Handle back/forward buttons
    window.addEventListener("popstate", (e) => {
      if (e.state && e.state.url) {
        this.navigate(e.state.url, false);
      }
    });

    // Add scroll restoration
    if ("scrollRestoration" in history) {
      history.scrollRestoration = "manual";
    }
  }

  fadeIn() {
    const wrapper = document.getElementById("page-transition");
    if (wrapper) {
      wrapper.classList.add("fade-in");
      setTimeout(() => {
        wrapper.classList.remove("fade-in");
      }, this.transitionDuration);
    }
  }

  fadeOut(callback) {
    const wrapper = document.getElementById("page-transition");
    if (wrapper) {
      wrapper.classList.add("fade-out");
      setTimeout(() => {
        if (callback) callback();
        wrapper.classList.remove("fade-out");
      }, this.transitionDuration);
    } else {
      if (callback) callback();
    }
  }

  setupLinkInterception() {
    document.addEventListener("click", (e) => {
      const link = e.target.closest("a");

      // Check if it's a valid internal link
      if (!link) return;
      if (link.hasAttribute("data-no-transition")) return;
      if (link.target === "_blank") return;
      if (link.hasAttribute("download")) return;

      const href = link.getAttribute("href");
      if (
        !href ||
        href.startsWith("#") ||
        href.startsWith("mailto:") ||
        href.startsWith("tel:")
      )
        return;

      // Check if it's an external link
      const url = new URL(href, window.location.origin);
      if (url.origin !== window.location.origin) return;

      // Intercept the navigation
      e.preventDefault();
      this.navigate(href, true);
    });
  }

  navigate(url, updateHistory = true) {
    if (this.isTransitioning) return;
    this.isTransitioning = true;

    this.fadeOut(() => {
      if (updateHistory) {
        history.pushState({ url }, "", url);
      }
      window.location.href = url;
    });
  }

  // Scroll to element with smooth animation
  scrollTo(selector, offset = 0) {
    const element = document.querySelector(selector);
    if (!element) return;

    const top =
      element.getBoundingClientRect().top + window.pageYOffset - offset;

    window.scrollTo({
      top,
      behavior: "smooth",
    });
  }

  // Scroll to top
  scrollToTop() {
    window.scrollTo({
      top: 0,
      behavior: "smooth",
    });
  }
}

/**
 * Lazy Loading Images
 * Improves performance by loading images only when they're visible
 */
class LazyLoader {
  constructor() {
    this.images = [];
    this.observer = null;
    this.init();
  }

  init() {
    // Find all lazy images
    this.images = document.querySelectorAll(
      'img[data-src], img[loading="lazy"]'
    );

    // Set up Intersection Observer
    if ("IntersectionObserver" in window) {
      this.observer = new IntersectionObserver(
        (entries) => {
          entries.forEach((entry) => {
            if (entry.isIntersecting) {
              this.loadImage(entry.target);
            }
          });
        },
        {
          rootMargin: "50px",
        }
      );

      this.images.forEach((img) => this.observer.observe(img));
    } else {
      // Fallback for older browsers
      this.images.forEach((img) => this.loadImage(img));
    }
  }

  loadImage(img) {
    const src = img.getAttribute("data-src");
    if (src) {
      img.src = src;
      img.removeAttribute("data-src");
    }

    // Add fade-in effect
    img.addEventListener("load", () => {
      img.classList.add("loaded");
    });

    if (this.observer) {
      this.observer.unobserve(img);
    }
  }

  // Add new images to observer
  observe(images) {
    if (!images) return;

    const imageList = Array.isArray(images) ? images : [images];
    imageList.forEach((img) => {
      if (this.observer) {
        this.observer.observe(img);
      } else {
        this.loadImage(img);
      }
    });
  }
}

/**
 * Smooth Scroll Handler
 * Adds smooth scrolling to anchor links
 */
class SmoothScroll {
  constructor() {
    this.init();
  }

  init() {
    document.querySelectorAll('a[href^="#"]').forEach((anchor) => {
      anchor.addEventListener("click", (e) => {
        const href = anchor.getAttribute("href");
        if (href === "#") return;

        e.preventDefault();
        const target = document.querySelector(href);

        if (target) {
          const offset = 80; // Account for fixed header
          const top =
            target.getBoundingClientRect().top + window.pageYOffset - offset;

          window.scrollTo({
            top,
            behavior: "smooth",
          });

          // Update URL without scrolling
          history.pushState(null, "", href);
        }
      });
    });
  }
}

/**
 * Back to Top Button
 * Shows/hides button based on scroll position
 */
class BackToTop {
  constructor() {
    this.button = null;
    this.scrollThreshold = 300;
    this.init();
  }

  init() {
    // Wait for body to exist
    if (!document.body) return;

    // Create button if it doesn't exist
    this.button = document.getElementById("back-to-top");
    if (!this.button) {
      this.button = document.createElement("button");
      this.button.id = "back-to-top";
      this.button.className = "back-to-top";
      this.button.innerHTML = "↑";
      this.button.setAttribute("aria-label", "Back to top");
      document.body.appendChild(this.button);
    }

    // Handle scroll
    window.addEventListener("scroll", () => {
      if (window.pageYOffset > this.scrollThreshold) {
        this.button.classList.add("visible");
      } else {
        this.button.classList.remove("visible");
      }
    });

    // Handle click
    this.button.addEventListener("click", () => {
      window.scrollTo({
        top: 0,
        behavior: "smooth",
      });
    });
  }
}

/**
 * Loading Overlay
 * Shows loading state during async operations
 */
class LoadingOverlay {
  constructor() {
    this.overlay = null;
    this.activeOperations = 0;
    this.init();
  }

  init() {
    // Wait for body to exist
    if (!document.body) return;

    // Create overlay if it doesn't exist
    this.overlay = document.getElementById("loading-overlay");
    if (!this.overlay) {
      this.overlay = document.createElement("div");
      this.overlay.id = "loading-overlay";
      this.overlay.className = "loading-overlay";
      this.overlay.innerHTML = `
        <div class="loading-spinner">
          <div class="spinner"></div>
          <p>Loading...</p>
        </div>
      `;
      document.body.appendChild(this.overlay);
    }
  }

  show() {
    this.activeOperations++;
    this.overlay.classList.add("active");
    document.body.style.overflow = "hidden";
  }

  hide() {
    this.activeOperations = Math.max(0, this.activeOperations - 1);

    if (this.activeOperations === 0) {
      this.overlay.classList.remove("active");
      document.body.style.overflow = "";
    }
  }

  // Force hide regardless of operation count
  forceHide() {
    this.activeOperations = 0;
    this.overlay.classList.remove("active");
    document.body.style.overflow = "";
  }
}

/**
 * Page Visibility Handler
 * Handles actions when page becomes visible/hidden
 */
class PageVisibility {
  constructor() {
    this.callbacks = {
      visible: [],
      hidden: [],
    };
    this.init();
  }

  init() {
    document.addEventListener("visibilitychange", () => {
      if (document.hidden) {
        this.callbacks.hidden.forEach((cb) => cb());
      } else {
        this.callbacks.visible.forEach((cb) => cb());
      }
    });
  }

  onVisible(callback) {
    this.callbacks.visible.push(callback);
  }

  onHidden(callback) {
    this.callbacks.hidden.push(callback);
  }
}

/**
 * Network Status Handler
 * Monitors online/offline status
 */
class NetworkStatus {
  constructor() {
    this.isOnline = navigator.onLine;
    this.callbacks = {
      online: [],
      offline: [],
    };
    this.init();
  }

  init() {
    window.addEventListener("online", () => {
      this.isOnline = true;
      this.callbacks.online.forEach((cb) => cb());
      this.showNotification("Back online", "success");
    });

    window.addEventListener("offline", () => {
      this.isOnline = false;
      this.callbacks.offline.forEach((cb) => cb());
      this.showNotification("No internet connection", "error");
    });
  }

  onOnline(callback) {
    this.callbacks.online.push(callback);
  }

  onOffline(callback) {
    this.callbacks.offline.push(callback);
  }

  showNotification(message, type) {
    if (window.Utils && window.Utils.notify) {
      window.Utils.notify(message, type);
    }
  }
}

// Initialize when DOM is ready
if (document.readyState === "loading") {
  document.addEventListener("DOMContentLoaded", initPageTransitions);
} else {
  initPageTransitions();
}

function initPageTransitions() {
  // Initialize all modules
  window.pageTransitions = new PageTransitions();
  window.lazyLoader = new LazyLoader();
  window.smoothScroll = new SmoothScroll();
  window.backToTop = new BackToTop();
  window.loadingOverlay = new LoadingOverlay();
  window.pageVisibility = new PageVisibility();
  window.networkStatus = new NetworkStatus();

  console.log("Page transitions initialized");
}

// Add CSS if not already present
if (!document.getElementById("page-transitions-styles")) {
  const style = document.createElement("style");
  style.id = "page-transitions-styles";
  style.textContent = `
    .page-transition {
      opacity: 1;
      transition: opacity 300ms ease;
    }

    .page-transition.fade-in {
      opacity: 0;
      animation: fadeIn 300ms ease forwards;
    }

    .page-transition.fade-out {
      opacity: 1;
      animation: fadeOut 300ms ease forwards;
    }

    @keyframes fadeIn {
      from { opacity: 0; }
      to { opacity: 1; }
    }

    @keyframes fadeOut {
      from { opacity: 1; }
      to { opacity: 0; }
    }

    img[data-src] {
      opacity: 0;
      transition: opacity 300ms ease;
    }

    img.loaded {
      opacity: 1;
    }

    .back-to-top {
      position: fixed;
      bottom: 20px;
      right: 20px;
      width: 50px;
      height: 50px;
      background: #667eea;
      color: white;
      border: none;
      border-radius: 50%;
      font-size: 24px;
      cursor: pointer;
      opacity: 0;
      visibility: hidden;
      transform: translateY(20px);
      transition: all 0.3s ease;
      z-index: 999;
      box-shadow: 0 4px 12px rgba(0,0,0,0.2);
    }

    .back-to-top.visible {
      opacity: 1;
      visibility: visible;
      transform: translateY(0);
    }

    .back-to-top:hover {
      background: #5568d3;
      transform: translateY(-2px);
    }

    .loading-overlay {
      position: fixed;
      top: 0;
      left: 0;
      width: 100%;
      height: 100%;
      background: rgba(255,255,255,0.95);
      display: flex;
      align-items: center;
      justify-content: center;
      opacity: 0;
      visibility: hidden;
      transition: all 0.3s ease;
      z-index: 9999;
    }

    .loading-overlay.active {
      opacity: 1;
      visibility: visible;
    }

    .loading-spinner {
      text-align: center;
    }

    .spinner {
      width: 60px;
      height: 60px;
      border: 4px solid #f3f3f3;
      border-top: 4px solid #667eea;
      border-radius: 50%;
      animation: spin 1s linear infinite;
      margin: 0 auto 16px;
    }

    @keyframes spin {
      0% { transform: rotate(0deg); }
      100% { transform: rotate(360deg); }
    }

    .loading-spinner p {
      color: #667eea;
      font-size: 16px;
      font-weight: 600;
      margin: 0;
    }
  `;
  document.head.appendChild(style);
}
