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

// ============================================================
// SVG ICONS — minimal stroke icons (Lucide-like, redrawn)
// ============================================================
const Icon = {
  Search: (p) => (<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.6" strokeLinecap="round" strokeLinejoin="round" {...p}><circle cx="11" cy="11" r="7"/><path d="M21 21l-4.3-4.3"/></svg>),
  Cart: (p) => (<svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.6" strokeLinecap="round" strokeLinejoin="round" {...p}><path d="M3 3h2l2.5 12.5a2 2 0 0 0 2 1.5h8.5a2 2 0 0 0 2-1.5L22 7H6"/><circle cx="9" cy="20" r="1.5"/><circle cx="18" cy="20" r="1.5"/></svg>),
  Heart: (p) => (<svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.6" strokeLinecap="round" strokeLinejoin="round" {...p}><path d="M20.8 4.6a5.5 5.5 0 0 0-7.8 0L12 5.6l-1-1a5.5 5.5 0 0 0-7.8 7.8l1 1L12 21.4l7.8-8 1-1a5.5 5.5 0 0 0 0-7.8z"/></svg>),
  Menu: (p) => (<svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.6" strokeLinecap="round" {...p}><path d="M4 7h16M4 12h16M4 17h16"/></svg>),
  X: (p) => (<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" {...p}><path d="M18 6L6 18M6 6l12 12"/></svg>),
  Plus: (p) => (<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" {...p}><path d="M12 5v14M5 12h14"/></svg>),
  Compare: (p) => (<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.6" strokeLinecap="round" strokeLinejoin="round" {...p}><rect x="3" y="5" width="7" height="14"/><rect x="14" y="5" width="7" height="14"/><path d="M10 9l4 0M10 15l4 0"/></svg>),
  Filter: (p) => (<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.6" strokeLinecap="round" strokeLinejoin="round" {...p}><path d="M3 5h18M6 12h12M10 19h4"/></svg>),
  Bookmark: (p) => (<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.6" strokeLinecap="round" strokeLinejoin="round" {...p}><path d="M19 21l-7-5-7 5V5a2 2 0 0 1 2-2h10a2 2 0 0 1 2 2z"/></svg>),
  Arrow: (p) => (<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.6" strokeLinecap="round" strokeLinejoin="round" {...p}><path d="M5 12h14M13 5l7 7-7 7"/></svg>),
  Check: (p) => (<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" {...p}><path d="M20 6L9 17l-5-5"/></svg>),
  Shield: (p) => (<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.6" strokeLinecap="round" strokeLinejoin="round" {...p}><path d="M12 2l9 4v6c0 5-3.6 9.4-9 10-5.4-.6-9-5-9-10V6l9-4z"/><path d="M9 12l2 2 4-4"/></svg>),
  Plane: (p) => (<svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.6" strokeLinecap="round" strokeLinejoin="round" {...p}><path d="M3 11l18-8-8 18-2-8-8-2z"/></svg>),
};

// ============================================================
// LOGO LOCKUP
// ============================================================
function Logo({ onClick }) {
  return (
    <div className="nav-brand" onClick={onClick}>
      <div className="nav-brand-mark">
        <img src="assets/indiepaper.png" alt="INDIE Paper logomark" />
      </div>
      <div className="nav-brand-text">
        <div className="wm">INDIE PAPER</div>
        <div className="sub">The right paper changes everything.</div>
      </div>
    </div>
  );
}

// ============================================================
// NAV
// ============================================================
function Nav({ route, navigate, cartCount = 0, compareCount = 0, onCartClick, authUser, authProfile, onAuthClick, onSignOut, onProfileClick }) {
  const [scrolled, setScrolled] = useState(false);
  const [searchOpen, setSearchOpen] = useState(false);
  const [searchQuery, setSearchQuery] = useState('');
  const [searchResults, setSearchResults] = useState([]);

  // Simple search function — runs against _INDIE_CATALOG in memory
  const runSearch = (q) => {
    setSearchQuery(q);
    if (!q || q.length < 2) { setSearchResults([]); return; }
    const catalog = window._INDIE_CATALOG || window.PAPERS || [];
    const ql = q.toLowerCase();
    const results = catalog.filter(p => {
      return (
        p.name.toLowerCase().includes(ql) ||
        (p.brand || '').toLowerCase().includes(ql) ||
        (p.finish || '').toLowerCase().includes(ql) ||
        (p.color || '').toLowerCase().includes(ql) ||
        (p.sku || '').toLowerCase().includes(ql) ||
        String(p.gsm || '').includes(q) ||
        (p.tags || []).some(t => t.toLowerCase().includes(ql))
      );
    }).slice(0, 8);
    setSearchResults(results);
  };

  const openSearch = () => { setSearchOpen(true); setTimeout(() => document.getElementById('ip-search-input')?.focus(), 50); };
  const closeSearch = () => { setSearchOpen(false); setSearchQuery(''); setSearchResults([]); };

  // Close on Escape
  useEffect(() => {
    const onKey = (e) => { if (e.key === 'Escape') closeSearch(); };
    window.addEventListener('keydown', onKey);
    return () => window.removeEventListener('keydown', onKey);
  }, []);

  useEffect(() => {
    const onKey = (e) => {
      if ((e.metaKey || e.ctrlKey) && e.key === 'k') {
        e.preventDefault();
        openSearch();
      }
    };
    window.addEventListener('keydown', onKey);
    return () => window.removeEventListener('keydown', onKey);
  }, []);

  useEffect(() => {
    const onScroll = () => setScrolled(window.scrollY > 8);
    window.addEventListener("scroll", onScroll);
    onScroll();
    return () => window.removeEventListener("scroll", onScroll);
  }, []);

  return (
    <nav className={"nav" + (scrolled ? " scrolled" : "")}>
      <div className="shell nav-inner">
        <Logo onClick={() => navigate("/gallery")} />
        <div className="nav-links">
          <a onClick={() => { navigate("/gallery"); window.scrollTo({top:0, behavior:'smooth'}); }}>Home</a>
          <a className={route === "/gallery" ? "is-active" : ""} onClick={() => { navigate("/gallery"); setTimeout(() => document.querySelector('.filter-bar')?.scrollIntoView({behavior:'smooth'}), 300); }}>Gallery</a>
          <a className={route === "/sample-request" ? "is-active" : ""} onClick={() => navigate("/sample-request")}>Sample Kit</a>
          <a className={route === "/about" ? "is-active" : ""} onClick={() => navigate("/about")}>About</a>
          <a className={route === "/contact" ? "is-active" : ""} onClick={() => navigate("/contact")}>Contact</a>
          <a onClick={() => window.open("https://pixelindie.com", "_blank")}>PixelIndie ↗</a>
        </div>
        <div className="nav-spacer" />
        <div className="nav-actions">
          <div className="nav-search" onClick={openSearch}>
            <Icon.Search />
            <span>Cari kertas, brand, gsm…</span>
            <span className="mono" style={{marginLeft: "auto", fontSize: 10, color: "var(--ink-faint)"}}>⌘K</span>
          </div>
          <button className="nav-icon-btn" title="Compare">
            <Icon.Compare />
            {compareCount > 0 && <span className="pill-count">{compareCount}</span>}
          </button>
          <button className="nav-icon-btn" title="Cart" onClick={onCartClick}>
            <Icon.Cart />
            {cartCount > 0 && <span className="pill-count">{cartCount}</span>}
          </button>
          {authUser ? (
            <div className="nav-auth-user nav-auth-dropdown" title={authProfile?.full_name || authUser.email}>
              <button className="nav-auth-trigger">
                <span className="nav-auth-name">{authProfile?.full_name?.split(' ')[0] || 'Akun'}</span>
                <span style={{fontSize:10, color:'var(--ink-meta)'}}>▾</span>
              </button>
              <div className="nav-auth-menu">
                <a className="nav-auth-menu-item" onClick={onProfileClick}>👤 Profil saya</a>
                <a className="nav-auth-menu-item" onClick={() => onProfileClick('orders')}>📦 Riwayat Order</a>
                <div className="nav-auth-menu-divider" />
                <a className="nav-auth-menu-item nav-auth-menu-item--danger" onClick={onSignOut}>↩ Sign out</a>
              </div>
            </div>
          ) : (
            <button className="nav-auth-btn" onClick={onAuthClick}>Masuk</button>
          )}
          <button className="nav-icon-btn nav-burger" title="Menu">
            <Icon.Menu />
          </button>
        </div>
      </div>
      {searchOpen && (
        <div className="search-overlay" onClick={closeSearch}>
          <div className="search-box" onClick={e => e.stopPropagation()}>
            <div className="search-input-row">
              <Icon.Search style={{flexShrink:0, color:'var(--ink-meta)'}} />
              <input
                id="ip-search-input"
                type="text"
                placeholder="Cari kertas, brand, gsm, finish…"
                value={searchQuery}
                onChange={e => runSearch(e.target.value)}
                autoComplete="off"
                style={{flex:1, border:'none', outline:'none', fontSize:16, fontFamily:'var(--font-sans)', background:'transparent', color:'var(--ink)'}}
              />
              {searchQuery && (
                <button onClick={() => runSearch('')} style={{background:'none', border:'none', cursor:'pointer', color:'var(--ink-meta)', display:'grid', placeItems:'center'}}>
                  <Icon.X />
                </button>
              )}
              <span className="mono" style={{fontSize:11, color:'var(--ink-faint)', flexShrink:0}}>ESC</span>
            </div>

            {searchQuery.length >= 2 && (
              <div className="search-results">
                {searchResults.length === 0 ? (
                  <div className="search-empty">
                    Tidak ada kertas yang cocok untuk <em>"{searchQuery}"</em>
                  </div>
                ) : (
                  <>
                    <div className="search-count">{searchResults.length} hasil</div>
                    {searchResults.map(p => {
                      const gsmKeys = Object.keys(p.price || {}).filter(k => k !== 'default').sort((a,b)=>parseInt(a)-parseInt(b));
                      return (
                        <div key={p.id} className="search-result-item" onClick={() => { navigate('/product/' + p.id); closeSearch(); }}>
                          <div className="sri-swatch" style={{background: p.swatchTone || '#F4EFE3'}} />
                          <div className="sri-info">
                            <div className="sri-name">{p.name}</div>
                            <div className="sri-meta">
                              {p.brand && <span>{p.brand}</span>}
                              {p.origin && <span>· {p.origin}</span>}
                              {gsmKeys.length > 0 && <span>· {gsmKeys.map(k=>k+'gsm').join(', ')}</span>}
                              <span>· {p.finish}</span>
                            </div>
                          </div>
                          <div className="sri-price mono">
                            {p.price_min > 0 ? 'Rp ' + p.price_min.toLocaleString('id-ID') : '—'}
                          </div>
                        </div>
                      );
                    })}
                    {(window._INDIE_CATALOG || []).filter(p => {
                      const ql = searchQuery.toLowerCase();
                      return p.name.toLowerCase().includes(ql) || (p.brand||'').toLowerCase().includes(ql);
                    }).length > 8 && (
                      <div className="search-more" onClick={() => {
                        closeSearch();
                        // TODO: navigate to gallery with search query
                      }}>
                        Lihat semua hasil →
                      </div>
                    )}
                  </>
                )}
              </div>
            )}

            {!searchQuery && (
              <div className="search-hints">
                <div className="sh-label">Coba cari:</div>
                {['Mohawk', 'Fedrigoni', '176gsm', 'Uncoated', 'Felt'].map(hint => (
                  <button key={hint} className="sh-chip" onClick={() => runSearch(hint)}>{hint}</button>
                ))}
              </div>
            )}
          </div>
        </div>
      )}
    </nav>
  );
}

// ============================================================
// BRAND STAMP — small circular brand badge
// ============================================================
function BrandStamp({ brand, tier }) {
  const cls =
    brand === "Fedrigoni" ? "fedrigoni" :
    brand === "Superb Bamboo" ? "bamboo" :
    brand === "Gmund" ? "gmund" :
    "local";
  const initial =
    brand === "Fedrigoni" ? "F" :
    brand === "Superb Bamboo" ? "竹" :
    brand === "Gmund" ? "G" :
    brand === "Arjowiggins" ? "A" :
    "L";
  return (
    <span className={"brand-stamp " + cls} title={brand}>
      <span className="dot">{initial}</span>
      {brand}
    </span>
  );
}

// ============================================================
// PAPER SWATCH — visual placeholder with paper-like texture
// drops to image-slot when user fills
// ============================================================
function Swatch({ paper, slotId, children }) {
  // Render as CSS-generated paper texture by default — terra-cotta, ivory, kraft tones.
  // `image-slot` element underneath will accept user drops later.
  return (
    <div className="swatch" style={{ "--tone": paper.swatchTone }}>
      <PaperTexture tone={paper.swatchTone} grain={paper.grain} />
      <image-slot
        id={slotId}
        placeholder={`${paper.brand} — ${paper.name} swatch`}
        shape="rect"
        style={{ position: "absolute", inset: 0, opacity: 0.0 }}
      />
      {children}
    </div>
  );
}

// CSS-generated paper texture using layered radial gradients + SVG noise
function PaperTexture({ tone, grain }) {
  // Determine grain pattern via SVG turbulence baseFreq
  const baseFreq = {
    smooth:    "0.65",
    felt:      "0.85",
    fiber:     "1.2",
    cotton:    "0.95",
    laid:      "0.55",
    kraft:     "1.4",
    embossed:  "0.4",
    tradition: "0.75",
  }[grain] || "0.85";

  const id = useMemo(() => "ptx-" + Math.random().toString(36).slice(2, 9), []);

  // For dark papers (black), invert noise feel
  const isDark = tone === "#1A1A18";
  const noiseOpacity = isDark ? 0.18 : 0.32;

  return (
    <div style={{
      position: "absolute", inset: 0,
      background: `linear-gradient(135deg, ${tone} 0%, ${shade(tone, -6)} 100%)`,
      overflow: "hidden",
    }}>
      <svg width="100%" height="100%" style={{position:"absolute", inset:0, opacity: noiseOpacity, mixBlendMode: isDark ? "screen" : "multiply"}}>
        <filter id={id}>
          <feTurbulence type="fractalNoise" baseFrequency={baseFreq} numOctaves="2" seed="3" />
          <feColorMatrix values={isDark ? "0 0 0 0 0.9 0 0 0 0 0.9 0 0 0 0 0.9 0 0 0 1 0" : "0 0 0 0 0.2 0 0 0 0 0.18 0 0 0 0 0.15 0 0 0 1 0"} />
        </filter>
        <rect width="100%" height="100%" filter={`url(#${id})`} />
      </svg>
      {/* embossed/laid lines for laid finish */}
      {grain === "laid" && (
        <div style={{
          position:"absolute", inset:0,
          backgroundImage: `repeating-linear-gradient(0deg, transparent 0, transparent 6px, rgba(0,0,0,0.04) 6px, rgba(0,0,0,0.04) 7px)`,
        }} />
      )}
      {/* deckled edge (top-left corner peel) */}
      <svg style={{position:"absolute", top:0, left:0, width:40, height:40, opacity:0.18}} viewBox="0 0 40 40">
        <path d="M0 12 Q 5 11 8 6 T 14 0" stroke="rgba(0,0,0,0.4)" strokeWidth="0.5" fill="none" />
      </svg>
    </div>
  );
}

// shade utility — darken a hex by N%
function shade(hex, percent) {
  const h = hex.replace("#", "");
  const num = parseInt(h, 16);
  let r = (num >> 16) + Math.round(255 * percent / 100);
  let g = ((num >> 8) & 0xff) + Math.round(255 * percent / 100);
  let b = (num & 0xff) + Math.round(255 * percent / 100);
  r = Math.max(0, Math.min(255, r));
  g = Math.max(0, Math.min(255, g));
  b = Math.max(0, Math.min(255, b));
  return "#" + ((r << 16) | (g << 8) | b).toString(16).padStart(6, "0");
}

// ============================================================
// PAPER CARD
// ============================================================
function PaperCard({ paper, onOpen, onAddCart, onToggleCompare, isComparing, onRequestSample }) {
  const gsmOptions = Object.keys(paper.price || {}).filter(k => k !== 'default').sort((a,b) => parseInt(a)-parseInt(b));
  const [selectedGsm, setSelectedGsm] = useState(gsmOptions.length === 1 ? gsmOptions[0] : null);
  const unitPrice = selectedGsm ? (paper.price[selectedGsm] || paper.price_min || 0) : (paper.price_min || 0);
  const hasVariants = gsmOptions.length > 1;
  return (
    <article className="paper-card fade-in" onClick={() => onOpen?.(paper)}>
      <Swatch paper={paper} slotId={`sw-${paper.id}`}>
        <div className="badges-tl">
          {paper.eco && <span className="badge badge-eco">Eco · FSC</span>}
          {paper.brandTier === "premium" && !paper.eco && <span className="badge badge-premium">Premium</span>}
          {paper.featured && <span className="badge badge-new">Editor's pick</span>}
        </div>
        <button
          className={"compare-btn" + (isComparing ? " is-active" : "")}
          onClick={(e) => { e.stopPropagation(); onToggleCompare?.(paper); }}
          title="Add to compare"
        >
          {isComparing ? <Icon.Check /> : <Icon.Plus />}
        </button>

        <div className="swatch-overlay">
          <dl className="qspec">
            <dt>Grain</dt><dd className="serif">{paper.grain}</dd>
            <dt>Color</dt><dd>{paper.color}</dd>
            <dt>Origin</dt><dd>{paper.origin}</dd>
            <dt>MOQ</dt><dd>{paper.moq} sheets</dd>
          </dl>
        </div>
      </Swatch>

      <div className="body">
        <div className="pc-brand">
          <span className="brand-name">{paper.brand}</span>
          <span className="mono" style={{fontSize:11, color:"var(--ink-faint)"}}>{paper.origin}</span>
        </div>
        <h3 className="pc-name">{paper.name}</h3>
        <div className="pc-specs">
          <span>A3+</span>
          <span>· {paper.finish}</span>
        </div>
        {hasVariants && (
          <div className="pc-gsm-selector" onClick={e => e.stopPropagation()}>
            {gsmOptions.map(g => (
              <button
                key={g}
                className={"pc-gsm-btn" + (selectedGsm === g ? " is-active" : "")}
                onClick={() => setSelectedGsm(g)}
              >{g}</button>
            ))}
          </div>
        )}
        <div className="pc-foot">
          <div className="pc-price">
            <span className="label">A3+ · from / sheet</span>
            <span className="val">
              {selectedGsm
                ? <>Rp {unitPrice.toLocaleString("id-ID")}<span className="mono" style={{fontSize:10, fontWeight:400, marginLeft:4, color:"var(--ink-meta)"}}>{selectedGsm}gsm</span></>
                : <>from Rp {(paper.price_min || 0).toLocaleString("id-ID")}</>
              }
            </span>
          </div>
          <div className="pc-icon-actions" onClick={(e) => e.stopPropagation()}>
            <button
              className="pc-icon-btn"
              title="Request Sample"
              onClick={() => onRequestSample?.(paper)}
            ><Icon.Bookmark /></button>
            <button
              className={"pc-icon-btn pc-icon-btn--primary" + (hasVariants && !selectedGsm ? " is-disabled" : "")}
              title={hasVariants && !selectedGsm ? "Pilih gramatur dulu" : "Add to Cart"}
              disabled={hasVariants && !selectedGsm}
              onClick={() => {
                if (hasVariants && !selectedGsm) return;
                onAddCart?.(paper, { format: selectedGsm || 'default', qty: paper.moq || 10 });
              }}
            ><Icon.Cart style={{width:14,height:14}} /></button>
          </div>
        </div>
      </div>
    </article>
  );
}

// ============================================================
// FOOTER
// ============================================================
function Footer({ navigate }) {
  return (
    <footer className="footer">
      <div className="shell">
        <div className="footer-inner">
          <div className="brand-block">
            <div className="wm">INDIE PAPER</div>
            <p>Specialty paper gallery di Jakarta. Bagian dari PT. Indie Kreasi Media — sister company PixelIndie Print Shop.</p>
            <div className="jp-tag">ペーパー · Sejak 2026</div>
          </div>
          <div>
            <h5>Gallery</h5>
            <ul>
              <li><a onClick={() => navigate("/gallery")}>All papers</a></li>
              <li><a onClick={() => navigate("/gallery?cat=eco")}>Eco papers</a></li>
              <li><a onClick={() => navigate("/gallery?brand=Fedrigoni")}>Fedrigoni</a></li>
              <li><a onClick={() => navigate("/gallery?cat=textured")}>Textured</a></li>
            </ul>
          </div>
          <div>
            <h5>Help</h5>
            <ul>
              <li><a onClick={() => navigate("/sample-request")}>Request sample kit</a></li>
              <li><a>Cara order</a></li>
              <li><a>Custom cut</a></li>
              <li><a>Shipping & lead time</a></li>
            </ul>
          </div>
          <div>
            <h5>INDIE Group</h5>
            <ul>
              <li><a>About PT. Indie Kreasi Media</a></li>
              <li><a>PixelIndie Print Shop ↗</a></li>
              <li><a>INDIE Pack ↗</a></li>
              <li><a>Hubungi kami</a></li>
            </ul>
          </div>
        </div>
        <div className="footer-foot">
          <div>© 2026 PT. Indie Kreasi Media. Jakarta, Indonesia.</div>
          <div className="sib">
            <a>Privacy</a>
            <a>Terms</a>
            <a>IG · @indiepaper</a>
          </div>
        </div>
      </div>
    </footer>
  );
}

// expose
Object.assign(window, {
  React, Icon, Logo, Nav, Footer,
  BrandStamp, Swatch, PaperTexture, PaperCard, shade,
});
