// components.jsx — shared UI primitives for Elektrobee Vending

// ─────────────────────────────────────────────────────────────
// Icon system — minimal stroke icons drawn inline
// ─────────────────────────────────────────────────────────────
const Icon = ({ name, size = 20, color = 'currentColor', stroke = 1.75 }) => {
  const props = {
    width: size, height: size, viewBox: '0 0 24 24', fill: 'none',
    stroke: color, strokeWidth: stroke, strokeLinecap: 'round', strokeLinejoin: 'round',
  };
  switch (name) {
    case 'qr':
      return (<svg {...props}>
        <rect x="3" y="3" width="7" height="7" rx="1"/>
        <rect x="14" y="3" width="7" height="7" rx="1"/>
        <rect x="3" y="14" width="7" height="7" rx="1"/>
        <path d="M14 14h3v3M21 14v3M14 18v3h3M21 18v3"/>
      </svg>);
    case 'back':
      return (<svg {...props}><path d="M15 6l-6 6 6 6"/></svg>);
    case 'close':
      return (<svg {...props}><path d="M6 6l12 12M18 6l-6 6-6 6"/></svg>);
    case 'search':
      return (<svg {...props}><circle cx="11" cy="11" r="7"/><path d="M21 21l-4.3-4.3"/></svg>);
    case 'cart':
      return (<svg {...props}>
        <path d="M3 4h2l2.6 11.2a2 2 0 002 1.6h8.2a2 2 0 002-1.6L21 8H6"/>
        <circle cx="9" cy="20" r="1.4"/>
        <circle cx="17" cy="20" r="1.4"/>
      </svg>);
    case 'menu':
      return (<svg {...props}><path d="M4 7h16M4 12h16M4 17h16"/></svg>);
    case 'user':
      return (<svg {...props}><circle cx="12" cy="8" r="4"/><path d="M4 21c0-4.4 3.6-8 8-8s8 3.6 8 8"/></svg>);
    case 'check':
      return (<svg {...props}><path d="M4 12l5 5L20 6"/></svg>);
    case 'plus':
      return (<svg {...props}><path d="M12 5v14M5 12h14"/></svg>);
    case 'minus':
      return (<svg {...props}><path d="M5 12h14"/></svg>);
    case 'chevron':
      return (<svg {...props}><path d="M9 6l6 6-6 6"/></svg>);
    case 'chevron-down':
      return (<svg {...props}><path d="M6 9l6 6 6-6"/></svg>);
    case 'clock':
      return (<svg {...props}><circle cx="12" cy="12" r="9"/><path d="M12 7v5l3 2"/></svg>);
    case 'pin':
      return (<svg {...props}><path d="M12 22s8-7 8-13a8 8 0 10-16 0c0 6 8 13 8 13z"/><circle cx="12" cy="9" r="2.5"/></svg>);
    case 'ticket':
      return (<svg {...props}><path d="M3 9a2 2 0 012-2h14a2 2 0 012 2v2a2 2 0 100 4v2a2 2 0 01-2 2H5a2 2 0 01-2-2v-2a2 2 0 100-4V9z"/><path d="M13 7v2M13 11v2M13 15v2"/></svg>);
    case 'bell':
      return (<svg {...props}><path d="M6 8a6 6 0 1112 0c0 7 3 8 3 8H3s3-1 3-8"/><path d="M10 21h4"/></svg>);
    case 'flash':
      return (<svg {...props}><path d="M13 2L4 14h7l-1 8 9-12h-7l1-8z"/></svg>);
    case 'shield':
      return (<svg {...props}><path d="M12 2l8 4v6c0 5-3.5 9-8 10-4.5-1-8-5-8-10V6l8-4z"/><path d="M9 12l2 2 4-4"/></svg>);
    case 'lock':
      return (<svg {...props}><rect x="5" y="11" width="14" height="10" rx="2"/><path d="M8 11V7a4 4 0 018 0v4"/></svg>);
    case 'info':
      return (<svg {...props}><circle cx="12" cy="12" r="9"/><path d="M12 8v.01M11 12h1v5h1"/></svg>);
    case 'package':
      return (<svg {...props}><path d="M3 7l9-4 9 4-9 4-9-4z"/><path d="M3 7v10l9 4 9-4V7"/><path d="M12 11v10"/></svg>);
    case 'sparkle':
      return (<svg {...props}><path d="M12 3v6M12 15v6M3 12h6M15 12h6M5.6 5.6l4.2 4.2M14.2 14.2l4.2 4.2M18.4 5.6l-4.2 4.2M9.8 14.2l-4.2 4.2"/></svg>);
    case 'phone':
      return (<svg {...props}><path d="M5 4a2 2 0 012-2h2l2 5-2 1c1 2 3 4 5 5l1-2 5 2v2a2 2 0 01-2 2C8 17 3 12 3 4z"/></svg>);
    case 'pill':
      return (<svg {...props}><rect x="3" y="9" width="18" height="6" rx="3" transform="rotate(-45 12 12)"/><path d="M8 8l8 8"/></svg>);
    case 'cup':
      return (<svg {...props}><path d="M5 6h12v8a4 4 0 01-4 4H9a4 4 0 01-4-4V6z"/><path d="M17 8h2a2 2 0 010 4h-2M7 2v3M11 2v3"/></svg>);
    case 'help':
      return (<svg {...props}><circle cx="12" cy="12" r="9"/><path d="M9.5 9a2.5 2.5 0 015 0c0 2-2.5 2-2.5 4M12 17v.01"/></svg>);
    case 'refresh':
      return (<svg {...props}><path d="M21 12a9 9 0 11-3-6.7L21 8M21 3v5h-5"/></svg>);
    case 'arrow-right':
      return (<svg {...props}><path d="M5 12h14M13 6l6 6-6 6"/></svg>);
    case 'arrow-down':
      return (<svg {...props}><path d="M12 5v14M6 13l6 6 6-6"/></svg>);
    case 'card':
      return (<svg {...props}><rect x="3" y="6" width="18" height="13" rx="2"/><path d="M3 10h18M7 15h3"/></svg>);
    case 'sort':
      return (<svg {...props}><path d="M7 3v18M3 7l4-4 4 4M17 21V3M21 17l-4 4-4-4"/></svg>);
    case 'mail':
      return (<svg {...props}><rect x="3" y="5" width="18" height="14" rx="2"/><path d="M3 7l9 6 9-6"/></svg>);
    case 'home-tab':
      return (<svg {...props}><path d="M3 11l9-7 9 7v9a2 2 0 01-2 2h-4v-7h-6v7H5a2 2 0 01-2-2v-9z"/></svg>);
    case 'receipt':
      return (<svg {...props}><path d="M5 3v18l2-1.5L9 21l2-1.5L13 21l2-1.5L17 21l2-1.5V3l-2 1.5L15 3l-2 1.5L11 3 9 4.5 7 3 5 4.5z"/><path d="M8 9h8M8 13h8M8 17h5"/></svg>);
    default: return null;
  }
};

// ─────────────────────────────────────────────────────────────
// Logo mark — small navy block with amber bee accent
// ─────────────────────────────────────────────────────────────
const EbLogo = ({ size = 28, withText = false, light = false }) => {
  const b = (typeof window !== 'undefined' && window.BRAND) || {};
  const letter = b.logoLetter || 'E';
  const name = b.name || 'Elektrobee';
  return (
  <span className="eb-logo" style={{ fontSize: size * 0.55, color: light ? '#fff' : 'var(--eb-navy)' }}>
    <span className="eb-logo-mark" style={{
      width: size, height: size, fontSize: size * 0.55,
      background: light ? 'var(--eb-amber)' : 'var(--eb-navy)',
      color: light ? 'var(--eb-navy)' : 'var(--eb-amber)',
    }}>
      <span style={{ fontFamily: 'IBM Plex Mono', fontWeight: 700 }}>{letter}</span>
    </span>
    {withText && <span>{name}</span>}
  </span>
  );
};

// ─────────────────────────────────────────────────────────────
// Stock badge
// ─────────────────────────────────────────────────────────────
const StockBadge = ({ stock }) => {
  if (stock === 0) return <span className="pill pill-stock-out">Habis</span>;
  if (stock <= 5) return <span className="pill pill-stock-low">Tinggal {stock}</span>;
  return <span className="pill pill-stock-ok">Stok {stock}+</span>;
};

// ─────────────────────────────────────────────────────────────
// Product thumbnail — color-blocked initials placeholder, OR
// real image when product.image is set, OR drag-target image-slot
// when allowDrop (or window.__EB_ALLOW_PRODUCT_DROP) is on.
// ─────────────────────────────────────────────────────────────
const ProductThumb = ({ product, size = null, allowDrop = false }) => {
  const sizeStyle = size ? { width: size, height: size, aspectRatio: 'auto', flexShrink: 0 } : null;
  const drop = allowDrop || window.__EB_ALLOW_PRODUCT_DROP;

  // 1) Real image set on product — render <img>
  if (product.image) {
    return (
      <div className="product-thumb" style={sizeStyle}>
        <img src={product.image} alt={product.name} style={{
          width: '100%', height: '100%', objectFit: 'cover', display: 'block',
        }} onError={(e) => {
          // Hide image on load failure; show fallback by removing src
          e.target.style.display = 'none';
        }} />
        {product.isAdult && (
          <span className="pill pill-21" style={{
            position: 'absolute', top: 6, left: 6, fontSize: 9, padding: '2px 6px',
          }}>21+</span>
        )}
      </div>
    );
  }

  // 2) Drop target — drag your own image into this slot
  if (drop) {
    return (
      <div className="product-thumb" style={{ ...sizeStyle, padding: 0 }}>
        <image-slot
          id={`prod-${product.id}`}
          shape="rounded"
          radius="10"
          placeholder={product.name}
          style={{ width: '100%', height: '100%', display: 'block', borderRadius: 10 }}
        ></image-slot>
        {product.isAdult && (
          <span className="pill pill-21" style={{
            position: 'absolute', top: 6, left: 6, fontSize: 9, padding: '2px 6px', zIndex: 2,
          }}>21+</span>
        )}
      </div>
    );
  }

  // 3) Default — colored swatch with initials
  return (
    <div className="product-thumb" style={sizeStyle}>
      <div style={{
        position: 'absolute', inset: 0,
        background: `linear-gradient(135deg, ${product.swatch}22 0%, ${product.swatch}11 100%)`,
      }} />
      <div style={{
        width: '62%', aspectRatio: '1 / 1.2', borderRadius: 6,
        background: `linear-gradient(180deg, ${product.swatch} 0%, ${product.swatch}cc 100%)`,
        display: 'flex', alignItems: 'center', justifyContent: 'center',
        color: '#fff', fontFamily: 'IBM Plex Mono', fontWeight: 700,
        fontSize: size ? size * 0.22 : 18, letterSpacing: '-0.02em',
        boxShadow: '0 4px 12px rgba(0,0,0,0.15), inset 0 1px 0 rgba(255,255,255,0.25)',
      }}>{product.initials}</div>
      {product.isAdult && (
        <span className="pill pill-21" style={{
          position: 'absolute', top: 6, left: 6, fontSize: 9, padding: '2px 6px',
        }}>21+</span>
      )}
    </div>
  );
};

// ─────────────────────────────────────────────────────────────
// Product card (grid)
// ─────────────────────────────────────────────────────────────
const ProductCard = ({ product, onTap, inCart = 0 }) => {
  const out = product.stock === 0;
  return (
    <button className="product-card" data-out={out} onClick={() => !out && onTap(product)}>
      <ProductThumb product={product} />
      <div style={{ display: 'flex', flexDirection: 'column', gap: 3, minWidth: 0 }}>
        <div className="product-name">{product.name}</div>
        <div className="product-meta">{product.brand} · {product.unit}</div>
      </div>
      <div className="product-price-row">
        <span className="price">{fmtRp(product.price)}</span>
        <StockBadge stock={product.stock} />
      </div>
      {inCart > 0 && (
        <div style={{
          position: 'absolute', top: 8, right: 8,
          width: 22, height: 22, borderRadius: 11,
          background: 'var(--eb-amber)', color: 'var(--eb-navy)',
          display: 'flex', alignItems: 'center', justifyContent: 'center',
          fontFamily: 'IBM Plex Mono', fontWeight: 700, fontSize: 11,
          boxShadow: '0 2px 6px rgba(var(--eb-amber-strong-rgb), 0.4)',
        }}>{inCart}</div>
      )}
    </button>
  );
};

// ─────────────────────────────────────────────────────────────
// SpinnerIcon — circular spinner mechanism with N product wedges,
// optionally with one wedge highlighted as active (dispensing).
// ─────────────────────────────────────────────────────────────
const SpinnerIcon = ({ slots = 8, activeSlot = null, size = 30, dispenseWedgeColor = null }) => {
  const r = size / 2;
  const inner = r * 0.55;
  // angle math: top is the dispense slot (-90°). Wedge angle spans the arc.
  const wedgeAngle = 360 / slots;
  return (
    <svg width={size} height={size} viewBox={`0 0 ${size} ${size}`} style={{ display: 'block' }}>
      <defs>
        <radialGradient id={`spinBg-${size}`} cx="0.5" cy="0.5" r="0.5">
          <stop offset="0%" stopColor="currentColor" stopOpacity="0.05"/>
          <stop offset="100%" stopColor="currentColor" stopOpacity="0.2"/>
        </radialGradient>
      </defs>
      {/* outer ring */}
      <circle cx={r} cy={r} r={r - 1} fill={`url(#spinBg-${size})`} stroke="currentColor" strokeWidth="0.8" strokeOpacity="0.3"/>
      {/* wedge separators */}
      {Array.from({ length: slots }).map((_, i) => {
        const a = (i * wedgeAngle - 90) * Math.PI / 180;
        const x1 = r + Math.cos(a) * inner;
        const y1 = r + Math.sin(a) * inner;
        const x2 = r + Math.cos(a) * (r - 2);
        const y2 = r + Math.sin(a) * (r - 2);
        return (
          <line key={i} x1={x1} y1={y1} x2={x2} y2={y2}
            stroke="currentColor" strokeWidth="0.6" strokeOpacity="0.25" />
        );
      })}
      {/* dispense slot indicator (top) */}
      <path
        d={`M ${r} 1 L ${r - 3} 5 L ${r + 3} 5 Z`}
        fill="currentColor" opacity="0.6"
      />
      {/* active wedge highlight */}
      {activeSlot != null && (() => {
        const startA = (activeSlot * wedgeAngle - 90 - wedgeAngle / 2) * Math.PI / 180;
        const endA   = (activeSlot * wedgeAngle - 90 + wedgeAngle / 2) * Math.PI / 180;
        const x1 = r + Math.cos(startA) * (r - 2);
        const y1 = r + Math.sin(startA) * (r - 2);
        const x2 = r + Math.cos(endA) * (r - 2);
        const y2 = r + Math.sin(endA) * (r - 2);
        const largeArc = wedgeAngle > 180 ? 1 : 0;
        return (
          <path
            d={`M ${r} ${r} L ${x1} ${y1} A ${r - 2} ${r - 2} 0 ${largeArc} 1 ${x2} ${y2} Z`}
            fill={dispenseWedgeColor || 'var(--eb-amber)'}
            opacity="0.85"
          />
        );
      })()}
      {/* center hub */}
      <circle cx={r} cy={r} r={inner * 0.6} fill="currentColor" opacity="0.18" />
      <circle cx={r} cy={r} r={inner * 0.25} fill="currentColor" opacity="0.4" />
    </svg>
  );
};

// ─────────────────────────────────────────────────────────────
// MachineWall — small horizontal indicator showing "you're at
// machine N of M in this wall". Optional, non-interactive by default.
// ─────────────────────────────────────────────────────────────
const MachineWall = ({ position, total, onTapOther }) => (
  <div className="machine-wall">
    {Array.from({ length: total }).map((_, i) => {
      const here = (i + 1) === position;
      return (
        <button key={i} className="machine-wall-unit" data-active={here}
          onClick={() => !here && onTapOther && onTapOther(i + 1)}
          aria-label={here ? `Mesin ${i + 1} (di sini)` : `Mesin ${i + 1}`}>
          <SpinnerIcon size={18} slots={8} />
          <span className="machine-wall-num">{i + 1}</span>
        </button>
      );
    })}
  </div>
);

// (ClusterWall removed — old wall-of-cubes UI replaced by MachineWall
// since each Elektrobee unit is now a standalone spinner machine.)


// ─────────────────────────────────────────────────────────────
// Bottom sheet
// ─────────────────────────────────────────────────────────────
const BottomSheet = ({ open, onClose, children, maxHeight = '88%' }) => {
  if (!open) return null;
  return (
    <>
      <div className="sheet-backdrop" onClick={onClose} />
      <div className="sheet" style={{ maxHeight }}>
        <div className="sheet-handle" />
        {children}
      </div>
    </>
  );
};

// ─────────────────────────────────────────────────────────────
// Topbar
// ─────────────────────────────────────────────────────────────
const Topbar = ({ title, sub, onBack, right, transparent = false }) => (
  <div className="topbar" style={transparent ? { background: 'transparent' } : null}>
    <div style={{ display: 'flex', alignItems: 'center', gap: 10, minWidth: 0, flex: 1 }}>
      {onBack && (
        <button className="icon-btn ghost" onClick={onBack} style={{ flexShrink: 0 }}>
          <Icon name="back" size={20} />
        </button>
      )}
      <div style={{ minWidth: 0, flex: 1 }}>
        <div className="topbar-title" style={{
          overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap',
        }}>{title}</div>
        {sub && <div className="topbar-sub" style={{
          overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap',
        }}>{sub}</div>}
      </div>
    </div>
    {right}
  </div>
);

// ─────────────────────────────────────────────────────────────
// QR mock — stylized QR using SVG noise (just for visual)
// ─────────────────────────────────────────────────────────────
const QrMock = ({ size = 200, seed = 0 }) => {
  const cells = 25;
  // Deterministic pseudo-random pattern
  const isOn = (x, y) => {
    const n = (x * 73856093) ^ (y * 19349663) ^ (seed * 83492791);
    return ((n >>> 0) % 7) < 3;
  };
  const cs = size / cells;
  const finders = [[0, 0], [0, cells - 7], [cells - 7, 0]];
  const inFinder = (x, y) => finders.some(([fx, fy]) => x >= fx && x < fx + 7 && y >= fy && y < fy + 7);
  return (
    <svg width={size} height={size} viewBox={`0 0 ${cells} ${cells}`} style={{ display: 'block' }}>
      {Array.from({ length: cells }).map((_, y) =>
        Array.from({ length: cells }).map((_, x) => {
          if (inFinder(x, y)) return null;
          return isOn(x, y) ? <rect key={`${x}-${y}`} x={x} y={y} width="1" height="1" fill="#0F1729" /> : null;
        })
      )}
      {finders.map(([fx, fy], i) => (
        <g key={i}>
          <rect x={fx} y={fy} width="7" height="7" fill="#0F1729" />
          <rect x={fx + 1} y={fy + 1} width="5" height="5" fill="#fff" />
          <rect x={fx + 2} y={fy + 2} width="3" height="3" fill="#0F1729" />
        </g>
      ))}
      {/* center logo */}
      <rect x={cells/2 - 2.5} y={cells/2 - 2.5} width="5" height="5" fill="#fff" />
      <rect x={cells/2 - 1.5} y={cells/2 - 1.5} width="3" height="3" fill="#042147" rx="0.4" />
    </svg>
  );
};

// ─────────────────────────────────────────────────────────────
// Format helper for mm:ss
// ─────────────────────────────────────────────────────────────
const mmss = (sec) => {
  if (sec < 0) sec = 0;
  const m = Math.floor(sec / 60);
  const s = sec % 60;
  return `${m}:${String(s).padStart(2, '0')}`;
};

// ─────────────────────────────────────────────────────────────
// NavBar — bottom tab bar with center elevated Scan FAB
// Shown only on tab-root screens (home/riwayat/voucher/akun).
// ─────────────────────────────────────────────────────────────
const NavBar = ({ current, voucherCount = 0, onTab, onScan }) => {
  const tabs = [
    { id: 'home',     label: 'Beranda', icon: 'home-tab' },
    { id: 'cari',     label: 'Cari',    icon: 'search' },
    { id: 'voucher',  label: 'Voucher', icon: 'ticket', badge: voucherCount },
    { id: 'akun',     label: 'Akun',    icon: 'user' },
  ];
  // Insert FAB in the middle — between index 1 and 2
  return (
    <div className="navbar">
      <div className="navbar-inner">
        {tabs.slice(0, 2).map(t => <NavTab key={t.id} t={t} active={current === t.id} onClick={() => onTab(t.id)} />)}
        <div className="navbar-fab-slot">
          <button className="navbar-fab" onClick={onScan} aria-label="Pindai QR">
            <Icon name="qr" size={26} stroke={2} />
          </button>
          <span className="navbar-fab-label">Pindai</span>
        </div>
        {tabs.slice(2).map(t => <NavTab key={t.id} t={t} active={current === t.id} onClick={() => onTab(t.id)} />)}
      </div>
    </div>
  );
};

const NavTab = ({ t, active, onClick }) => (
  <button className="nav-tab" data-active={active} onClick={onClick}>
    <div className="nav-tab-icon">
      <Icon name={t.icon} size={22} stroke={active ? 2 : 1.75} />
      {t.badge > 0 && <span className="nav-tab-badge">{t.badge > 9 ? '9+' : t.badge}</span>}
    </div>
    <span className="nav-tab-label">{t.label}</span>
  </button>
);

// Export
Object.assign(window, {
  Icon, EbLogo, StockBadge, ProductThumb, ProductCard,
  SpinnerIcon, MachineWall, BottomSheet, Topbar, QrMock, mmss,
  NavBar, NavTab,
});
