---
import type { ImageMetadata } from 'astro';
import { ClientRouter } from 'astro:transitions';
import BaseHead from '../components/BaseHead.astro';
import Footer from '../components/Footer.astro';
import GridOverlay from '../components/GridOverlay.astro';
import Navigation from '../components/Navigation.astro';
import CustomCursor from '../components/CustomCursor';
import ContextMenu from '../components/ContextMenu.astro';
import ThemePreferenceDialog from '../components/ThemePreferenceDialog.astro';
import { SITE_TITLE, SITE_DESCRIPTION, SOCIAL_LINKS } from '../consts';

interface Props {
  title?: string;
  description?: string;
  usePadding?: boolean;
  image?: ImageMetadata;
  type?: 'website' | 'article';
  publishedTime?: Date;
  modifiedTime?: Date;
}

const {
  title = SITE_TITLE,
  description = SITE_DESCRIPTION,
  usePadding = true,
  image,
  type = 'website',
  publishedTime,
  modifiedTime,
} = Astro.props;

// Master Person schema - establishes canonical identity across all pages
const personSchema = {
  "@context": "https://schema.org",
  "@type": "Person",
  "@id": `${SOCIAL_LINKS.website}/#person`,
  "name": "Nicholai Vogel",
  "url": SOCIAL_LINKS.website,
  "email": SOCIAL_LINKS.email,
  "jobTitle": "VFX Supervisor & Technical Artist",
  "description": "VFX Supervisor specializing in both 2D and 3D VFX, AI and high-end technical visualization.",
  "knowsAbout": [
    "Houdini",
    "Nuke",
    "ComfyUI",
    "Python",
    "VFX Pipeline",
    "Real-time VFX",
    "Motion Graphics",
    "Technical Art"
  ],
  "sameAs": [
    SOCIAL_LINKS.linkedin,
    "https://www.instagram.com/nicholai.exe"
  ],
  "affiliation": {
    "@type": "Organization",
    "name": "Biohazard VFX",
    "url": "https://biohazardvfx.com",
    "founder": {
      "@id": `${SOCIAL_LINKS.website}/#person`
    }
  }
};
---

<!DOCTYPE html>
<html lang="en" class="scroll-smooth" data-theme="dark">
  <head>
    <ClientRouter />
    <!-- Theme initialization script - runs before page render to prevent flash -->
    <script is:inline>
      function applyTheme() {
        // Apply theme
        const storedLocal = localStorage.getItem('theme');
        const storedSession = sessionStorage.getItem('theme');
        const theme =
          (storedLocal === 'light' || storedLocal === 'dark') ? storedLocal :
          (storedSession === 'light' || storedSession === 'dark') ? storedSession :
          'dark'; // Default fallback
        document.documentElement.setAttribute('data-theme', theme);

        // Apply saved accent color
        const savedColor = localStorage.getItem('accent-color');
        if (savedColor) {
          document.documentElement.style.setProperty('--color-brand-accent', savedColor);
        }
      }

      // Run immediately
      applyTheme();

      // Re-run on view transition
      document.addEventListener('astro:after-swap', applyTheme);
    </script>
    <BaseHead
      title={title}
      description={description}
      image={image}
      type={type}
      publishedTime={publishedTime}
      modifiedTime={modifiedTime}
    />

    <!-- Master Person Schema - Canonical Identity -->
    <script type="application/ld+json" set:html={JSON.stringify(personSchema)} />

    <slot name="head" />
  </head>
  
  <body class="antialiased selection:bg-brand-accent selection:text-brand-dark">
    <!-- First-visit theme preference dialog -->
    <ThemePreferenceDialog />

    <!-- Only hydrate custom cursor on devices that can actually benefit from it -->
    <CustomCursor client:media="(pointer: fine) and (hover: hover)" />
    <GridOverlay />
    <Navigation />

    <main class:list={["relative z-10 min-h-screen pb-24 lg:pl-24", { "pt-32 lg:pt-12": usePadding }]}>
      <slot />
    </main>

    <Footer />

    <!-- Custom context menu -->
    <ContextMenu />

    <script>
      // ===== SCROLL ANIMATION SYSTEM =====
      // If you're using Astro view transitions, elements can change between navigations.
      // We'll (re)bind observers on initial load and on `astro:page-load`.

      // Observer for scroll-triggered animations
      const scrollObserverOptions = {
        threshold: 0.15,
        rootMargin: "0px 0px -50px 0px"
      };

      const scrollObserver = new IntersectionObserver((entries) => {
        entries.forEach(entry => {
          if (entry.isIntersecting) {
            entry.target.classList.add('is-visible');
            // Optionally unobserve after animation
            // scrollObserver.unobserve(entry.target);
          }
        });
      }, scrollObserverOptions);

      // Observer for legacy reveal-text animations
      const revealObserverOptions = {
        threshold: 0.1,
        rootMargin: "0px"
      };

      const revealObserver = new IntersectionObserver((entries) => {
        entries.forEach(entry => {
          if (entry.isIntersecting) {
            entry.target.classList.add('active');
          }
        });
      }, revealObserverOptions);

      function bindScrollAnimations() {
        // Observe animate-on-scroll elements (avoid re-observing elements already visible)
        document.querySelectorAll('.animate-on-scroll:not(.is-visible)').forEach(el => {
          scrollObserver.observe(el);
        });

        // Observe reveal-text elements
        document.querySelectorAll('.reveal-text:not(.active)').forEach(el => {
          revealObserver.observe(el);
        });

        // Auto-stagger children in containers with .stagger-children class
        document.querySelectorAll('.stagger-children').forEach(container => {
          const children = container.querySelectorAll('.animate-on-scroll');
          children.forEach((child, index) => {
            child.classList.add(`stagger-${Math.min(index + 1, 8)}`);
          });
        });
      }

      // Initial bind
      bindScrollAnimations();

      // Re-bind on Astro page transitions (if enabled)
      document.addEventListener('astro:page-load', bindScrollAnimations);
    </script>
  </body>
</html>
