/* =========== Shared components =========== */
const { useState, useEffect, useRef, useCallback, useMemo } = React;

/* ------- Cursor ------- */
function useCursor(){
  useEffect(()=>{
    const ring = document.getElementById('cursorRing');
    if(!ring) return;
    let rx=0,ry=0,tx=0,ty=0;
    const onMove = (e)=>{
      tx = e.clientX; ty = e.clientY;
      const el = e.target.closest?.('[data-cursor]');
      if(el){
        const kind = el.getAttribute('data-cursor');
        ring.classList.add('hover');
        if(kind === 'view') ring.classList.add('view'); else ring.classList.remove('view');
      } else {
        ring.classList.remove('hover');
        ring.classList.remove('view');
      }
    };
    const tick = ()=>{
      rx += (tx-rx)*.18; ry += (ty-ry)*.18;
      ring.style.transform = `translate(${rx}px, ${ry}px) translate(-50%,-50%)`;
      requestAnimationFrame(tick);
    };
    window.addEventListener('mousemove', onMove);
    tick();
    return ()=>window.removeEventListener('mousemove', onMove);
  },[]);
}

/* ------- i18n: taalkeuze (NL default / EN) ------- */
let WV_LANG = (()=>{ try { return localStorage.getItem('wv-lang') || 'nl'; } catch(e){ return 'nl'; } })();
window.WV_LANG = WV_LANG;
try { document.documentElement.lang = WV_LANG; } catch(e){}
function setLang(l){
  WV_LANG = l;
  window.WV_LANG = l;
  try { localStorage.setItem('wv-lang', l); } catch(e){}
  try { document.documentElement.lang = l; } catch(e){}
  window.dispatchEvent(new Event('wv-lang'));
}
function useLang(){
  const [,force] = useState(0);
  useEffect(()=>{
    const h = ()=> force(x=>x+1);
    window.addEventListener('wv-lang', h);
    return ()=> window.removeEventListener('wv-lang', h);
  }, []);
  return WV_LANG;
}
function useT(){ useLang(); return (nl, en)=> (WV_LANG==='en' ? (en==null?nl:en) : nl); }
// global helper for non-component code (e.g. data.js): tg('nl','en')
function tg(nl, en){ return WV_LANG==='en' ? (en==null?nl:en) : nl; }
Object.assign(window, { setLang, useLang, useT, tg });

/* ------- History router (clean crawlable URLs) ------- */
const SITE_ORIGIN = 'https://www.weddingvisions.be';

function pathFromLocation(){
  // Migrate legacy hash URLs (?/#/foo) to clean paths
  if(location.hash && location.hash.startsWith('#/')){
    const path = location.hash.slice(1);
    history.replaceState({}, '', path);
    return path || '/';
  }
  return location.pathname || '/';
}

function useRoute(){
  const [route, setRoute] = useState(pathFromLocation);
  useEffect(()=>{
    const onChange = ()=> setRoute(pathFromLocation());
    window.addEventListener('popstate', onChange);
    window.addEventListener('wv-route', onChange);
    return ()=>{
      window.removeEventListener('popstate', onChange);
      window.removeEventListener('wv-route', onChange);
    };
  },[]);
  return route;
}

function navigate(to){
  const current = pathFromLocation();
  if(current === to){
    window.scrollTo({top:0, behavior:'smooth'});
    return;
  }
  const curtain = document.getElementById('curtain');
  const scrollTop = ()=>{
    const prev = document.documentElement.style.scrollBehavior;
    document.documentElement.style.scrollBehavior = 'auto';
    window.scrollTo(0,0);
    document.documentElement.scrollTop = 0;
    document.body.scrollTop = 0;
    document.documentElement.style.scrollBehavior = prev;
  };
  const go = ()=>{
    history.pushState({}, '', to);
    window.dispatchEvent(new Event('wv-route'));
    scrollTop();
  };
  if(!curtain){ go(); return; }
  curtain.classList.remove('out');
  curtain.classList.add('in');
  setTimeout(()=>{
    go();
    requestAnimationFrame(()=>{
      requestAnimationFrame(()=>{
        curtain.classList.remove('in');
        curtain.classList.add('out');
        setTimeout(()=> curtain.classList.remove('out'), 500);
      });
    });
  }, 450);
}

// Navigeer naar een dienst: scroll naar een sectie op /diensten (met optionele tab),
// of open een aparte pagina (to). Werkt vanaf eender welke pagina.
function goToDienst(item){
  if(item.to){ navigate(item.to); return; }
  if(pathFromLocation() === '/diensten'){
    window.dispatchEvent(new CustomEvent('wv-dienst-jump', {detail:item}));
  } else {
    window.__wvDienstTarget = item;
    navigate('/diensten');
  }
}
Object.assign(window, { goToDienst });

function Link({to, children, className, onClick: customOnClick, ...rest}){
  const onClick = (e)=>{
    // Allow native open-in-new-tab / middle click / cmd-click
    if(e.metaKey || e.ctrlKey || e.shiftKey || e.button === 1) return;
    e.preventDefault();
    customOnClick && customOnClick(e);
    navigate(to);
  };
  return <a href={to} onClick={onClick} className={className} {...rest}>{children}</a>;
}

/* ------- Per-page meta tags for SEO ------- */
function useDocumentMeta({title, description, image, type}){
  useEffect(()=>{
    const fullTitle = title
      ? `${title} · Wedding Visions`
      : 'Wedding Visions · Trouwfoto, video en photobooth in Roeselare';
    document.title = fullTitle;

    const set = (sel, content)=>{
      const el = document.querySelector(sel);
      if(el && content != null) el.setAttribute('content', content);
    };
    if(description){
      set('meta[name="description"]', description);
      set('meta[property="og:description"]', description);
      set('meta[name="twitter:description"]', description);
    }
    set('meta[property="og:title"]', fullTitle);
    set('meta[name="twitter:title"]', fullTitle);
    if(image){
      set('meta[property="og:image"]', image);
      set('meta[name="twitter:image"]', image);
    }
    if(type) set('meta[property="og:type"]', type);

    const fullUrl = SITE_ORIGIN + (location.pathname || '/');
    set('meta[property="og:url"]', fullUrl);
    const canon = document.querySelector('link[rel="canonical"]');
    if(canon) canon.setAttribute('href', fullUrl);
  }, [title, description, image, type]);
}

// Injecteer (en verwijder bij navigatie) een JSON-LD blok in de <head>.
function useJsonLd(id, data){
  const json = data ? JSON.stringify(data) : null;
  useEffect(()=>{
    if(!json) return;
    const elId = 'jsonld-' + id;
    let s = document.getElementById(elId);
    if(!s){ s = document.createElement('script'); s.type = 'application/ld+json'; s.id = elId; document.head.appendChild(s); }
    s.textContent = json;
    return ()=>{ const e = document.getElementById(elId); if(e) e.remove(); };
  }, [id, json]);
}

/* ------- Reveal on scroll ------- */
function useReveal(){
  useEffect(()=>{
    const els = document.querySelectorAll('.reveal, .reveal-stagger');
    const io = new IntersectionObserver((entries)=>{
      entries.forEach(e=>{
        if(e.isIntersecting){ e.target.classList.add('in'); io.unobserve(e.target); }
      });
    }, { threshold: .12, rootMargin: '0px 0px -40px 0px' });
    els.forEach(el=> io.observe(el));
    // Alles wat al in beeld is meteen tonen (geen scroll nodig na navigatie)
    const revealInView = ()=>{
      const vh = window.innerHeight || document.documentElement.clientHeight;
      document.querySelectorAll('.reveal:not(.in), .reveal-stagger:not(.in)').forEach(el=>{
        const r = el.getBoundingClientRect();
        if(r.top < vh * 0.98 && r.bottom > 0){ el.classList.add('in'); io.unobserve(el); }
      });
    };
    const raf1 = requestAnimationFrame(()=>{ revealInView(); });
    const t = setTimeout(revealInView, 120);
    return ()=>{ io.disconnect(); cancelAnimationFrame(raf1); clearTimeout(t); };
  });
}

/* ------- Nav ------- */
// Vertalingen voor nav-/dropdown-labels (NL-label uit data.js -> EN)
const NAV_LABELS_EN = {
  'Home':'Home',
  'Diensten & Prijzen':'Services & Pricing',
  'Portfolio':'Portfolio',
  'Werkwijze':'Process',
  'Team':'Team',
  'Plan gesprek':'Book a call',
  'Fotografie':'Photography',
  'Videografie':'Videography',
  'Photobooth':'Photobooth',
  'Album':'Album',
  'Koppelshoot':'Couple shoot',
};
function navT(label){ return WV_LANG==='en' ? (NAV_LABELS_EN[label] || label) : label; }
Object.assign(window, { navT });

function Nav({current, solid}){
  const [scrolled, setScrolled] = useState(false);
  const [open, setOpen] = useState(false);
  const lang = useLang();
  const t = useT();
  useEffect(()=>{
    const onScroll = ()=> setScrolled(window.scrollY > 40);
    window.addEventListener('scroll', onScroll);
    return ()=> window.removeEventListener('scroll', onScroll);
  },[]);
  const cls = 'nav' + (solid || scrolled ? ' solid' : '') + (open ? ' mobile-open' : '');
  const close = ()=> setOpen(false);
  const mainLinks = SITE.nav.filter(n=> n.to !== '/contact');
  const langBtn = (code, label)=> (
    <button
      type="button"
      onClick={()=> setLang(code)}
      data-cursor="hover"
      aria-pressed={lang===code}
      style={{
        background:'transparent', border:'none', cursor:'pointer', padding:'2px 4px',
        fontSize:11, letterSpacing:'.18em', fontWeight: lang===code ? 700 : 400,
        color: lang===code ? 'inherit' : 'currentColor',
        opacity: lang===code ? 1 : 0.5,
        transition:'opacity .2s',
      }}
    >{label}</button>
  );
  const langToggle = (
    <div className="nav__lang" style={{display:'inline-flex', alignItems:'center', gap:2, marginRight:4}} aria-label="Taal / Language">
      {langBtn('nl','NL')}
      <span aria-hidden="true" style={{opacity:.4, fontSize:11}}>|</span>
      {langBtn('en','EN')}
    </div>
  );
  return (
    <nav className={cls}>
      <Link to="/" className="nav__logo" data-cursor="hover" aria-label="Wedding Visions">
        <img src="/assets/logo.png" alt="Wedding Visions" className="nav__logo-img"/>
      </Link>
      <div className="nav__lang-bar">{langToggle}</div>
      <button className="nav__mobile-toggle" aria-label="Menu" onClick={()=>setOpen(!open)}>
        {open ? '×' : '≡'}
      </button>
      <div className="nav__links">
        {mainLinks.map(n=>{
          const isActive = current===n.to || (n.to!=='/' && current.startsWith(n.to));
          if(n.to === '/diensten'){
            return (
              <div key={n.to} className="nav__item-drop">
                <Link to={n.to} className={isActive?'active':''} onClick={close}>
                  {navT(n.label)} <span className="nav__caret" aria-hidden="true">▾</span>
                </Link>
                <div className="nav__dropdown">
                  {(SITE.navServices||[]).map((s,i)=>(
                    <button key={i} className="nav__dropdown-item" data-cursor="hover"
                      onClick={()=>{ close(); goToDienst(s); }}>
                      {navT(s.label)}
                    </button>
                  ))}
                </div>
              </div>
            );
          }
          return (
            <Link key={n.to} to={n.to} className={isActive?'active':''} onClick={close}>
              {navT(n.label)}
            </Link>
          );
        })}
      </div>
      <div className="nav__actions">
        {langToggle}
        <Link to="/contact" className="nav__cta nav__cta--primary" data-cursor="hover" onClick={close}>
          {t('Plan gesprek','Book a call')}
        </Link>
        <a href="https://perceptiongroup.up.railway.app/portal/login" target="_blank" rel="noreferrer" className="nav__cta nav__cta--secondary" data-cursor="hover">{t('Login','Login')}</a>
      </div>
      <style>{`
        .nav__lang button:hover{opacity:1 !important}
        .nav__lang-bar{display:none}
        @media (max-width:1024px){
          .nav__actions .nav__lang{display:none}
          .nav__lang-bar{display:inline-flex; align-items:center; margin-left:auto; margin-right:6px}
          .nav.mobile-open .nav__lang-bar{margin-left:0}
        }
      `}</style>
    </nav>
  );
}

/* ------- Footer ------- */
function Footer(){
  const t = useT();
  const reviews = t('5,0 · 12 Google reviews','5.0 · 12 Google reviews');
  return (
    <footer className="footer">
      <div className="wrap">
        <div className="footer-grid">
          <div>
            <h6>{SITE.contact.company}</h6>
            <p style={{marginBottom:8}}>{SITE.contact.address1}<br/>{SITE.contact.address2}, {t('België','Belgium')}</p>
            <p style={{color:'#8E867C', fontSize:12}}>{t('BTW BE 1031.162.458','VAT BE 1031.162.458')}</p>
            <div style={{display:'flex', gap:20, marginTop:24}}>
              <a href={SITE.contact.instagram} target="_blank" rel="noreferrer">Instagram ↗</a>
              <a href={SITE.contact.facebook} target="_blank" rel="noreferrer">Facebook ↗</a>
            </div>
          </div>
          <div>
            <h6>{t('Navigatie','Navigation')}</h6>
            {SITE.nav.map(n=> <Link key={n.to} to={n.to}>{navT(n.label)}</Link>)}
          </div>
          <div>
            <h6>{t('Diensten','Services')}</h6>
            <Link to="/diensten">{t('Fotografie','Photography')}</Link>
            <Link to="/diensten">{t('Videografie','Videography')}</Link>
            <Link to="/diensten">{t('Photobooth','Photobooth')}</Link>
            <Link to="/diensten">{t('Koppelshoot','Couple shoot')}</Link>
            <Link to="/diensten">{t('Fotoboek','Photo album')}</Link>
          </div>
          <div>
            <h6>Contact</h6>
            <a href={'mailto:'+SITE.contact.email}>{SITE.contact.email}</a>
            <a href={SITE.contact.phoneLink}>{SITE.contact.phone}</a>
            <p style={{fontSize:12, color:'#8E867C', marginTop:16}}>
              ★ {reviews}
            </p>
          </div>
        </div>

        <div className="footer-bottom">
          <span>© {new Date().getFullYear()} Wedding Visions · {t('Alle rechten voorbehouden','All rights reserved')}</span>
          <span style={{display:'flex', gap:20, alignItems:'center', flexWrap:'wrap'}}>
            <Link to="/voorwaarden">{t('Algemene voorwaarden','Terms & conditions')}</Link>
            <a href="/admin" className="footer-admin" title={t('Beheer','Admin')} aria-label={t('Beheer','Admin')}>
              <svg viewBox="0 0 24 24" width="14" height="14" fill="none" stroke="currentColor" strokeWidth="1.6" strokeLinecap="round" strokeLinejoin="round">
                <rect x="5" y="11" width="14" height="9" rx="1.5"/>
                <path d="M8 11V8a4 4 0 0 1 8 0v3"/>
              </svg>
            </a>
          </span>
        </div>
      </div>
    </footer>
  );
}

/* ------- Scroll to top knop (hele site) ------- */
function ScrollTopButton(){
  const [show, setShow] = useState(false);
  const t = useT();
  useEffect(()=>{
    const onScroll = ()=> setShow(window.scrollY > 600);
    window.addEventListener('scroll', onScroll, {passive:true});
    onScroll();
    return ()=> window.removeEventListener('scroll', onScroll);
  },[]);
  return (
    <button
      className={'scrolltop '+(show?'show':'')}
      onClick={()=> window.scrollTo({top:0, behavior:'smooth'})}
      aria-label={t('Terug naar boven','Back to top')}
      data-cursor="hover"
    >
      <svg viewBox="0 0 24 24" width="18" height="18" fill="none" stroke="currentColor" strokeWidth="1.8" strokeLinecap="round" strokeLinejoin="round">
        <path d="M12 19V5M6 11l6-6 6 6"/>
      </svg>
    </button>
  );
}

/* ------- Page shell ------- */
function Page({children, label}){
  useReveal();
  return (
    <main data-screen-label={label} style={{paddingTop:0}}>
      {children}
    </main>
  );
}

/* ------- Real image component ------- */
function Img({src, alt, ar="3/4", style={}, className="", zoom=false}){
  return (
    <div className={`img ${zoom?'zoom':''} ${className}`} style={{aspectRatio:ar, ...style}}>
      <img src={src} alt={alt||''} loading="lazy"/>
    </div>
  );
}

Object.assign(window, { useCursor, useRoute, navigate, Link, useReveal, Nav, Footer, Page, Img, useDocumentMeta, useJsonLd });
