const MotionLib = window.Motion || window.framerMotion;
const { motion, AnimatePresence } = MotionLib || {};

if (!MotionLib || !motion || !AnimatePresence) {
  document.getElementById('root').innerHTML = '<div class="app-error">Motion library did not load. Check your connection and refresh.</div>';
  throw new Error('Framer Motion UMD bundle not available on window.Motion');
}

let directors = [];

let projects = [];

let heroClips = [];
const fade = { initial: { opacity: 0, y: 12 }, animate: { opacity: 1, y: 0 }, exit: { opacity: 0, y: -10 }, transition: { duration: 0.42, ease: [0.22, 1, 0.36, 1] } };

function Logo({ onClick, mobile=false }) {
  return <button className={mobile ? "mobile-logo" : "logo"} onClick={onClick} aria-label="Go to home"><img src="assets/logo.svg" alt="Chubby Films" /></button>;
}

function PinkMenuButton({ open, setOpen }) {
  return <motion.button className={`pink-menu ${open ? 'open' : ''}`} aria-label={open ? 'Close menu' : 'Open menu'} onClick={() => setOpen(!open)} whileTap={{ scale: .9 }}>
    <span />
  </motion.button>;
}

function Home({ setView, setSelectedProject, selectedDirector, setSelectedDirector }) {
  const [menuOpen, setMenuOpen] = React.useState(false);
  const [clip, setClip] = React.useState(0);
  const trackRef = React.useRef(null);
  const activeIndexRef = React.useRef(0);
  React.useEffect(() => { activeIndexRef.current = clip; }, [clip]);
  React.useEffect(() => {
    document.documentElement.classList.add('home-scroll');
    document.body.classList.add('home-scroll');
    return () => {
      document.documentElement.classList.remove('home-scroll');
      document.body.classList.remove('home-scroll');
      document.body.classList.remove('drawer-open');
    };
  }, []);
  React.useEffect(() => {
    document.body.classList.toggle('drawer-open', menuOpen);
  }, [menuOpen]);
  React.useEffect(() => {
    const gsap = window.gsap;
    const Observer = window.Observer;
    const track = trackRef.current;
    const desktop = window.matchMedia('(min-width: 901px)').matches;
    if (!desktop || !gsap || !Observer || !track) return;

    gsap.registerPlugin(Observer);
    const slides = Array.from(track.children);
    let animating = false;
    const clampIndex = (value) => Math.max(0, Math.min(slides.length - 1, value));
    const goTo = (index) => {
      const next = clampIndex(index);
      if (animating || next === activeIndexRef.current) return;
      animating = true;
      activeIndexRef.current = next;
      setClip(next);
      gsap.to(track, {
        x: -next * window.innerWidth,
        duration: 0.72,
        ease: 'power3.inOut',
        onComplete: () => { animating = false; }
      });
    };
    const observer = Observer.create({
      target: window,
      type: 'wheel,touch,pointer',
      preventDefault: true,
      tolerance: 14,
      onChangeY: (self) => {
        if (menuOpen) return;
        goTo(activeIndexRef.current + (self.deltaY > 0 ? 1 : -1));
      }
    });
    const handleResize = () => gsap.set(track, { x: -activeIndexRef.current * window.innerWidth });
    window.addEventListener('resize', handleResize);
    gsap.set(track, { x: 0 });

    return () => {
      observer.kill();
      window.removeEventListener('resize', handleResize);
      gsap.killTweensOf(track);
      gsap.set(track, { clearProps: 'transform' });
      window.scrollTo(0, 0);
    };
  }, [menuOpen]);
  const handleTrackScroll = () => {
    const track = trackRef.current;
    if (!track) return;
    const slides = Array.from(track.children);
    const nearest = slides.reduce((best, slide, i) => {
      const distance = Math.abs(slide.offsetLeft - track.scrollLeft);
      return distance < best.distance ? { i, distance } : best;
    }, { i: 0, distance: Infinity });
    if (nearest.i !== clip) setClip(nearest.i);
  };
  const scrollToClip = (i) => {
    setClip(i);
    activeIndexRef.current = i;
    const track = trackRef.current;
    const slide = track?.children?.[i];
    if (!track || !slide) return;
    if (window.matchMedia('(min-width: 901px)').matches && window.gsap) {
      window.gsap.to(track, { x: -i * window.innerWidth, duration: 0.72, ease: 'power3.inOut' });
      return;
    }
    track.scrollTo({ left: slide.offsetLeft, behavior: 'smooth' });
  };
  const current = heroClips[clip % heroClips.length];
  return <main className="cinematic-home">
    <AnimatePresence mode="wait">
      <motion.img key={current.img} className="cinematic-media" src={current.img} alt={`${current.brand} ${current.project}`} initial={{ opacity: 0, scale: 1.05 }} animate={{ opacity: 1, scale: 1 }} exit={{ opacity: 0, scale: 1.015 }} transition={{ duration: .7, ease: [0.22,1,0.36,1] }}/>
    </AnimatePresence>
    <div className="home-shade" />
    <Logo onClick={() => { setView('home'); setMenuOpen(false); }} />
    <div className="home-tagline">Creative Production Company</div>
    <PinkMenuButton open={menuOpen} setOpen={setMenuOpen} />
    <div className="home-caption"><span>{current.brand}</span><small>{current.project}</small></div>
    <section className="home-carousel fullscreen-horizontal" aria-label="Featured films fullscreen horizontal slides">
      <div className="home-track" ref={trackRef} onScroll={handleTrackScroll}>
        {heroClips.map((p,i) => <motion.button key={p.page || p.title} className={`home-slide ${clip===i?'active':''}`} onClick={() => scrollToClip(i)}>
          <img src={p.img} alt={`${p.brand} ${p.project}`} loading="lazy" />
          <span>{p.brand}</span>
        </motion.button>)}
      </div>
      <div className="home-dots">{heroClips.map((_,i)=><button key={i} className={clip===i?'active':''} onClick={() => scrollToClip(i)} aria-label={`Go to clip ${i+1}`} />)}</div>
      {clip >= 2 && <motion.button className="go-projects" onClick={() => setView('projects')} initial={{opacity:0,y:10}} animate={{opacity:1,y:0}}>Go to Projects</motion.button>}
    </section>
    <MenuDrawer open={menuOpen} setOpen={setMenuOpen} setView={setView} selectedDirector={selectedDirector} setSelectedDirector={setSelectedDirector} setSelectedProject={setSelectedProject} />
  </main>;
}

function MenuDrawer({ open, setOpen, setView, selectedDirector, setSelectedDirector, setSelectedProject }) {
  const [active, setActive] = React.useState(0);
  const [panel, setPanel] = React.useState('about');
  const current = directors[active];
  const go = (view) => { setView(view); setOpen(false); };
  return <AnimatePresence>
    {open && <motion.aside className="menu-drawer" initial={{ x: '-100%' }} animate={{ x: 0 }} exit={{ x: '-100%' }} transition={{ duration: .55, ease: [0.22,1,0.36,1] }}>
      <div className="drawer-left">
        <div className="drawer-nav"><button className="active">Directors</button><span>/</span><button onClick={() => go('projects')}>Projects</button></div>
        <div className="drawer-subnav"><button>Branded Content</button><button>Music Videos</button><button>Editorial</button></div>
        <nav className="drawer-directors">
          {directors.map((d,i)=><motion.button key={d.name} className={active===i?'active':''} onMouseEnter={() => setActive(i)} onFocus={() => setActive(i)} onClick={() => { setSelectedDirector(d); go('director'); }} whileHover={{ x: 10 }}>{d.name}</motion.button>)}
        </nav>
        <div className="drawer-actions"><button className={panel==='about'?'active':''} onClick={() => setPanel('about')}>ABOUT</button><button className={panel==='contact'?'active':''} onClick={() => setPanel('contact')}>CONTACT</button></div>
        <AnimatePresence mode="wait">
          {panel==='about' && <motion.div className="drawer-panel" key="about" {...fade}>We are a creative production company based in London UK and Milan IT.<br/><br/>We tell stories through original content with a strong narrative approach.</motion.div>}
          {panel==='contact' && <motion.div className="drawer-panel contact" key="contact" {...fade}><p><strong>Pierpaolo Di Stefano</strong><br/>Partner / Executive Producer<br/><a href="mailto:pierpaolo@chubbyfilms.com">pierpaolo@chubbyfilms.com</a></p><p><strong>Chiara Broggi</strong><br/>Partner / Creative Director<br/><a href="mailto:chiara@chubbyfilms.com">chiara@chubbyfilms.com</a></p><p><strong>General Inquiries</strong><br/><a href="mailto:info@chubbyfilms.com">info@chubbyfilms.com</a></p><p><strong>Work with us</strong><br/><a href="mailto:jobs@chubbyfilms.com">jobs@chubbyfilms.com</a></p></motion.div>}
        </AnimatePresence>
      </div>
      <div className="drawer-preview"><AnimatePresence mode="wait"><motion.img key={current.img} src={current.img} alt={current.name} initial={{opacity:0}} animate={{opacity:1}} exit={{opacity:0}} /></AnimatePresence><div className="drawer-caption"><span>{current.caption[0]}</span><small>{current.caption[1]}</small></div></div>
    </motion.aside>}
  </AnimatePresence>;
}

function Projects({ setView, setSelectedProject }) {
  return <motion.main className="projects-page project-catalog" {...fade}>
    <PageTop setView={setView} current="projects" backLabel="← Home" backTo="home" />
    <div className="bar"><h1>Projects</h1><div className="filters"><button className="active">All</button><button>Branded Content</button><button>Music Videos</button><button>Editorial</button></div></div>
    <section className="grid" aria-label="Projects grid">
      {projects.map((p,i)=><motion.button className="card" type="button" key={`${p.brand}-${i}`} onClick={() => { setSelectedProject({...p,index:i}); setView('detail'); }} whileHover={{ y: -8 }}><div className="thumb"><img src={p.img} alt={`${p.brand} ${p.project}`} loading="lazy" /></div><div className="card-label">{p.brand}<small>{p.project}</small></div></motion.button>)}
    </section>
    <SiteFooter />
  </motion.main>;
}

function PageTop({ setView, current, backLabel='← Back', backTo='home' }) {
  return <div className="page-controls"><button className="back" onClick={() => setView(backTo)}>{backLabel}</button><div className="section-nav"><button className={current==='directors'?'active':''} onClick={() => setView('home')}>Directors</button><span>/</span><button className={current==='projects'?'active':''} onClick={() => setView('projects')}>Projects</button></div></div>;
}

function Director({ selectedDirector, setView, setSelectedProject }) {
  const [bio, setBio] = React.useState(false);
  const directorProjects = projects.filter(p => p.director === selectedDirector.name);
  const visible = directorProjects.length ? directorProjects : projects.slice(0, 3);
  return <motion.main className="director-page" {...fade}>
    <PageTop setView={setView} current="directors" backLabel="← Home" backTo="home" />
    <div className="director-head"><div><div className="breadcrumb">DIRECTORS / {selectedDirector.name.toUpperCase()}</div><h1 className="director-title">{selectedDirector.name}</h1></div><button className="bio-toggle" onClick={() => setBio(!bio)}>{bio?'CLOSE BIO -':'READ BIO +'}</button></div>
    <AnimatePresence>{bio && <motion.p className="bio" {...fade}>{selectedDirector.bio}</motion.p>}</AnimatePresence>
    {visible[0] && <button className="featured-project" onClick={() => { setSelectedProject({...visible[0], index: projects.indexOf(visible[0])}); setView('detail'); }}><img src={visible[0].img} /><span>{visible[0].brand}</span><small>{visible[0].project}</small></button>}
    <section className="grid director-grid">{visible.slice(1).map((p,i)=><motion.button className="card" key={i} onClick={() => { setSelectedProject({...p,index:projects.indexOf(p)}); setView('detail'); }}><div className="thumb"><img src={p.img} /></div><div className="card-label">{p.brand}<small>{p.project}</small></div></motion.button>)}</section>
  </motion.main>;
}

function vimeoId(v) {
  if (!v) return null;
  const s = String(v).trim();
  const m = s.match(/(?:vimeo\.com\/(?:video\/)?)?(\d{6,})/);
  return m ? m[1] : null;
}

function VimeoMedia({ project }) {
  const id = vimeoId(project.vimeo);
  const alt = `${project.brand} ${project.project}`;
  // Show the video when a Vimeo is linked, unless the editor forced "image".
  const useVideo = id && project.display !== 'image';
  if (!useVideo) return <img src={project.img} alt={alt} />;
  return <iframe className="vimeo-frame" src={`https://player.vimeo.com/video/${id}?title=0&byline=0&portrait=0`} title={alt} allow="autoplay; fullscreen; picture-in-picture" allowFullScreen />;
}

function Detail({ setView, selectedProject, setSelectedProject }) {
  const index = selectedProject?.index ?? Math.max(0, projects.findIndex(p => p.brand === selectedProject?.brand && p.project === selectedProject?.project));
  const project = projects[index] || projects[0];
  const move = (delta) => { const ni=(index+delta+projects.length)%projects.length; setSelectedProject({...projects[ni], index:ni}); };
  return <motion.main className="detail-page" {...fade}>
    <PageTop setView={setView} current="projects" backLabel="← Back to projects" backTo="projects" />
    <button className="project-arrow prev" onClick={() => move(-1)}>‹</button><button className="project-arrow next" onClick={() => move(1)}>›</button>
    <section className="detail-hero"><div><div className="breadcrumb">PROJECTS / {project.brand}</div><h1 className="detail-title">{project.brand}<br/><span>{project.project}</span></h1><div className="credits">CREDITS<br/>Creative direction and production by Chubby Films</div></div><motion.div className="detail-media" initial={{clipPath:'inset(0 0 100% 0)'}} animate={{clipPath:'inset(0 0 0% 0)'}} transition={{duration:.8,ease:[.22,1,.36,1]}}><VimeoMedia project={project} /></motion.div></section>
  </motion.main>;
}

function SiteFooter(){return <footer className="site-footer"><div>Creative production company<br/>based in London UK and Milan IT.</div><div>ITA<br/>Chubby Films SRL<br/>Viale Argonne 40<br/>20133 - Milano, IT</div><div>UK<br/>Chubby Films LTD<br/>7 Ifield Road<br/>SW10 9AZ - London, UK</div><div>General Inquiries<br/><a href="mailto:info@chubbyfilms.com">info@chubbyfilms.com</a><br/><br/>Work with us<br/><a href="mailto:jobs@chubbyfilms.com">jobs@chubbyfilms.com</a></div><div className="copyright">© 2026 CHUBBY FILMS. ALL RIGHTS RESERVED. PRIVACY POLICY - COOKIES POLICY</div></footer>}

function App(){
  const [view,setView]=React.useState('home');
  const [selectedDirector,setSelectedDirector]=React.useState(directors[0]);
  const [selectedProject,setSelectedProject]=React.useState({...projects[0], index:0});
  React.useEffect(() => { const goHome=()=>setView('home'); window.addEventListener('go-home',goHome); return()=>window.removeEventListener('go-home',goHome); }, []);
  return <div className="app"><AnimatePresence mode="wait">
    {view==='home' && <Home key="home" setView={setView} selectedDirector={selectedDirector} setSelectedDirector={setSelectedDirector} setSelectedProject={setSelectedProject} />}
    {view==='projects' && <Projects key="projects" setView={setView} setSelectedProject={setSelectedProject} />}
    {view==='director' && <Director key="director" selectedDirector={selectedDirector} setView={setView} setSelectedProject={setSelectedProject} />}
    {view==='detail' && <Detail key="detail" setView={setView} selectedProject={selectedProject} setSelectedProject={setSelectedProject} />}
  </AnimatePresence><div className="noise" /></div>;
}

Promise.all([
  fetch('content/directors.json').then(r => { if (!r.ok) throw new Error('directors'); return r.json(); }),
  fetch('content/projects.json').then(r => { if (!r.ok) throw new Error('projects'); return r.json(); })
]).then(([d, p]) => {
  directors = d.directors || [];
  projects = p.projects || [];
  const featured = projects.filter(x => x.featured).sort((a, b) => a.featured - b.featured);
  heroClips = featured.length ? featured : projects.slice(0, 3);
  ReactDOM.createRoot(document.getElementById('root')).render(<App/>);
}).catch(() => {
  document.getElementById('root').innerHTML = '<div class="app-error">Failed to load site content. Refresh to try again.</div>';
});
