const { useState, useEffect, useMemo, useRef } = React;

// ============ ICONS (Lucide-style, monolinear) ============
const Icon = {
  Search: () => (
    <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.8" strokeLinecap="round" strokeLinejoin="round">
      <circle cx="11" cy="11" r="7" />
      <path d="m21 21-4.3-4.3" />
    </svg>
  ),
  ArrowRight: ({ size = 14 }) => (
    <svg width={size} height={size} viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.8" strokeLinecap="round" strokeLinejoin="round">
      <path d="M5 12h14" /><path d="m12 5 7 7-7 7" />
    </svg>
  ),
  Copy: () => (
    <svg width="11" height="11" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
      <rect x="9" y="9" width="13" height="13" rx="1" /><path d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1" />
    </svg>
  ),
  Check: () => (
    <svg width="11" height="11" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.4" strokeLinecap="round" strokeLinejoin="round">
      <path d="M20 6 9 17l-5-5" />
    </svg>
  ),
  Mail: () => (
    <svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.8" strokeLinecap="round" strokeLinejoin="round">
      <rect width="20" height="16" x="2" y="4" rx="0" /><path d="m22 7-10 5L2 7" />
    </svg>
  ),
  Grid: () => (
    <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.8" strokeLinecap="round" strokeLinejoin="round">
      <rect x="3" y="3" width="7" height="7" /><rect x="14" y="3" width="7" height="7" />
      <rect x="14" y="14" width="7" height="7" /><rect x="3" y="14" width="7" height="7" />
    </svg>
  ),
  List: () => (
    <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.8" strokeLinecap="round" strokeLinejoin="round">
      <line x1="8" x2="21" y1="6" y2="6" /><line x1="8" x2="21" y1="12" y2="12" /><line x1="8" x2="21" y1="18" y2="18" />
      <line x1="3" x2="3.01" y1="6" y2="6" /><line x1="3" x2="3.01" y1="12" y2="12" /><line x1="3" x2="3.01" y1="18" y2="18" />
    </svg>
  ),
};

// ============ LOGO COMPONENT (with fallback) ============
function PartnerLogo({ partner, size = 56 }) {
  const [err, setErr] = useState(false);
  if (partner.logo && !err) {
    const wide = partner.wide;
    const imgStyle = partner.logoScale
      ? { maxWidth: Math.min(100, 88 * partner.logoScale) + '%', maxHeight: (88 * partner.logoScale) + '%' }
      : undefined;
    return (
      <div
        className={"pcard__logo" + (wide ? " pcard__logo--wide" : "")}
        style={{ width: wide ? Math.round(size * 1.95) : size, height: size }}
      >
        <img src={partner.logo} alt={partner.name} onError={() => setErr(true)} style={imgStyle} />
      </div>
    );
  }
  return (
    <div className="pcard__logo pcard__logo--fallback" style={{ width: size, height: size }}>
      {partner.short}
    </div>
  );
}

// ============ HEADER ============
function Header() {
  return (
    <header className="site-header">
      <div className="site-header__inner">
        <div className="brandmark">
          <span className="lockup">
            <img className="lockup__z47" src="brand/z47-logo-orange.svg" alt="Z47" />
            <span className="lockup__rule"></span>
            <img className="lockup__devc" src="brand/devc-logo-knockout.svg" alt="DeVC" />
          </span>
          <div className="brandmark__divider"></div>
          <span style={{ fontFamily: 'var(--font-display)', fontWeight: 400, fontSize: 14, letterSpacing: '0.04em', color: 'var(--fg-2)' }}>
            Partnerships Playbook
          </span>
        </div>
        <div className="header-meta">
          <span className="header-meta__issue"><span className="header-meta__dot"></span>For portfolio founders only</span>
        </div>
      </div>
    </header>
  );
}

// ============ HERO ============
function Hero({ data }) {
  const totalPartners = data.categories.reduce((a, c) => a + c.partners.length, 0);
  const totalCategories = data.categories.length;
  return (
    <section className="hero">
      <div className="hero__eyebrow">
        <div className="hero__path"></div>
        <span className="hero__eyebrow-text">Portfolio Company Perks</span>
      </div>
      <h1 className="hero__title">
        Exclusive Partner <span className="italic accent">Benefits</span><br />
        for Z47 Portfolio Companies
      </h1>
      <p className="hero__lede">
        {totalPartners} partners across {totalCategories} categories — over a million dollars in credits, discounts, and dedicated programmes, curated for missionary founders building from Day Zero.
      </p>
      <div className="hero__numbers">
        <div className="bignum">
          <div className="bignum__value">{totalPartners}</div>
          <div className="bignum__label">Active partners</div>
        </div>
        <div className="bignum">
          <div className="bignum__value">$1<span className="unit">M+</span></div>
          <div className="bignum__label">Credits & discounts available</div>
        </div>
        <div className="bignum">
          <div className="bignum__value">{totalCategories}</div>
          <div className="bignum__label">Categories of leverage</div>
        </div>
      </div>
    </section>
  );
}

// ============ TOOLBAR ============
function Toolbar({ data, active, setActive, search, setSearch, view, setView }) {
  const counts = useMemo(() => {
    const total = data.categories.reduce((acc, c) => acc + c.partners.length, 0);
    const map = { all: total };
    data.categories.forEach((c) => { map[c.id] = c.partners.length; });
    return map;
  }, [data]);

  return (
    <div className="toolbar">
      <div className="toolbar__row">
        <span className="toolbar__label">Browse</span>
        <button className="chip" data-active={active === "all"} onClick={() => setActive("all")}>
          All <span className="chip__count">{counts.all}</span>
        </button>
        {data.categories.map((c) => (
          <button key={c.id} className="chip" data-active={active === c.id} onClick={() => setActive(c.id)}>
            {c.name} <span className="chip__count">{counts[c.id]}</span>
          </button>
        ))}
        <div className="toolbar__search">
          <Icon.Search />
          <input
            type="text"
            placeholder="Search by partner, perk, or keyword"
            value={search}
            onChange={(e) => setSearch(e.target.value)}
          />
        </div>
        <button
          className="chip"
          style={{ padding: '10px 12px' }}
          data-active={view === "list"}
          onClick={() => setView(view === "list" ? "grid" : "list")}
          title="Toggle view"
          aria-label="Toggle view"
        >
          {view === "list" ? <Icon.Grid /> : <Icon.List />}
        </button>
      </div>
    </div>
  );
}

// ============ PARTNER CARD ============
function PartnerCard({ partner, density }) {
  const [expanded, setExpanded] = useState(false);
  const [copied, setCopied] = useState(false);

  const showMore = partner.bullets.length > 2;

  const copyCode = () => {
    navigator.clipboard?.writeText(partner.code.value);
    setCopied(true);
    window.dispatchEvent(new CustomEvent('z47-toast', { detail: `Copied · ${partner.code.value}` }));
    setTimeout(() => setCopied(false), 1800);
  };

  return (
    <article className={"pcard" + (density === "dense" ? " dense" : "")}>
      <div className="pcard__top">
        <PartnerLogo partner={partner} size={density === "dense" ? 48 : 56} />
        <div className="pcard__tag">{partner.tag}</div>
      </div>
      <h3 className="pcard__name">{partner.name}</h3>
      <p className="pcard__headline">{partner.headline}</p>
      <ul className={"pcard__bullets" + (!expanded ? " collapsed" : "")}>
        {partner.bullets.map((b, i) => <li key={i}>{b}</li>)}
      </ul>
      {showMore && (
        <button className="pcard__more" onClick={() => setExpanded(!expanded)}>
          {expanded ? "Show less ↑" : `+ ${partner.bullets.length - 2} more details`}
        </button>
      )}
      {partner.note && (
        <p className="pcard__note">{partner.note}</p>
      )}
      <div className="pcard__bottom">
        {partner.code && (
          <div className="pcard__codebar">
            <div>
              <div className="pcard__codebar-label">{partner.code.label}</div>
              <div className="pcard__codebar-value">{partner.code.value}</div>
            </div>
            <button className={"pcard__codebar-copy" + (copied ? " copied" : "")} onClick={copyCode}>
              {copied ? <><Icon.Check /> Copied</> : <><Icon.Copy /> Copy</>}
            </button>
          </div>
        )}
        {partner.contact && (
          <div className="pcard__contact"><Icon.Mail /> {partner.contact}</div>
        )}
        {partner.cta ? (
          <a className="pcard__cta" href={partner.cta.href} target="_blank" rel="noreferrer">
            <span>{partner.cta.label}</span>
            <Icon.ArrowRight size={16} />
          </a>
        ) : (
          <a className="pcard__cta pcard__cta--ghost" href={partner.contact ? `mailto:${(partner.contact.match(/[\w.+-]+@[\w-]+\.[\w.-]+/)||[''])[0]}` : '#'}>
            <span>Get in touch</span>
            <Icon.ArrowRight size={16} />
          </a>
        )}
      </div>
    </article>
  );
}

// ============ INDEX ROW (list view) ============
function IndexRow({ partner, n }) {
  return (
    <div className="idx-row">
      <div className="idx-row__num">{String(n).padStart(2, '0')}</div>
      <div className="idx-row__logo">
        <PartnerLogo partner={partner} size={44} />
      </div>
      <div className="idx-row__name">{partner.name}</div>
      <div className="idx-row__headline">{partner.headline}</div>
      <div className="idx-row__tag">{partner.tag}</div>
      <a className="idx-row__cta" href={partner.cta?.href || '#'} target="_blank" rel="noreferrer">
        {partner.cta?.label || 'Details'} <Icon.ArrowRight />
      </a>
    </div>
  );
}

// ============ CATEGORY ============
function CategorySection({ category, filteredPartners, density }) {
  if (filteredPartners.length === 0) return null;
  return (
    <section className="category" id={`cat-${category.id}`}>
      <div className="category__head">
        <div className="category__tag">{category.tag} / 07</div>
        <h2 className="category__name">{category.name}</h2>
        <div className="category__path"></div>
        <div className="category__count">{filteredPartners.length} partner{filteredPartners.length > 1 ? 's' : ''}</div>
      </div>
      <div className={"category__cards" + (density === "dense" ? " dense" : "")}>
        {filteredPartners.map((p) => (
          <PartnerCard key={p.name} partner={p} density={density} />
        ))}
      </div>
    </section>
  );
}

// ============ FOOTER ============
function Footer() {
  return (
    <footer className="site-footer">
      <div className="site-footer__inner">
        <div>
          <h2>Need an intro? <span className="italic accent">We'll make it.</span></h2>
          <p>Partnerships listed here are negotiated by Z47 and DeVC on behalf of our portfolio. If a perk you need isn't listed, please do reach out and we will try add them to this list.</p>
          <a className="pcard__cta" href="#" style={{ background: 'var(--z47-orange)', maxWidth: 280 }}>
            <span>Request a new partner</span>
            <Icon.ArrowRight size={16} />
          </a>
        </div>
        <div className="site-footer__col">
          <h4>For founders</h4>
          <ul>
            <li>Rupali Sharma · Point of contact</li>
            <li>rupali@z47.com</li>
          </ul>
        </div>
        <div className="site-footer__col">
          <h4>Legal</h4>
          <ul>
            <li>Offers subject to partner terms</li>
            <li>Verify discount before contracting</li>
            <li>Updated quarterly</li>
          </ul>
        </div>
      </div>
      <div className="site-footer__bottom">
        <span className="site-footer__lockup"><img className="lockup__z47" src="brand/z47-logo-orange.svg" alt="Z47" /><span className="lockup__rule"></span><img className="lockup__devc" src="brand/devc-logo-knockout.svg" alt="DeVC" /><span className="site-footer__meta">Partnerships Playbook · July 2026</span></span>
        <span>Founder Vision. Nation Mission.</span>
      </div>
    </footer>
  );
}

// ============ TOAST ============
function Toast() {
  const [msg, setMsg] = useState(null);
  useEffect(() => {
    const handler = (e) => {
      setMsg(e.detail);
      setTimeout(() => setMsg(null), 1800);
    };
    window.addEventListener('z47-toast', handler);
    return () => window.removeEventListener('z47-toast', handler);
  }, []);
  return (
    <div className={"toast" + (msg ? " show" : "")}>
      <span className="toast__dot"></span>
      <span>{msg}</span>
    </div>
  );
}

// ============ TWEAKS ============
const TWEAK_DEFAULTS = /*EDITMODE-BEGIN*/{
  "density": "comfortable",
  "view": "grid",
  "accentSection": "none"
}/*EDITMODE-END*/;

function TweaksUI({ t, setTweak }) {
  return (
    <TweaksPanel title="Tweaks">
      <TweakSection title="Layout">
        <TweakRadio
          label="Card density"
          value={t.density}
          onChange={(v) => setTweak('density', v)}
          options={[
            { value: 'comfortable', label: 'Roomy' },
            { value: 'dense', label: 'Dense' },
          ]}
        />
        <TweakRadio
          label="Default view"
          value={t.view}
          onChange={(v) => setTweak('view', v)}
          options={[
            { value: 'grid', label: 'Grid' },
            { value: 'list', label: 'Index' },
          ]}
        />
      </TweakSection>
      <TweakSection title="Editorial accent">
        <TweakSelect
          label="Section accent bg"
          value={t.accentSection}
          onChange={(v) => setTweak('accentSection', v)}
          options={[
            { value: 'none', label: 'None — all white' },
            { value: 'cream', label: 'Alternate cream' },
            { value: 'mixed', label: 'Mixed (cream / blue / plum)' },
          ]}
        />
      </TweakSection>
    </TweaksPanel>
  );
}

// ============ APP ============
function App() {
  const data = window.PARTNERS_DATA;
  const [t, setTweak] = useTweaks(TWEAK_DEFAULTS);
  const [active, setActive] = useState("all");
  const [search, setSearch] = useState("");
  const [view, setView] = useState(t.view);

  useEffect(() => { setView(t.view); }, [t.view]);

  // Filter logic
  const filteredCategories = useMemo(() => {
    return data.categories.map((cat) => {
      let partners = cat.partners;
      if (active !== "all" && active !== cat.id) return { ...cat, partners: [] };
      if (search.trim()) {
        const q = search.toLowerCase();
        partners = partners.filter((p) =>
          p.name.toLowerCase().includes(q) ||
          p.headline.toLowerCase().includes(q) ||
          p.tag.toLowerCase().includes(q) ||
          p.bullets.some((b) => b.toLowerCase().includes(q))
        );
      }
      return { ...cat, partners };
    });
  }, [data, active, search]);

  const totalFiltered = filteredCategories.reduce((a, c) => a + c.partners.length, 0);

  // Section bg accents
  const accentBg = (i) => {
    if (t.accentSection === 'cream') return i % 2 === 1 ? 'var(--z47-cream)' : 'transparent';
    if (t.accentSection === 'mixed') {
      const bgs = ['transparent', 'var(--z47-cream)', 'transparent', 'var(--z47-light-blue)', 'transparent', 'var(--z47-light-plum)', 'transparent'];
      return bgs[i % bgs.length];
    }
    return 'transparent';
  };

  // Flat list (for list view)
  const flatPartners = filteredCategories.flatMap((c) => c.partners.map((p) => ({ ...p, _cat: c.name })));

  return (
    <>
      <Header />
      <div className="hero-wrap">
        <Hero data={data} />
      </div>
      <div className="toolbar-wrap">
        <Toolbar
          data={data}
          active={active} setActive={setActive}
          search={search} setSearch={setSearch}
          view={view} setView={setView}
        />
      </div>

      {totalFiltered === 0 && (
        <div className="empty">
          No partners match "{search}"
          <button onClick={() => { setSearch(""); setActive("all"); }}>Reset filters →</button>
        </div>
      )}

      {view === 'grid' && filteredCategories.map((c, i) => {
        const visibleIdx = filteredCategories.slice(0, i).filter((x) => x.partners.length > 0).length;
        const isDark = visibleIdx % 2 === 1;
        if (c.partners.length === 0) return null;
        return (
          <div key={c.id} className={"section-wrap" + (isDark ? " section-wrap--dark" : "")}>
            <CategorySection category={c} filteredPartners={c.partners} density={t.density} />
          </div>
        );
      })}

      {view === 'list' && totalFiltered > 0 && (
        <section style={{ maxWidth: 1440, margin: '0 auto', padding: '64px 56px' }}>
          <div className="idx-head">
            <div>#</div>
            <div></div>
            <div>Partner</div>
            <div>Offer</div>
            <div>Category</div>
            <div style={{ textAlign: 'right' }}>Action</div>
          </div>
          {flatPartners.map((p, i) => (
            <IndexRow key={p.name} partner={p} n={i + 1} />
          ))}
        </section>
      )}

      <Footer />
      <Toast />
      <TweaksUI t={t} setTweak={setTweak} />
    </>
  );
}

ReactDOM.createRoot(document.getElementById('root')).render(<App />);
