/* global React */
const { useState, useEffect } = React;

// ----- Lucide icon helper -----
// Uses the documented `<i data-lucide="...">` + `lucide.createIcons()` pattern
// so we work with whatever shape the UMD bundle ships.
function Icon({ name, size = 20, stroke = 1.75, color }) {
  const ref = React.useRef(null);
  useEffect(() => {
    if (window.lucide && window.lucide.createIcons && ref.current) {
      window.lucide.createIcons({ icons: window.lucide.icons, nameAttr: 'data-lucide', attrs: {} });
    }
  });
  return (
    <span ref={ref} style={{ display: 'inline-flex', color, lineHeight: 0 }}>
      <i data-lucide={name} style={{ width: size, height: size, strokeWidth: stroke }} />
    </span>
  );
}

// ----- Logo (inline SVG so brand fonts apply) -----
function Logo({ height = 30 }) {
  const w = (height / 80) * 360;
  return (
    <svg width={w} height={height} viewBox="0 0 360 80" xmlns="http://www.w3.org/2000/svg" aria-label="Rio Grande Websites">
      <g stroke="var(--rg-turq-500, #2D5F58)" strokeWidth="3" fill="none" strokeLinecap="round">
        <path d="M 0,29 C 16,22 28,36 44,29"/>
        <path d="M 0,40 C 16,33 28,47 44,40"/>
        <path d="M 0,51 C 16,44 28,58 44,51"/>
      </g>
      <text x="56" y="46" style={{ fontFamily: "'Cormorant Garamond', Georgia, serif", fontStyle: 'italic', fontWeight: 500, fontSize: 44, fill: 'var(--rg-ink-900, #1F1A14)', letterSpacing: '-0.01em' }}>Rio Grande</text>
      <text x="58" y="68" style={{ fontFamily: "var(--font-sans), system-ui, sans-serif", fontWeight: 600, fontSize: 11, letterSpacing: '0.32em', fill: 'var(--rg-clay-700, #823D2B)', textTransform: 'uppercase' }}>WEBSITES</text>
    </svg>
  );
}

// ----- Eyebrow -----
function Eyebrow({ children }) {
  return <span className="eyebrow">{children}</span>;
}

// ----- Buttons -----
// Primary buttons get a subtle magnetic pull toward the cursor on desktop.
function Button({ children, variant = 'primary', icon, onClick }) {
  const ref = React.useRef(null);
  useEffect(() => {
    const el = ref.current;
    if (!el) return;
    const coarse = window.matchMedia('(pointer: coarse)').matches;
    const reduced = window.matchMedia('(prefers-reduced-motion: reduce)').matches;
    if (coarse || reduced || variant !== 'primary') return;
    const onMove = (e) => {
      const r = el.getBoundingClientRect();
      const dx = e.clientX - (r.left + r.width / 2);
      const dy = e.clientY - (r.top + r.height / 2);
      el.style.setProperty('--mx', `${dx * 0.18}px`);
      el.style.setProperty('--my', `${dy * 0.22}px`);
    };
    const onLeave = () => {
      el.style.setProperty('--mx', `0px`);
      el.style.setProperty('--my', `0px`);
    };
    el.addEventListener('pointermove', onMove);
    el.addEventListener('pointerleave', onLeave);
    return () => {
      el.removeEventListener('pointermove', onMove);
      el.removeEventListener('pointerleave', onLeave);
    };
  }, [variant]);
  return (
    <button ref={ref} className={`btn btn-${variant} ${variant === 'primary' ? 'btn-magnetic' : ''}`} onClick={onClick}>
      <span className="btn-inner">
        {children}
        {icon && <Icon name={icon} size={16} />}
      </span>
    </button>
  );
}

// ----- Word-stagger headline -----
// Splits text on spaces, wraps each word in a span that rises into place.
// Supports an italic accent for the trailing N words (defaults to the last 2).
function StaggerHeadline({ text, tail = 2, className = '' }) {
  const words = text.split(' ');
  const headCount = Math.max(0, words.length - tail);
  return (
    <h1 className={`stagger-h1 ${className}`} aria-label={text}>
      {words.map((w, i) => {
        const isTail = i >= headCount;
        return (
          <span key={i} className="word-wrap">
            <span
              className={`word ${isTail ? 'word-italic' : ''}`}
              style={{ animationDelay: `${0.06 * i + 0.08}s` }}
            >
              {w}
            </span>
          </span>
        );
      })}
    </h1>
  );
}

// ----- Counter — counts up to target on intersection -----
function Counter({ to, prefix = '', suffix = '', duration = 1400 }) {
  const ref = React.useRef(null);
  const [val, setVal] = useState(0);
  useEffect(() => {
    const el = ref.current;
    if (!el) return;
    const reduced = window.matchMedia('(prefers-reduced-motion: reduce)').matches;
    if (reduced) { setVal(to); return; }
    let started = false;
    const io = new IntersectionObserver((entries) => {
      entries.forEach((e) => {
        if (e.isIntersecting && !started) {
          started = true;
          const start = performance.now();
          const tick = (now) => {
            const t = Math.min(1, (now - start) / duration);
            // ease-out cubic
            const eased = 1 - Math.pow(1 - t, 3);
            setVal(Math.round(to * eased));
            if (t < 1) requestAnimationFrame(tick);
          };
          requestAnimationFrame(tick);
          io.disconnect();
        }
      });
    }, { threshold: 0.3 });
    io.observe(el);
    return () => io.disconnect();
  }, [to, duration]);
  return <span ref={ref}>{prefix}{val}{suffix}</span>;
}

// ----- Spotlight card — pointer-follow soft glow -----
// Wraps an existing card; coordinates fed to CSS via --sx / --sy.
function Spotlight({ children, className = '', ...rest }) {
  const ref = React.useRef(null);
  useEffect(() => {
    const el = ref.current;
    if (!el) return;
    const coarse = window.matchMedia('(pointer: coarse)').matches;
    if (coarse) return;
    const onMove = (e) => {
      const r = el.getBoundingClientRect();
      el.style.setProperty('--sx', `${e.clientX - r.left}px`);
      el.style.setProperty('--sy', `${e.clientY - r.top}px`);
    };
    el.addEventListener('pointermove', onMove);
    return () => el.removeEventListener('pointermove', onMove);
  }, []);
  return <div ref={ref} className={`spotlight ${className}`} {...rest}>{children}</div>;
}

// ----- Tilt card — subtle 3D rotation toward cursor -----
function Tilt({ children, className = '', max = 6, ...rest }) {
  const ref = React.useRef(null);
  useEffect(() => {
    const el = ref.current;
    if (!el) return;
    const coarse = window.matchMedia('(pointer: coarse)').matches;
    const reduced = window.matchMedia('(prefers-reduced-motion: reduce)').matches;
    if (coarse || reduced) return;
    const onMove = (e) => {
      const r = el.getBoundingClientRect();
      const px = (e.clientX - r.left) / r.width - 0.5;
      const py = (e.clientY - r.top) / r.height - 0.5;
      el.style.setProperty('--tx', `${-py * max}deg`);
      el.style.setProperty('--ty', `${px * max}deg`);
    };
    const onLeave = () => {
      el.style.setProperty('--tx', `0deg`);
      el.style.setProperty('--ty', `0deg`);
    };
    el.addEventListener('pointermove', onMove);
    el.addEventListener('pointerleave', onLeave);
    return () => {
      el.removeEventListener('pointermove', onMove);
      el.removeEventListener('pointerleave', onLeave);
    };
  }, [max]);
  return <div ref={ref} className={`tilt ${className}`} {...rest}>{children}</div>;
}

// ----- Nav -----
function Nav({ page, setPage }) {
  const [scrolled, setScrolled] = useState(false);
  const [menuOpen, setMenuOpen] = useState(false);
  useEffect(() => {
    const onScroll = () => setScrolled(window.scrollY > 64);
    window.addEventListener('scroll', onScroll);
    onScroll();
    return () => window.removeEventListener('scroll', onScroll);
  }, []);
  // Close on Escape; lock body scroll while open
  useEffect(() => {
    if (!menuOpen) return;
    const onKey = (e) => { if (e.key === 'Escape') setMenuOpen(false); };
    window.addEventListener('keydown', onKey);
    const prev = document.body.style.overflow;
    document.body.style.overflow = 'hidden';
    return () => {
      window.removeEventListener('keydown', onKey);
      document.body.style.overflow = prev;
    };
  }, [menuOpen]);
  // Close menu when navigating to a new page
  const go = (k) => { setPage(k); setMenuOpen(false); };
  const items = [
    ['home', 'Home'], ['services', 'Services'],
    ['about', 'About'], ['contact', 'Contact'],
  ];
  return (
    <>
      <nav className={`nav ${scrolled ? 'scrolled' : ''}`}>
        <div className="nav-brand" onClick={() => go('home')}>
          <Logo />
        </div>
        <div className="nav-links">
          {items.map(([k, label]) => (
            <a key={k} className={`nav-link ${page === k ? 'active' : ''}`} onClick={(e) => { e.preventDefault(); go(k); }}>
              {label}
            </a>
          ))}
        </div>
        <a className="nav-cta" onClick={() => go('contact')}>
          Start a project
          <Icon name="arrow-up-right" size={14} stroke={2.25} />
        </a>
        <button
          type="button"
          className="nav-toggle"
          aria-label={menuOpen ? 'Close menu' : 'Open menu'}
          aria-expanded={menuOpen}
          aria-controls="mobile-drawer"
          onClick={() => setMenuOpen((v) => !v)}
        >
          <Icon name={menuOpen ? 'x' : 'menu'} size={22} stroke={2} />
        </button>
      </nav>
      <div
        id="mobile-drawer"
        className={`nav-drawer ${menuOpen ? 'open' : ''}`}
        aria-hidden={!menuOpen}
      >
        <div className="nav-drawer-inner">
          <ul className="nav-drawer-links">
            {items.map(([k, label]) => (
              <li key={k}>
                <a
                  className={page === k ? 'active' : ''}
                  onClick={(e) => { e.preventDefault(); go(k); }}
                  tabIndex={menuOpen ? 0 : -1}
                >
                  {label}
                </a>
              </li>
            ))}
          </ul>
          <a className="nav-drawer-cta" onClick={() => go('contact')} tabIndex={menuOpen ? 0 : -1}>
            Start a project
            <Icon name="arrow-up-right" size={16} stroke={2.25} />
          </a>
        </div>
      </div>
    </>
  );
}

// ----- Footer -----
function Footer({ setPage }) {
  return (
    <footer className="footer">
      <div className="footer-grid">
        <div className="footer-brand">
          <Logo height={40} />
          <p>A local web team in Las Cruces, New Mexico. Clean, modern, affordable websites for small businesses and individuals.</p>
        </div>
        <div>
          <h5>Studio</h5>
          <ul>
            <li><a onClick={() => setPage('about')}>About</a></li>
            <li><a onClick={() => setPage('services')}>Services</a></li>
            <li><a onClick={() => setPage('contact')}>Contact</a></li>
          </ul>
        </div>
        <div>
          <h5>Web design</h5>
          <ul>
            <li><a href="/web-design-las-cruces">Web design Las Cruces</a></li>
            <li><a href="/web-design-el-paso">Web design El Paso</a></li>
            <li><a href="/small-business-websites">Small business websites</a></li>
            <li><a href="/website-redesign">Website redesign</a></li>
            <li><a href="/seo-las-cruces">Local SEO</a></li>
          </ul>
        </div>
        <div>
          <h5>Contact</h5>
          <ul>
            <li><a href="mailto:contact@riograndeweb.com">contact@riograndeweb.com</a></li>
            <li><a>Las Cruces, NM</a></li>
          </ul>
        </div>
      </div>
      <div className="footer-bottom">
        <span>© 2026 Rio Grande Websites · Las Cruces, <em>NM</em>.</span>
        <span><a href="/privacy-policy">Privacy policy</a> · <a href="/terms-and-conditions">Terms</a> · <a href="/disclaimer">Disclaimer</a></span>
      </div>
    </footer>
  );
}

// ----- Image plate -----
function ImagePlate({ src, ratio = '4/5', radius = 'var(--r-2xl)', shift }) {
  return (
    <div style={{
      aspectRatio: ratio,
      borderRadius: radius,
      backgroundImage: `url(${src})`,
      backgroundSize: 'cover',
      backgroundPosition: 'center',
      boxShadow: 'var(--shadow-md)',
      transform: shift,
    }} />
  );
}

// ----- Reveal-on-scroll -----
// Adds .is-visible the first time the element crosses ~15% into view.
// Once visible, we stop observing — reveals never re-fire on re-scroll.
function useReveal(options = {}) {
  const ref = React.useRef(null);
  React.useEffect(() => {
    const el = ref.current;
    if (!el) return;
    const reduced = window.matchMedia('(prefers-reduced-motion: reduce)').matches;
    if (reduced) { el.classList.add('is-visible'); return; }
    const io = new IntersectionObserver((entries) => {
      entries.forEach((e) => {
        if (e.isIntersecting) {
          el.classList.add('is-visible');
          io.unobserve(el);
        }
      });
    }, { threshold: options.threshold ?? 0.15, rootMargin: options.rootMargin ?? '0px 0px -8% 0px' });
    io.observe(el);
    return () => io.disconnect();
  }, []);
  return ref;
}

function Reveal({ children, as: Tag = 'div', stagger = false, className = '', ...rest }) {
  const ref = useReveal();
  const cls = [stagger ? 'reveal-stagger' : 'reveal', className].filter(Boolean).join(' ');
  return <Tag ref={ref} className={cls} {...rest}>{children}</Tag>;
}

// ----- Marquee — duplicate group inline so the -50% loop is seamless -----
function Marquee({ items }) {
  const Group = ({ ariaHidden }) => (
    <div className="marquee-group" aria-hidden={ariaHidden ? 'true' : undefined}>
      {items.map((it, i) => (
        <React.Fragment key={i}>
          <span>{it}</span>
          <span className="dot" aria-hidden="true" />
        </React.Fragment>
      ))}
    </div>
  );
  return (
    <div className="clients" role="region" aria-label="What we build for">
      <div className="marquee">
        <Group />
        <Group ariaHidden />
      </div>
    </div>
  );
}

// expose
Object.assign(window, {
  Icon, Logo, Eyebrow, Button, Nav, Footer, ImagePlate, Reveal, useReveal, Marquee,
  StaggerHeadline, Counter, Spotlight, Tilt,
});
