/* global React, Photo, Eyebrow, Rule, SectionNum */

/* Hero carousel — discovers however many `hero<n>.jpg` files exist (no fixed
   count), then shuffles the order fresh on every page load. */
const HERO_PATH = (n) => asset(`assets/ahp-photos/hero${n}.jpg`);
const HERO_MAX_PROBE = 40;    // hard ceiling on how far to scan
const HERO_PROBE_CHUNK = 8;   // probe this many at a time, then decide
const HERO_AUTO_MS = 4500;    // calm, but not sleepy

/* These two are composed wide; cropped to a portrait phone frame the subject
   falls outside the frame, so they sit the mobile carousel out. Skipped before
   the probe, so a phone never downloads them either. */
const HERO_SKIP_ON_PHONE = [3, 4];
const PHONE_QUERY = '(max-width: 640px)';

function shuffleArr(arr) {
  const a = [...arr];
  for (let i = a.length - 1; i > 0; i--) {
    const j = Math.floor(Math.random() * (i + 1));
    [a[i], a[j]] = [a[j], a[i]];
  }
  return a;
}

/* Discover the hero images by probing for them; keep the ones that load (which
   also preloads them).

   Probing runs a chunk at a time and stops at the first chunk that comes back
   entirely empty, rather than firing all HERO_MAX_PROBE requests every single
   load. With 8 heroes that is 16 requests instead of 40 — the difference is
   ~32 pointless 404s in the server log and on the visitor's connection, which
   matters most on a phone. Gaps in the numbering are still fine as long as no
   full chunk is missing. */
function loadHeroImages() {
  const onPhone = typeof window !== 'undefined'
    && window.matchMedia(PHONE_QUERY).matches;
  const skip = onPhone ? HERO_SKIP_ON_PHONE : [];

  const probe = (n) => {
    if (skip.indexOf(n) !== -1) return Promise.resolve(null);
    return new Promise((resolve) => {
      const img = new Image();
      img.onload = () => resolve(HERO_PATH(n));
      img.onerror = () => resolve(null);
      img.src = HERO_PATH(n);
    });
  };

  const found = [];
  // Promise chaining rather than async/await: these files are transpiled by
  // Babel standalone in the browser with no regenerator runtime loaded.
  const step = (start) => {
    if (start > HERO_MAX_PROBE) return Promise.resolve(found);
    const size = Math.min(HERO_PROBE_CHUNK, HERO_MAX_PROBE - start + 1);
    return Promise.all(Array.from({ length: size }, (_, i) => probe(start + i)))
      .then((batch) => {
        const hits = batch.filter(Boolean);
        if (!hits.length) return found;      // nothing in this chunk — stop
        found.push(...hits);
        return step(start + size);
      });
  };
  return step(1);
}

/* hero1 always opens the carousel; everything after it is shuffled fresh on
   each load. Falls back to a plain shuffle if hero1.jpg is ever missing. */
function orderHeroes(imgs) {
  const lead = HERO_PATH(1);
  const rest = shuffleArr(imgs.filter((src) => src !== lead));
  return imgs.indexOf(lead) === -1 ? rest : [lead].concat(rest);
}

function HomeHero() {
  const [order, setOrder] = React.useState([]);
  const [idx, setIdx] = React.useState(0);
  const go = (d) => setIdx((i) => (order.length ? (i + d + order.length) % order.length : 0));

  // Discover available hero images once, then order them.
  React.useEffect(() => {
    let live = true;
    loadHeroImages().then((imgs) => { if (live) setOrder(orderHeroes(imgs)); });
    return () => { live = false; };
  }, []);

  // Auto-advance. Keyed on idx so ANY change (auto or a manual click)
  // restarts the clock — no surprise jump right after clicking an arrow.
  React.useEffect(() => {
    if (order.length < 2) return;
    const t = setTimeout(() => go(1), HERO_AUTO_MS);
    return () => clearTimeout(t);
  }, [idx, order]);

  const multiple = order.length > 1;

  // Swipe, for phones and trackpad-less tablets where the arrows are a small
  // target. Horizontal intent only — a mostly-vertical drag is a page scroll.
  const touch = React.useRef(null);
  const onTouchStart = (e) => {
    const t = e.touches[0];
    touch.current = { x: t.clientX, y: t.clientY };
  };
  const onTouchEnd = (e) => {
    if (!touch.current || !multiple) return;
    const t = e.changedTouches[0];
    const dx = t.clientX - touch.current.x;
    const dy = t.clientY - touch.current.y;
    touch.current = null;
    if (Math.abs(dx) > 45 && Math.abs(dx) > Math.abs(dy)) go(dx < 0 ? 1 : -1);
  };

  return (
    <section className="hero-bleed" onTouchStart={onTouchStart} onTouchEnd={onTouchEnd}>
      {order.map((src, i) => (
        <img key={src} src={src} alt="" className="hero-bleed__img" style={{ opacity: i === idx ? 1 : 0 }} />
      ))}
      {multiple && (
        <React.Fragment>
          <button className="hero-arrow hero-arrow--left" aria-label="Previous photo" onClick={() => go(-1)}>
            <svg viewBox="0 0 24 24"><polyline points="14.5 5.5 8 12 14.5 18.5" fill="none" stroke="currentColor" strokeWidth="1.2" strokeLinecap="round" strokeLinejoin="round" /></svg>
          </button>
          <button className="hero-arrow hero-arrow--right" aria-label="Next photo" onClick={() => go(1)}>
            <svg viewBox="0 0 24 24"><polyline points="9.5 5.5 16 12 9.5 18.5" fill="none" stroke="currentColor" strokeWidth="1.2" strokeLinecap="round" strokeLinejoin="round" /></svg>
          </button>
        </React.Fragment>
      )}
    </section>
  );
}

function Welcome() {
  return (
    <section className="welcome">
      <div className="welcome__inner welcome__inner--wide">
        <Eyebrow center>A Warm Welcome</Eyebrow>
        {/* Deliberately unbroken — .headline-oneline keeps it on a single line
            across desktop widths and lets it wrap naturally on small screens. */}
        <h2 className="kit-headline kit-headline--lg headline-oneline" style={{ marginTop: 32 }}>
          <em>Hello,</em> I'm so glad you're here.
        </h2>
        <Rule center />
        <p className="kit-lede page-lede page-lede--center">
          Abby Harper Photo is built on quiet, unhurried photography for
          weddings, families, and honest milestones in Athens, Georgia.
          With a gentle editorial touch, I focus on the small, true gestures
          that make your story yours: slow mornings, quiet anticipation, and
          shared tables. Timeless imagery centered on authentic connection,
          without the rush.
        </p>
      </div>
    </section>
  );
}

function MeetPreview({ onNav }) {
  return (
    <section className="meet">
      <div className="meet__inner">
        <div className="meet__figure">
          <Photo src="assets/ahp-photos/home-branding.jpg" aspect="4/5" position="50% 32%">
          </Photo>
          <img src={asset("assets/ahp-logo/Symbol-clay.png")} alt="" className="meet__stamp" />
        </div>
        <div>
          <Eyebrow>Meet the Photographer</Eyebrow>
          <h2 className="kit-headline kit-headline--lg" style={{ marginTop: 24 }}>
            Behind the<br />
            <em>camera.</em>
          </h2>
          <Rule />
          <p className="kit-lede" style={{ marginBottom: 18 }}>
            I'm Abby, an authentic wedding and lifestyle photographer based
            in Athens. Guided by a love for quiet moments and vanilla lattes,
            my goal is simple: to create images that feel like real life.
            Less posing, more presence, and photographs that bring you right
            back to the feeling of the day.
          </p>
          <p className="kit-lede">
            My favorite photographs are the quiet ones — the ones you
            don't notice being taken, the ones that look like the day
            actually felt.
          </p>
          <div style={{ marginTop: 40, display: 'flex', alignItems: 'center', gap: 28 }}>
            <button className="kit-btn" onClick={() => onNav('about')}>
              The Whole Story
            </button>
          </div>
        </div>
      </div>
    </section>
  );
}

function FeaturedGalleries({ onNav }) {
  const items = [
    /* Each tile opens its own journal entry rather than a whole category.
       grid2 is the black-and-white frame of Ki & Madeline against the column
       (the same shot as ki-and-madeline/AHP-206), not the other Athens
       engagement — worth noting, since the title alone is ambiguous. */
    { n: '01', post: 'the-mansour-family',   title: 'The Mansour Family',    src: 'assets/ahp-photos/grid1.jpg', pos: '50% 30%', span: '1 / span 7',  h: 600 },
    { n: '02', post: 'ki-and-madeline',      title: 'An Athens Engagement',  src: 'assets/ahp-photos/grid2.jpg', pos: '50% 30%', span: '8 / span 5',  h: 600 },
    { n: '03', post: 'jack-and-katie',       title: 'Jack & Katie',          src: 'assets/ahp-photos/grid3.jpg', pos: '50% 50%', span: '1 / span 5',  h: 480 },
    { n: '04', post: 'classic-city-wedding', title: 'Classic City Wedding',  src: 'assets/ahp-photos/grid4.jpg', pos: '50% 35%', span: '6 / span 4',  h: 480 },
    { n: '05', post: 'the-wilsons',          title: 'The Wilsons',           src: 'assets/ahp-photos/grid5.jpg', pos: '50% 30%', span: '10 / span 3', h: 480 },
  ];
  return (
    <section className="featured">
      <div style={{ maxWidth: 'var(--maxw)', margin: '0 auto' }}>
        <div className="section-head">
          <div>
            <Eyebrow>Selected Work</Eyebrow>
            <h2 className="kit-headline kit-headline--lg" style={{ marginTop: 24, maxWidth: 640 }}>
              Stories told <em>thoughtfully.</em>
            </h2>
          </div>
          <button className="kit-btn kit-btn--ghost" onClick={() => onNav('portfolio')}>
            All the Galleries
          </button>
        </div>

        {/* Span + height ride on custom properties so site.css can re-shape the
            mosaic at each breakpoint — an inline grid-column could not be. */}
        <div className="featured__grid">
          {items.map(it => (
            <article
              key={it.n}
              className="featured__item"
              style={{ '--span': it.span, '--h': `${it.h}px` }}
              onClick={() => onNav(`post/${it.post}`)}
            >
              <Photo src={it.src} position={it.pos} aspect={null} className="featured__photo" />
              <div className="featured__cap">
                <h3 className="featured__title">{it.title}</h3>
              </div>
            </article>
          ))}
        </div>
      </div>
    </section>
  );
}

function HomeQuote() {
  return (
    <section className="kit-section kit-section--dark quote-band">
      <div className="quote-band__pattern" />
      <div className="quote-band__inner">
        <img src={asset("assets/ahp-logo/Symbol-rose.png")} alt="" className="quote-band__mark" />
        {/* No <br>s — the line breaks are the browser's to choose at this width */}
        <p className="quote-band__text quote-band__text--long">
          "She made our day so special and stress free. She really listened to
          what we wanted our wedding day to look like and made sure that she
          helped make that happen. She was so organized, professional, and kind!
          You could tell she just wanted to make sure we were having the{' '}
          <em style={{ color: 'var(--rose)' }}>best day!</em>"
        </p>
        <hr className="kit-rule kit-rule--center" style={{ margin: '28px auto', background: 'var(--rose)' }} />
        <div className="quote-band__attr">Hal &amp; Peyton · Wedding</div>
      </div>
    </section>
  );
}

function HomePage({ onNav }) {
  return (
    <React.Fragment>
      <HomeHero />
      <Welcome />
      <MeetPreview onNav={onNav} />
      <FeaturedGalleries onNav={onNav} />
      <HomeQuote />
    </React.Fragment>
  );
}

window.HomePage = HomePage;
