/* global React */
const { useState: useSCState, useEffect: useSCEffect, useRef: useSCRef } = React;

function Showcase() {
  const cases = [
    {
      name: "Hoshino Matcha",
      tag: "Subscription · Beverages",
      desc: "Stone-milled ceremonial matcha from Uji, delivered monthly.",
      gradient: "linear-gradient(135deg, #C9C39A 0%, #8F9A75 60%, #5A6A4F 100%)",
      accent: "#7E8A65",
      built: "Apr 2026",
      uplift: "1.4k subs · 30 days",
      readTime: "3 min",
      story: {
        founder: "Yuki Tanaka",
        location: "Tokyo, JP",
        summary: "A third-generation matcha grower wanted a subscription business but had no time to learn Shopify. Dispatch built the store, set the pricing tiers, and now runs renewals, support, and the monthly shipping rhythm.",
        moments: [
          "Storefront built in 94 seconds from a single paragraph",
          "Pricing tiers A/B tested across the first 200 visitors",
          "Renewal flow + customs paperwork running on autopilot",
        ],
        stats: [
          ["1,420", "Active subs · 30 days"],
          ["38%", "Email open rate"],
          ["0", "Hours spent on ops"],
        ],
      },
    },
    {
      name: "Maison Albe",
      tag: "Refill · Fragrance",
      desc: "A refillable parfum studio in Brooklyn — memberships, bookings, and supply.",
      gradient: "linear-gradient(135deg, #F0E2CC 0%, #C9A988 50%, #7A5F45 100%)",
      accent: "#B89B7F",
      built: "Mar 2026",
      uplift: "$84k MRR · self-run",
      readTime: "4 min",
      story: {
        founder: "Camille Albe",
        location: "Brooklyn, NY",
        summary: "A perfumer turning her studio practice into a brand. Dispatch handles the membership tier, in-studio booking calendar, and the refill supply chain so she can stay at the bench.",
        moments: [
          "Membership and one-time products under one checkout",
          "Booking calendar synced to studio capacity",
          "Refills auto-reordered when a region drops below threshold",
        ],
        stats: [
          ["$84k", "MRR"],
          ["620", "Active members"],
          ["12", "Hours/week saved"],
        ],
      },
    },
    {
      name: "North/Line Denim",
      tag: "Drops · Apparel",
      desc: "Weekly drops of restored Japanese vintage denim — no staff needed.",
      gradient: "linear-gradient(135deg, #6B7785 0%, #3A4452 50%, #1A222E 100%)",
      accent: "#5C6A78",
      built: "Feb 2026",
      uplift: "32 drops · 0 returns",
      readTime: "3 min",
      story: {
        founder: "Mark Reyes",
        location: "Portland, OR",
        summary: "Solo operator restoring vintage denim. Each piece is unique. Dispatch photographs prompts, drops the listings every Friday, and routes the shipping — turning a one-person shop into a weekly cadence.",
        moments: [
          "Drop cadence locked to every Friday 10am PT",
          "One-of-one product pages auto-generated from intake notes",
          "International shipping with duties included at checkout",
        ],
        stats: [
          ["32", "Drops shipped"],
          ["100%", "Sell-through"],
          ["0", "Returns"],
        ],
      },
    },
    {
      name: "Crescent Goods",
      tag: "DTC · Home",
      desc: "Handmade ceramic tableware from Lisbon, kiln to checkout.",
      gradient: "linear-gradient(135deg, #EFE0C6 0%, #C5A878 50%, #846B4A 100%)",
      accent: "#A38F6C",
      built: "Jan 2026",
      uplift: "98 SKUs · 12 countries",
      readTime: "5 min",
      story: {
        founder: "Inês Ferreira",
        location: "Lisbon, PT",
        summary: "A ceramics studio that grew faster than it could hire. Dispatch took over catalog, customer service, and tax compliance across 12 countries so the founders could focus on the kiln.",
        moments: [
          "98 SKUs catalogued in the studio voice",
          "VAT and duties compliant in 12 countries from day one",
          "Customer questions answered in tone or escalated",
        ],
        stats: [
          ["98", "SKUs live"],
          ["12", "Countries"],
          ["4.9", "Avg rating"],
        ],
      },
    },
    {
      name: "Parallel Studio",
      tag: "Editions · Print",
      desc: "Limited-run risograph prints — lotteries, printing, and global shipping.",
      gradient: "linear-gradient(135deg, #DAC6E8 0%, #9C7FC2 50%, #5A4080 100%)",
      accent: "#7E68A8",
      built: "Mar 2026",
      uplift: "9 editions · sold out",
      readTime: "3 min",
      story: {
        founder: "Saoirse Doyle",
        location: "Dublin, IE",
        summary: "A two-person print studio doing limited runs. Dispatch runs the entry lottery, sequences the print queue, and ships globally — and the studio simply prints.",
        moments: [
          "Entry lottery with one click per edition",
          "Print queue sequenced to studio capacity",
          "Global ship + tracking handled per buyer",
        ],
        stats: [
          ["9", "Editions"],
          ["100%", "Sold out"],
          ["48", "Countries shipped"],
        ],
      },
    },
    {
      name: "Sundry Ops",
      tag: "Wholesale · Pantry",
      desc: "A pantry brand selling to 200+ grocers — orders, invoices, and route planning.",
      gradient: "linear-gradient(135deg, #D7C5A0 0%, #A28B61 50%, #5F4B2C 100%)",
      accent: "#8A7250",
      built: "Feb 2026",
      uplift: "240 accounts · weekly",
      readTime: "4 min",
      story: {
        founder: "Asa Bergman",
        location: "Minneapolis, MN",
        summary: "A wholesale pantry brand with weekly orders from 240 specialty grocers. Dispatch runs the buyer portal, generates invoices, and plans delivery routes by region.",
        moments: [
          "Buyer portal personalized per account",
          "Net-30 invoicing with auto-reminders",
          "Route plans optimized weekly",
        ],
        stats: [
          ["240", "Accounts"],
          ["52", "Weekly orders"],
          ["98%", "On-time rate"],
        ],
      },
    },
  ];

  const [active, setActive] = useSCState(null);
  const trackRef = useSCRef(null);
  const dragState = useSCRef({ down: false, moved: 0, startX: 0, startScroll: 0 });

  useSCEffect(() => {
    if (active === null) return;
    const onKey = (e) => { if (e.key === "Escape") setActive(null); };
    window.addEventListener("keydown", onKey);
    const prevOverflow = document.body.style.overflow;
    document.body.style.overflow = "hidden";
    return () => {
      window.removeEventListener("keydown", onKey);
      document.body.style.overflow = prevOverflow;
    };
  }, [active]);

  const onPointerDown = (e) => {
    const track = trackRef.current;
    if (!track) return;
    dragState.current = { down: true, moved: 0, startX: e.clientX, startScroll: track.scrollLeft };
    track.setPointerCapture && track.setPointerCapture(e.pointerId);
    track.classList.add("dragging");
  };
  const onPointerMove = (e) => {
    if (!dragState.current.down) return;
    const track = trackRef.current;
    if (!track) return;
    const dx = e.clientX - dragState.current.startX;
    dragState.current.moved = Math.max(dragState.current.moved, Math.abs(dx));
    track.scrollLeft = dragState.current.startScroll - dx;
  };
  const onPointerUp = (e) => {
    const track = trackRef.current;
    dragState.current.down = false;
    if (track) {
      track.classList.remove("dragging");
      track.releasePointerCapture && track.releasePointerCapture(e.pointerId);
    }
  };
  const scrollBy = (dir) => {
    const track = trackRef.current;
    if (!track) return;
    const first = track.querySelector(".story");
    const step = first ? first.getBoundingClientRect().width + 20 : track.clientWidth * 0.8;
    track.scrollBy({ left: dir * step, behavior: "smooth" });
  };
  const handleCardClick = (i) => {
    if (dragState.current.moved > 6) return;
    setActive(i);
  };

  const open = active === null ? null : cases[active];

  return (
    <section className="section" id="stores">
      <div className="wrap">
        <div className="section-head">
          <span className="eyebrow"><span className="num">05 ——</span> Live on Dispatch</span>
          <div style={{display: "flex", justifyContent: "space-between", alignItems: "end", flexWrap: "wrap", gap: 24}}>
            <h2>Stories from<br/><span className="accent">founders running stores on Dispatch.</span></h2>
            <div style={{display: "flex", gap: 10, alignItems: "center"}}>
              <button type="button" className="story-nav" onClick={() => scrollBy(-1)} aria-label="Previous">
                <ArrowRight size={14} style={{transform: "rotate(180deg)"}} />
              </button>
              <button type="button" className="story-nav" onClick={() => scrollBy(1)} aria-label="Next">
                <ArrowRight size={14} />
              </button>
              <a href="#" className="btn btn-outline">All stories <ArrowRight /></a>
            </div>
          </div>
        </div>

        <div
          className="stories stories-carousel"
          ref={trackRef}
          onPointerDown={onPointerDown}
          onPointerMove={onPointerMove}
          onPointerUp={onPointerUp}
          onPointerLeave={onPointerUp}
        >
          {cases.map((c, i) => (
            <button
              type="button"
              className="story"
              key={i}
              onClick={() => handleCardClick(i)}
              aria-label={`Open case study: ${c.name}`}
            >
              <div className="story-img" style={{background: c.gradient}}>
                <span className="story-watermark">{c.name.split(" ").map(w => w[0]).join("").slice(0,2)}</span>
                <div className="story-grain" />
                <span className="story-time">{c.readTime}</span>
                <div className="story-shade" />
                <div className="story-caption">
                  <span className="story-tag">{c.tag}</span>
                  <h3>{c.name}</h3>
                  <span className="story-cue">Read case study <ArrowRight /></span>
                </div>
              </div>
            </button>
          ))}
        </div>
      </div>

      {open && (
        <div className="case-modal" role="dialog" aria-modal="true" onClick={() => setActive(null)}>
          <div className="case-modal-card" onClick={(e) => e.stopPropagation()}>
            <button className="case-close" onClick={() => setActive(null)} aria-label="Close">×</button>
            <div className="case-hero" style={{background: open.gradient}}>
              <span className="story-watermark">{open.name.split(" ").map(w => w[0]).join("").slice(0,2)}</span>
              <div className="story-grain" />
              <div className="case-hero-meta">
                <span className="story-tag">{open.tag}</span>
                <h3>{open.name}</h3>
                <span className="case-hero-loc">{open.story.founder} · {open.story.location}</span>
              </div>
            </div>
            <div className="case-body">
              <p className="case-summary">{open.story.summary}</p>

              <div className="case-stats">
                {open.story.stats.map(([k, v], i) => (
                  <div className="case-stat" key={i}>
                    <div className="case-stat-k">{k}</div>
                    <div className="case-stat-v">{v}</div>
                  </div>
                ))}
              </div>

              <div className="case-section-title">What Dispatch handles</div>
              <ul className="case-moments">
                {open.story.moments.map((m, i) => (
                  <li key={i}><span className="case-bullet" style={{background: open.accent}} />{m}</li>
                ))}
              </ul>

              <div className="case-foot">
                <span className="mono case-foot-meta">Built · {open.built}</span>
                <a href="#" className="btn btn-primary">Read the full story <Arrow /></a>
              </div>
            </div>
          </div>
        </div>
      )}
    </section>
  );
}

window.Showcase = Showcase;
