/* Shared small components */

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

function Icon({ name, size = 16 }) {
  const common = { width: size, height: size, viewBox: '0 0 24 24', fill: 'none', stroke: 'currentColor', strokeWidth: 2, strokeLinecap: 'round', strokeLinejoin: 'round' };
  const paths = {
    calendar: <><rect x="3" y="4" width="18" height="18" rx="2"/><path d="M16 2v4M8 2v4M3 10h18"/></>,
    trophy:   <><path d="M8 21h8M12 17v4M7 4h10v5a5 5 0 0 1-10 0V4Z"/><path d="M17 4h4v3a3 3 0 0 1-3 3M7 4H3v3a3 3 0 0 0 3 3"/></>,
    map:      <><path d="M9 4 3 6v15l6-2 6 2 6-2V4l-6 2-6-2Z"/><path d="M9 4v15M15 6v15"/></>,
    users:    <><path d="M16 21v-2a4 4 0 0 0-4-4H6a4 4 0 0 0-4 4v2"/><circle cx="9" cy="7" r="4"/><path d="M22 21v-2a4 4 0 0 0-3-3.87M16 3.13a4 4 0 0 1 0 7.75"/></>,
    cup:      <><path d="M6 9V4h12v5a6 6 0 0 1-12 0Z"/><path d="M6 4H3v3M18 4h3v3M9 21h6M12 15v6"/></>,
    pin:      <><path d="M12 22s7-7 7-12a7 7 0 1 0-14 0c0 5 7 12 7 12Z"/><circle cx="12" cy="10" r="3"/></>,
    mail:     <><rect x="2" y="5" width="20" height="14" rx="2"/><path d="m2 7 10 7 10-7"/></>,
    phone:    <><path d="M22 16.92v3a2 2 0 0 1-2.18 2 19.79 19.79 0 0 1-8.63-3.07 19.5 19.5 0 0 1-6-6 19.79 19.79 0 0 1-3.07-8.67A2 2 0 0 1 4.11 2h3a2 2 0 0 1 2 1.72c.13.96.36 1.9.7 2.81a2 2 0 0 1-.45 2.11L8.09 9.91a16 16 0 0 0 6 6l1.27-1.27a2 2 0 0 1 2.11-.45 12.84 12.84 0 0 0 2.81.7 2 2 0 0 1 1.72 2Z"/></>,
    check:    <><polyline points="20 6 9 17 4 12"/></>,
    info:     <><circle cx="12" cy="12" r="10"/><path d="M12 16v-4M12 8h.01"/></>,
    lock:     <><rect x="3" y="11" width="18" height="11" rx="2"/><path d="M7 11V7a5 5 0 0 1 10 0v4"/></>,
    edit:     <><path d="M12 20h9M16.5 3.5a2.12 2.12 0 0 1 3 3L7 19l-4 1 1-4 12.5-12.5Z"/></>,
    clock:    <><circle cx="12" cy="12" r="10"/><polyline points="12 6 12 12 16 14"/></>,
    flame:    <><path d="M8.5 14.5A2.5 2.5 0 0 0 11 17c1.5 0 3-1 3-3.5 0-2.5-2-3-2-3 .5-2-1-3.5-1-3.5-1 1-1 2-1 2.5 0 .5-.5 1-1 1a2 2 0 0 0-2 2c0 1 .5 1.5.5 1.5Z"/><path d="M12 21a9 9 0 0 0 9-9c0-4-2-5-2-8 0 0-3 1-3 4 0-2-2-4-4-4-4 0-7 3-7 8a9 9 0 0 0 7 9Z"/></>,
    bracket:  <><path d="M4 4v16M20 4v16M4 12h6M14 12h6M10 8v8M14 8v8"/></>,
    list:     <><path d="M8 6h13M8 12h13M8 18h13M3 6h.01M3 12h.01M3 18h.01"/></>,
    plus:     <><path d="M12 5v14M5 12h14"/></>,
    trash:    <><path d="M3 6h18M8 6V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2M19 6l-1 14a2 2 0 0 1-2 2H8a2 2 0 0 1-2-2L5 6M10 11v6M14 11v6"/></>,
    menu:     <><path d="M3 6h18M3 12h18M3 18h18"/></>,
    x:        <><path d="M18 6 6 18M6 6l12 12"/></>,
    print:    <><path d="M6 9V2h12v7"/><rect x="2" y="9" width="20" height="9" rx="2"/><path d="M6 14h12v7H6z"/></>,
    qrcode:   <><rect x="3" y="3" width="7" height="7"/><rect x="14" y="3" width="7" height="7"/><rect x="3" y="14" width="7" height="7"/><path d="M14 14h2v2h-2zM18 14h3M14 18h2v3M18 18h3v3"/></>,
    instagram:<><rect x="2" y="2" width="20" height="20" rx="5"/><circle cx="12" cy="12" r="4"/><circle cx="17.5" cy="6.5" r="0.6" fill="currentColor"/></>,
    'arrow-right': <><path d="M5 12h14M13 5l7 7-7 7"/></>,
    /* Tennis-Schläger + Ball — Material Design Icons (mdi:tennis), fill-based statt stroke. */
    racquet:  <path fill="currentColor" stroke="none" d="M18 15a4 4 0 0 1 4 4a4 4 0 0 1-4 4a4 4 0 0 1-4-4a4 4 0 0 1 4-4m0 2a2 2 0 0 0-2 2a2 2 0 0 0 2 2a2 2 0 0 0 2-2a2 2 0 0 0-2-2M6.05 14.54s1.41-1.42 1.42-4.24c-.36-2.19.5-4.76 2.47-6.72C12.87.65 17.14.17 19.5 2.5c2.33 2.36 1.85 6.63-1.08 9.56c-1.96 1.97-4.53 2.83-6.72 2.47c-2.82.01-4.24 1.42-4.24 1.42l-4.24 4.24l-1.41-1.41zM18.07 3.93C16.5 2.37 13.5 2.84 11.35 5c-2.14 2.14-2.62 5.15-1.06 6.71c1.57 1.56 4.57 1.08 6.71-1.06c2.16-2.15 2.63-5.15 1.07-6.72"/>,
  };
  return <svg {...common}>{paths[name]}</svg>;
}

function Toast({ message, onDone }) {
  useEffect(() => {
    if (!message) return;
    const t = setTimeout(onDone, 3000);
    return () => clearTimeout(t);
  }, [message]);
  if (!message) return null;
  return <div className="toast"><Icon name="check" size={14} /> &nbsp;{message}</div>;
}

function Countdown() {
  const [now, setNow] = useState(new Date());
  useEffect(() => {
    const id = setInterval(() => setNow(new Date()), 1000);
    return () => clearInterval(id);
  }, []);
  const { d, h, m, s } = diffParts(TOURNAMENT_START, now);
  return (
    <div className="countdown">
      <div className="head">
        <span className="label">Countdown</span>
      </div>
      <div className="cd-grid">
        <div className="cd-cell"><div className="num mono">{String(d).padStart(2,'0')}</div><div className="lbl">Tage</div></div>
        <div className="cd-cell"><div className="num mono">{String(h).padStart(2,'0')}</div><div className="lbl">Std</div></div>
        <div className="cd-cell"><div className="num mono">{String(m).padStart(2,'0')}</div><div className="lbl">Min</div></div>
        <div className="cd-cell"><div className="num mono">{String(s).padStart(2,'0')}</div><div className="lbl">Sek</div></div>
      </div>
    </div>
  );
}

function EdekaLogo() {
  return (
    <div className="edeka-logo">
      <img src="uploads/edeka-transparent.png?v=2026-solo" alt="EDEKA Riasanow"/>
    </div>
  );
}

// Powered-by-Badge fürs Hero — EDEKA Riasanow als alleiniger Hauptsponsor.
// Logo bringt Riasanow-Schriftzug und "regional. so. nah."-Baseline schon
// eingebaut mit, deshalb kein zusätzliches Sub-Label. Spans statt divs,
// damit das Element gültig in eine h1 eingebettet werden kann.
function HeroPoweredBadge() {
  return (
    <span className="hero-powered">
      <span className="hero-powered-label">
        <span className="line" aria-hidden="true"></span>
        Powered by
        <span className="line" aria-hidden="true"></span>
      </span>
      <span className="hero-powered-edeka">
        <img src="uploads/edeka-transparent.png?v=2026-solo" alt="EDEKA Riasanow" className="hero-powered-img hero-powered-img-edeka"/>
      </span>
    </span>
  );
}

function QRCode() {
  // Decorative QR-like SVG (not a real scannable code — placeholder)
  const cells = [];
  const seed = "1010110100110101011010110010101100101101010110010101101001010101011010110011010101010110100110";
  for (let r = 0; r < 21; r++) {
    for (let c = 0; c < 21; c++) {
      const i = (r * 21 + c) % seed.length;
      if (seed[i] === '1') cells.push(<rect key={`${r}-${c}`} x={c*4} y={r*4} width="4" height="4" fill="#1a1816"/>);
    }
  }
  // finder squares
  const finder = (x, y) => (
    <g transform={`translate(${x},${y})`}>
      <rect width="28" height="28" fill="#1a1816"/>
      <rect x="4" y="4" width="20" height="20" fill="#fff"/>
      <rect x="8" y="8" width="12" height="12" fill="#1a1816"/>
    </g>
  );
  return (
    <svg viewBox="0 0 84 84" width="84" height="84" style={{background:'#fff', borderRadius: 4}}>
      {cells}
      {finder(0,0)} {finder(56,0)} {finder(0,56)}
    </svg>
  );
}

// 12-zackiger Stern mit Preisgeld-Aufschrift, wie auf dem Flyer.
function PrizeStar() {
  const N = 12;
  const outer = 100, inner = 86;
  const pts = [];
  for (let i = 0; i < N * 2; i++) {
    const angle = (i / (N * 2)) * Math.PI * 2 - Math.PI / 2;
    const r = i % 2 === 0 ? outer : inner;
    pts.push(`${(Math.cos(angle) * r).toFixed(2)},${(Math.sin(angle) * r).toFixed(2)}`);
  }
  return (
    <div className="prize-star" aria-label="1.000 € Gesamtpreisgeld">
      <svg viewBox="-110 -110 220 220" xmlns="http://www.w3.org/2000/svg">
        <polygon points={pts.join(' ')} className="ps-burst"/>
        <polygon points={pts.join(' ')} className="ps-burst-inner"
                 transform="scale(0.86)"/>
        {/* GESAMT/PREISGELD optisch gleichweit von 1.000€ abgesetzt.
            Visible-Gap zur Amount-Bounding-Box ist oben und unten jeweils
            ~12 SVG-Einheiten. Da das amount-Glyph fast vollständig über
            seiner Baseline (y=16) rendert, sitzt GESAMT (y=-24) sichtbar
            näher als die alte Baseline -30 vermuten ließ. */}
        <text x="0" y="-24" textAnchor="middle" className="ps-label">GESAMT</text>
        <text x="0" y="16" textAnchor="middle" className="ps-amount">1.000€</text>
        <text x="0" y="44" textAnchor="middle" className="ps-label">PREISGELD</text>
      </svg>
    </div>
  );
}

// Print-Footer fuer jede A4/A3-Druckseite — Wappen links, Titel mittig:
// "1. Paartal Open" gross + Section-Subtitle (Hauptrunde / Trostrunde / etc.)
// Wird per CSS nur im Druck angezeigt.
function PrintFooter({ subtitle }) {
  return (
    <div className="print-footer">
      <img src="assets/wappen.png?v=2026-tennis" alt="" className="print-footer-wappen"/>
      <div className="print-footer-text">
        <div className="print-footer-title">1. Paartal Open</div>
        {subtitle && <div className="print-footer-sub">{subtitle}</div>}
      </div>
    </div>
  );
}

// Print-Mode-Trigger — shared zwischen Tableau und Meldeliste. Setzt eine
// Body-Klasse (print-a4 / print-a3) damit CSS spezifisch reagieren kann,
// injiziert fuer A3 ein temporaeres @page-Override (A3 quer), und nimmt
// beides in afterprint wieder zurueck. body.is-printing als Doppel-
// sicherung verhindert, dass fixed-positionierte Pillen (admin-banner,
// toast) im Race mit Chrome's @media-print-Anwendung auf den Druck
// durchschlagen — siehe CLAUDE.md "Drucklayout".
function printAs(mode) {
  const cls = 'print-' + mode;
  document.body.classList.add(cls);
  document.body.classList.add('is-printing');
  let pageStyle = null;
  if (mode === 'a3') {
    // Orientierung haengt von der Seite ab: das Tableau-Bracket braucht
    // Querformat (5 Runden nebeneinander), die Meldeliste-Aushang-Variante
    // dagegen Hochformat (lange Spielerliste laeuft nach unten).
    const isMeldeliste = document.body.dataset.page === 'meldeliste';
    const orientation = isMeldeliste ? 'portrait' : 'landscape';
    pageStyle = document.createElement('style');
    pageStyle.id = 'print-page-override';
    pageStyle.textContent = '@page { size: A3 ' + orientation + '; margin: 7mm; }';
    document.head.appendChild(pageStyle);
  }
  const cleanup = () => {
    document.body.classList.remove(cls);
    document.body.classList.remove('is-printing');
    if (pageStyle && pageStyle.parentNode) pageStyle.remove();
    window.removeEventListener('afterprint', cleanup);
  };
  window.addEventListener('afterprint', cleanup);
  window.print();
}

Object.assign(window, { Icon, Toast, Countdown, EdekaLogo, HeroPoweredBadge, PrizeStar, PrintFooter, QRCode, printAs });
