// ---------- Primitives ----------

const PLATFORM_META = {
  'Windows': { emoji: '🪟', short: 'Win' },
  'Mac': { emoji: '🍎', short: 'Mac' },
  'Linux': { emoji: '🐧', short: 'Lin' },
  'Web': { emoji: '🌐', short: 'Web' },
  'iOS': { emoji: '', short: 'iOS' },
  'Android': { emoji: '🤖', short: 'And' },
  'Web (self-hosted)': { emoji: '⚙️', short: 'Self' },
  'Self-hosted': { emoji: '⚙️', short: 'Self' },
};

function Platform({ name }) {
  // normalize
  const key = PLATFORM_META[name] ? name : (name.includes('self') ? 'Self-hosted' : name);
  const meta = PLATFORM_META[key] || { emoji: '•', short: name.slice(0,3) };
  return <span className="platform" title={key}>{meta.short}</span>;
}

function Platforms({ list }) {
  if (!list || !list.length) return null;
  return <span className="platforms">{list.map((p, i) => <Platform key={i} name={p} />)}</span>;
}

function Badge({ kind, children }) {
  const cls = {
    free: 'badge badge-free',
    oss: 'badge badge-oss',
    freemium: 'badge badge-freemium',
    neutral: 'badge badge-neutral',
  }[kind] || 'badge badge-neutral';
  return <span className={cls}><span className="badge-dot" />{children}</span>;
}

function AltBadges({ alt }) {
  const out = [];
  if (alt.gratuita && !alt.freemium) out.push(<Badge key="g" kind="free">Gratis</Badge>);
  if (alt.freemium && !alt.open_source) out.push(<Badge key="fm" kind="freemium">Freemium</Badge>);
  if (alt.open_source) out.push(<Badge key="os" kind="oss">Open Source</Badge>);
  if (alt.freemium && alt.open_source) out.push(<Badge key="fm2" kind="freemium">Freemium</Badge>);
  return <span className="alt-badges">{out}</span>;
}

function Stars({ value }) {
  // value 0-5 decimal
  const full = Math.floor(value);
  const half = value - full >= 0.25 && value - full < 0.75;
  const hasHalf = half ? 1 : 0;
  const empty = 5 - full - hasHalf;
  const star = (filled, key) => (
    <svg key={key} viewBox="0 0 24 24" className={filled ? '' : 'empty'}>
      <path d="M12 2l3.09 6.26L22 9.27l-5 4.87 1.18 6.88L12 17.77l-6.18 3.25L7 14.14 2 9.27l6.91-1.01L12 2z"/>
    </svg>
  );
  const halfStar = (key) => (
    <svg key={key} viewBox="0 0 24 24">
      <defs><linearGradient id={"hg"+key}><stop offset="50%" stopColor="currentColor"/><stop offset="50%" stopColor="#d6ceb8"/></linearGradient></defs>
      <path fill={`url(#hg${key})`} d="M12 2l3.09 6.26L22 9.27l-5 4.87 1.18 6.88L12 17.77l-6.18 3.25L7 14.14 2 9.27l6.91-1.01L12 2z"/>
    </svg>
  );
  const arr = [];
  for (let i=0;i<full;i++) arr.push(star(true, 'f'+i));
  if (hasHalf) arr.push(halfStar('h'));
  for (let i=0;i<empty;i++) arr.push(star(false, 'e'+i));
  return <span className="stars" aria-label={`Valutazione ${value} su 5`}>{arr}</span>;
}

function Rating({ value }) {
  return (
    <span className="alt-rating">
      <Stars value={value} />
      <span>{value.toFixed(1)}</span>
    </span>
  );
}

// Deterministic logo color based on name
function logoColor(name) {
  let h = 0; for (let i=0;i<name.length;i++) h = (h*31 + name.charCodeAt(i)) >>> 0;
  const hue = h % 360;
  return `hsl(${hue} 38% 92%)`;
}
function logoInk(name) {
  let h = 0; for (let i=0;i<name.length;i++) h = (h*31 + name.charCodeAt(i)) >>> 0;
  const hue = h % 360;
  return `hsl(${hue} 45% 32%)`;
}

function extractDomain(url) {
  if (!url) return null;
  try { return new URL(url).hostname.replace(/^www\./, ''); } catch { return null; }
}

function Logo({ name, size=44, url }) {
  const [failed, setFailed] = React.useState(false);
  const domain = url ? extractDomain(url) : null;
  const initials = name.split(/[\s.()\/]+/).filter(Boolean).slice(0,2).map(w => w[0]).join('').toUpperCase();
  const style = {
    width: size, height: size,
    fontSize: size*0.42,
    background: logoColor(name),
    color: logoInk(name),
  };
  if (domain && !failed) {
    return (
      <span className="sw-logo" style={{...style, padding: 6, background: '#fff', border: '1px solid var(--border)'}}>
        <img
          src={`https://www.google.com/s2/favicons?domain=${domain}&sz=128`}
          alt={`${name} logo`}
          width={size - 12} height={size - 12}
          style={{width: size-12, height: size-12, objectFit: 'contain', display: 'block'}}
          onError={() => setFailed(true)}
          loading="lazy"
        />
      </span>
    );
  }
  return <span className="sw-logo" style={style}>{initials || name[0]}</span>;
}

// ---------- Icons ----------
const Icon = {
  search: (p) => <svg {...p} width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"><circle cx="11" cy="11" r="7"/><path d="m21 21-4.3-4.3"/></svg>,
  arrow: (p) => <svg {...p} width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"><path d="M5 12h14M13 5l7 7-7 7"/></svg>,
  check: (p) => <svg {...p} width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="3" strokeLinecap="round" strokeLinejoin="round"><polyline points="20 6 9 17 4 12"/></svg>,
  warn: (p) => <svg {...p} width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.5" strokeLinecap="round" strokeLinejoin="round"><path d="M10.29 3.86 1.82 18a2 2 0 0 0 1.71 3h16.94a2 2 0 0 0 1.71-3L13.71 3.86a2 2 0 0 0-3.42 0z"/><path d="M12 9v4"/><path d="M12 17h.01"/></svg>,
  target: (p) => <svg {...p} width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"><circle cx="12" cy="12" r="10"/><circle cx="12" cy="12" r="6"/><circle cx="12" cy="12" r="2"/></svg>,
  ext: (p) => <svg {...p} width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"><path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"/><polyline points="15 3 21 3 21 9"/><line x1="10" y1="14" x2="21" y2="3"/></svg>,
};

// Category icons (simple inline SVGs, stroke)
function CatIcon({ name, className='cat-icon' }) {
  const common = { width: 28, height: 28, viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: 1.6, strokeLinecap: "round", strokeLinejoin: "round", className };
  const m = {
    "Produttività": <svg {...common}><path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"/><polyline points="14 2 14 8 20 8"/><line x1="9" y1="13" x2="15" y2="13"/><line x1="9" y1="17" x2="13" y2="17"/></svg>,
    "Project Management": <svg {...common}><rect x="3" y="4" width="7" height="16" rx="1"/><rect x="14" y="4" width="7" height="10" rx="1"/></svg>,
    "Grafica e Design": <svg {...common}><circle cx="13.5" cy="6.5" r="1.5"/><circle cx="17.5" cy="10.5" r="1.5"/><circle cx="8.5" cy="7.5" r="1.5"/><circle cx="6.5" cy="12.5" r="1.5"/><path d="M12 2C6.5 2 2 6.5 2 12s4.5 10 10 10c.83 0 1.5-.67 1.5-1.5 0-.39-.15-.74-.39-1.01-.23-.26-.38-.61-.38-.99 0-.83.67-1.5 1.5-1.5H16c3.31 0 6-2.69 6-6 0-5.52-4.48-10-10-10z"/></svg>,
    "Video Editing": <svg {...common}><rect x="2" y="4" width="20" height="16" rx="2"/><path d="M10 9l5 3-5 3V9z" fill="currentColor"/></svg>,
    "Comunicazione": <svg {...common}><path d="M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z"/></svg>,
    "Sicurezza e Privacy": <svg {...common}><path d="M12 22s8-4 8-10V5l-8-3-8 3v7c0 6 8 10 8 10z"/></svg>,
    "Email Marketing": <svg {...common}><path d="M4 4h16c1.1 0 2 .9 2 2v12c0 1.1-.9 2-2 2H4c-1.1 0-2-.9-2-2V6c0-1.1.9-2 2-2z"/><polyline points="22,6 12,13 2,6"/></svg>,
    "CRM e Vendite": <svg {...common}><line x1="18" y1="20" x2="18" y2="10"/><line x1="12" y1="20" x2="12" y2="4"/><line x1="6" y1="20" x2="6" y2="14"/></svg>,
    "Cloud e Storage": <svg {...common}><path d="M18 10h-1.26A8 8 0 1 0 9 20h9a5 5 0 0 0 0-10z"/></svg>,
    "AI e Chatbot": <svg {...common}><rect x="3" y="6" width="18" height="12" rx="2"/><circle cx="8.5" cy="12" r="1.5" fill="currentColor" stroke="none"/><circle cx="15.5" cy="12" r="1.5" fill="currentColor" stroke="none"/><path d="M12 6V3M8 3h8"/></svg>,
    "Software Italiani": <svg {...common}><path d="M3 9l9-7 9 7v11a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2z"/><polyline points="9 22 9 12 15 12 15 22"/></svg>,
  };
  return m[name] || <svg {...common}><circle cx="12" cy="12" r="9"/></svg>;
}

Object.assign(window, { Platform, Platforms, Badge, AltBadges, Stars, Rating, Logo, Icon, CatIcon, PLATFORM_META });
