const { useState, useMemo, useEffect } = React;

// Helpers
const formatDate = (iso) => {
  const d = new Date(iso);
  const months = ["stycznia", "lutego", "marca", "kwietnia", "maja", "czerwca", "lipca", "sierpnia", "września", "października", "listopada", "grudnia"];
  return `${d.getDate()} ${months[d.getMonth()]} ${d.getFullYear()}`;
};

const daysLeft = (iso) => {
  const now = new Date("2026-05-22");
  const end = new Date(iso);
  return Math.max(0, Math.ceil((end - now) / (1000 * 60 * 60 * 24)));
};

const Logo = ({ size = 32, inverted = false }) => {
  const gold = "#D4A03A";
  const ink = inverted ? "#FFFFFF" : "#1a2230";
  return (
    <svg width={size} height={size} viewBox="0 0 40 40" fill="none" aria-hidden="true">
      <rect x="4" y="22" width="9" height="14" rx="1.5" fill={ink} opacity="0.55" />
      <rect x="15.5" y="10" width="9" height="26" rx="1.5" fill={gold} />
      <rect x="27" y="16" width="9" height="20" rx="1.5" fill={ink} opacity="0.8" />
      <path d="M20 4 L21.3 7 L24.5 7.3 L22.1 9.4 L22.8 12.5 L20 10.9 L17.2 12.5 L17.9 9.4 L15.5 7.3 L18.7 7 Z"
        fill={gold} stroke={ink} strokeWidth="0.8" strokeLinejoin="round" />
    </svg>
  );
};

const Brand = ({ inverted = false }) => (
  <a href="#" className={`brand ${inverted ? 'brand-inv' : ''}`} aria-label="ran-king.pl — strona główna">
    <Logo size={34} inverted={inverted} />
    <span className="brand-wordmark">
      <span className="bw-ran">ran</span><span className="bw-dash">–</span><span className="bw-king">king</span><span className="bw-tld">.pl</span>
    </span>
  </a>
);

const Difficulty = ({ level, label }) =>
<div className="diff">
    <div className="diff-dots">
      {[1, 2, 3, 4, 5].map((i) =>
    <span key={i} className={`diff-dot ${i <= level ? 'on' : ''}`} />
    )}
    </div>
    <span className="diff-label">{label}</span>
  </div>;


const BankLogo = ({ bank }) =>
<div className="bank-logo" style={{ backgroundColor: bank.color }}>
    <span>{bank.initials}</span>
  </div>;


const OfferCard = ({ offer, expanded, onToggle, isFeatured }) => {
  const dLeft = daysLeft(offer.expiry);
  const urgent = dLeft <= 10;

  return (
    <article className={`offer-card ${isFeatured ? 'featured' : ''} ${expanded ? 'expanded' : ''}`} data-screen-label={`Oferta ${offer.rank}: ${offer.bank}`}>
      <div className="offer-rank">
        <span className="rank-num">{String(offer.rank).padStart(2, '0')}</span>
        {isFeatured && <span className="rank-medal">★</span>}
      </div>

      <div className="offer-main">
        <header className="offer-head">
          <BankLogo bank={offer} />
          <div className="offer-meta">
            <h2 className="offer-bank">{offer.bank}</h2>
            <p className="offer-product">{offer.product}</p>
          </div>
          <div className="offer-badges">
            {offer.badges.map((b) => <span key={b} className="badge">{b}</span>)}
          </div>
        </header>

        <div className="offer-body">
          <div className="offer-premia">
            <span className="premia-label">Premia</span>
            <span className="premia-value">{offer.premiaLabel}</span>
            <div className="premia-breakdown">
              {offer.breakdown.map((b, i) =>
              <div key={i} className="bd-row">
                  <span className="bd-label">{b.label}</span>
                  <span className="bd-value">{b.value}</span>
                </div>
              )}
            </div>
          </div>

          <div className="offer-info">
            <p className="offer-desc">{offer.description}</p>
            <div className="offer-stats">
              <div className="stat">
                <span className="stat-k">Trudność</span>
                <Difficulty level={offer.difficulty} label={offer.difficultyLabel} />
              </div>
              <div className="stat">
                <span className="stat-k">Czas do nagrody</span>
                <span className="stat-v">{offer.timeToReward}</span>
              </div>
              <div className="stat">
                <span className="stat-k">Oferta do</span>
                <span className={`stat-v ${urgent ? 'urgent' : ''}`}>
                  {formatDate(offer.expiry)}
                  {urgent && <span className="urgent-tag">tylko {dLeft} dni</span>}
                </span>
              </div>
              {offer.promoCode &&
              <div className="stat">
                  <span className="stat-k">Kod promocyjny</span>
                  <span className="stat-v code">{offer.promoCode}</span>
                </div>
              }
            </div>
          </div>

          <div className="offer-cta">
            <a href={offer.url} target="_blank" rel="noopener nofollow sponsored" className="btn-primary" data-track-bank={offer.id} data-track-rank={offer.rank} data-track-premia={offer.premia}>
              <span>Sprawdź ofertę</span>
              <svg width="14" height="14" viewBox="0 0 14 14" fill="none">
                <path d="M3 11L11 3M11 3H5M11 3V9" stroke="currentColor" strokeWidth="1.6" strokeLinecap="round" strokeLinejoin="round" />
              </svg>
            </a>
            <button className="btn-secondary" onClick={onToggle} data-track-expand={offer.id}>
              {expanded ? 'Zwiń warunki' : 'Pokaż warunki'}
              <svg width="12" height="12" viewBox="0 0 12 12" fill="none" style={{ transform: expanded ? 'rotate(180deg)' : 'none', transition: 'transform .2s' }}>
                <path d="M3 4.5L6 7.5L9 4.5" stroke="currentColor" strokeWidth="1.6" strokeLinecap="round" strokeLinejoin="round" />
              </svg>
            </button>
          </div>
        </div>

        {expanded &&
        <div className="offer-details">
            <h3>Warunki promocji</h3>
            <ol>
              {offer.conditions.map((c, i) => <li key={i}>{c}</li>)}
            </ol>
            <p className="disclaimer">
              Powyższe punkty to streszczenie kluczowych warunków. Przed założeniem konta zapoznaj się z pełnym regulaminem promocji na stronie banku.
            </p>
          </div>
        }
      </div>
    </article>);

};

const Filters = ({ sortBy, setSortBy, filterDiff, setFilterDiff, search, setSearch, count }) =>
<div className="filters" id="filters">
    <div className="filter-row">
      <div className="search-wrap">
        <svg width="16" height="16" viewBox="0 0 16 16" fill="none">
          <circle cx="7" cy="7" r="5" stroke="currentColor" strokeWidth="1.5" />
          <path d="M11 11L14 14" stroke="currentColor" strokeWidth="1.5" strokeLinecap="round" />
        </svg>
        <input
        type="text"
        placeholder="Szukaj banku..."
        value={search}
        onChange={(e) => setSearch(e.target.value)} />
      
      </div>

      <div className="filter-group">
        <span className="filter-label">Sortuj:</span>
        <div className="seg">
          {[
        { id: 'premia', label: 'Wysokość premii' },
        { id: 'difficulty', label: 'Łatwość warunków' },
        { id: 'expiry', label: 'Kończące się' }].
        map((opt) =>
        <button
          key={opt.id}
          className={`seg-btn ${sortBy === opt.id ? 'active' : ''}`}
          onClick={() => setSortBy(opt.id)}>
          
              {opt.label}
            </button>
        )}
        </div>
      </div>

      <div className="filter-group">
        <span className="filter-label">Trudność:</span>
        <div className="seg">
          {[
        { id: 'all', label: 'Wszystkie' },
        { id: 'easy', label: 'Łatwe' },
        { id: 'medium', label: 'Średnie' }].
        map((opt) =>
        <button
          key={opt.id}
          className={`seg-btn ${filterDiff === opt.id ? 'active' : ''}`}
          onClick={() => setFilterDiff(opt.id)}>
          
              {opt.label}
            </button>
        )}
        </div>
      </div>
    </div>
    <div className="filter-meta">
      <span><strong>{count}</strong> {count === 1 ? 'oferta' : count < 5 ? 'oferty' : 'ofert'} dopasowane do filtrów</span>
      <span className="filter-meta-sep">·</span>
      <span>Aktualizacja: <strong>22 maja 2026</strong></span>
    </div>
  </div>;


const Hero = ({ totalMax, bankCount, topOffer }) =>
<header className="hero">
    <div className="hero-top">
      <Brand />
      <nav className="nav">
        <a href="#ranking">Ranking</a>
        <a href="#jak">Jak to działa</a>
        <a href="#faq">FAQ</a>
        <a href="#metoda">Metodologia</a>
        <a href="kontakt.html">Kontakt</a>
      </nav>
    </div>

    <div className="hero-content">
      <div className="hero-eyebrow">
        <span className="live-dot" />
        {(window.VARIANT_CONFIG?.hero?.eyebrow) || 'Ranking maj 2026 — zaktualizowano dziś'}
      </div>
      <h1 className="hero-title">
        {(() => {
          const t = window.VARIANT_CONFIG?.hero?.title;
          if (t) {
            return <>{t.pre}<br />{t.em && <span className="hero-em">{t.em.replace('{premia}', topOffer.premia.toLocaleString('pl-PL'))}{' '}</span>}{t.post}</>;
          }
          return <>Najlepsze promocje bankowe.<br /><span className="hero-em">Do {topOffer.premia.toLocaleString('pl-PL')} zł{' '}</span> za otwarcie konta.</>;
        })()}
      </h1>
      <p className="hero-sub">
        {(window.VARIANT_CONFIG?.hero?.sub) || `Aktualne i sprawdzone oferty banków w Polsce — ${bankCount} promocji w jednym miejscu. Sortuj wg wysokości premii albo trudności warunków. Bez ukrytych haków, z bezpośrednimi linkami do każdej oferty.`}
      </p>

      <div className="hero-stats">
        <div className="hstat">
          <span className="hstat-v">{bankCount}</span>
          <span className="hstat-l">aktualnych promocji</span>
        </div>
        <div className="hstat">
          <span className="hstat-v">{topOffer.premiaLabel}</span>
          <span className="hstat-l">u lidera: {topOffer.bank}</span>
        </div>
        <div className="hstat">
          <span className="hstat-v">10 min</span>
          <span className="hstat-l">tyle trwa otwarcie konta online</span>
        </div>
        <div className="hstat">
          <span className="hstat-v">0 zł</span>
          <span className="hstat-l">opłaty za nasze rekomendacje</span>
        </div>
      </div>

      <div className="hero-cta">
        <a href="#ranking" className="btn-primary big">
          {(window.VARIANT_CONFIG?.hero?.cta) || 'Zobacz ranking'}
          <svg width="16" height="16" viewBox="0 0 16 16" fill="none">
            <path d="M4 8H12M12 8L8 4M12 8L8 12" stroke="currentColor" strokeWidth="1.8" strokeLinecap="round" strokeLinejoin="round" />
          </svg>
        </a>
        <a href="#jak" className="btn-ghost">
          Jak korzystać z promocji?
        </a>
      </div>
    </div>
  </header>;


const HowItWorks = () =>
<section className="how" id="jak">
    <div className="section-head">
      <span className="section-eyebrow">Jak to działa</span>
      <h2 className="section-title">Cztery kroki do premii</h2>
    </div>
    <div className="steps">
      {[
    { n: '01', t: 'Wybierz ofertę', d: 'Posortuj ranking wg wysokości premii lub trudności warunków. Sprawdź, czy nie obowiązuje Cię karencja.' },
    { n: '02', t: 'Wypełnij wniosek online', d: 'Każda oferta prowadzi bezpośrednio do strony banku. Większość konta założysz w 10 minut na selfie lub przez mObywatela.' },
    { n: '03', t: 'Spełnij warunki', d: 'Najczęściej wystarczy wpływ na konto i kilka płatności kartą lub BLIKIEM przez 2–3 miesiące.' },
    { n: '04', t: 'Odbierz premię', d: 'Bank wypłaca nagrodę przelewem — w jednej lub w kilku transzach, zgodnie z regulaminem promocji.' }].
    map((s) =>
    <div key={s.n} className="step">
          <span className="step-num">{s.n}</span>
          <h3 className="step-title">{s.t}</h3>
          <p className="step-desc">{s.d}</p>
        </div>
    )}
    </div>
  </section>;


const FAQ = () => {
  const [open, setOpen] = useState(0);
  const items = [
  {
    q: 'Czy promocje bankowe są bezpieczne?',
    a: 'Tak. Premia za otwarcie konta to standardowa forma marketingu — wszystkie banki w naszym rankingu są nadzorowane przez Komisję Nadzoru Finansowego i objęte gwarancjami Bankowego Funduszu Gwarancyjnego do 100 000 EUR.'
  },
  {
    q: 'Ile kont mogę założyć jednocześnie?',
    a: 'Nie ma limitu. Możesz brać udział w kilku promocjach naraz w różnych bankach. Pamiętaj jednak, że każdy bank określa własną „karencję" — okres, w którym nie mogłeś mieć u niego konta, żeby zaliczyć się do nowych klientów.'
  },
  {
    q: 'Czy od premii bankowej trzeba zapłacić podatek?',
    a: 'Zazwyczaj nie — większość banków sama rozlicza podatek lub korzysta ze zwolnienia (do 200 zł na podstawie art. 21 ust. 1 pkt 68a ustawy o PIT). Wyższe nagrody bywają wypłacane w transzach, by mieścić się w zwolnieniu. Szczegóły znajdziesz w regulaminie konkretnej promocji.'
  },
  {
    q: 'Jak długo czeka się na wypłatę bonusu?',
    a: 'Od 3 dni roboczych (Revolut) do nawet 12 miesięcy (Bank Pocztowy, PKO BP). Większość banków wypłaca premię w 30–60 dni od spełnienia warunków danego etapu.'
  },
  {
    q: 'Co to jest karencja w promocji bankowej?',
    a: 'To okres, w którym nie mogłeś być klientem danego banku, żeby załapać się na nową promocję. Najczęściej wynosi 6–24 miesiące. Erste Bank wymaga braku konta od 01.04.2024, mBank od 01.01.2022, a Alior Bank — przez ostatnie 3 lata.'
  },
  {
    q: 'Czy mogę zrezygnować z konta po odebraniu premii?',
    a: 'Tak, ale uważaj — niektóre regulaminy wymagają utrzymania konta przez określony czas (np. 6 miesięcy) po wypłacie ostatniej transzy nagrody. W przeciwnym razie bank może zażądać zwrotu bonusu.'
  },
  {
    q: 'Jak nie zapomnieć o warunkach każdej promocji?',
    a: 'Załóż kalendarz z przypomnieniami na każdy miesiąc: wpływ + transakcje kartą + logowanie do aplikacji. Najczęstszy powód utraty premii to niezauważone wymaganie z regulaminu, nie brak aktywności.'
  }];


  return (
    <section className="faq" id="faq">
      <div className="section-head">
        <span className="section-eyebrow">FAQ</span>
        <h2 className="section-title">Pytania, które naprawdę zadajecie</h2>
      </div>
      <div className="faq-list">
        {items.map((it, i) =>
        <div key={i} className={`faq-item ${open === i ? 'open' : ''}`}>
            <button className="faq-q" onClick={() => setOpen(open === i ? -1 : i)}>
              <span>{it.q}</span>
              <span className="faq-icon">{open === i ? '−' : '+'}</span>
            </button>
            {open === i && <div className="faq-a">{it.a}</div>}
          </div>
        )}
      </div>
    </section>);

};

const Methodology = () =>
<section className="methodology" id="metoda">
    <div className="section-head">
      <span className="section-eyebrow">Metodologia</span>
      <h2 className="section-title">Jak tworzymy ranking</h2>
    </div>
    <div className="method-grid">
      <div className="method-card">
        <span className="method-num">1</span>
        <h3>Analizujemy regulaminy</h3>
        <p>Każdą promocję czytamy w całości — łącznie z definicją „nowego klienta" i wymogami dotyczącymi zgód marketingowych.</p>
      </div>
      <div className="method-card">
        <span className="method-num">2</span>
        <h3>Ważymy nagrodę i trudność</h3>
        <p>Wysokość premii to nie wszystko. Porównujemy ją z liczbą wymaganych transakcji, minimalnym wpływem i czasem do wypłaty.</p>
      </div>
      <div className="method-card">
        <span className="method-num">3</span>
        <h3>Odrzucamy nieprzejrzyste</h3>
        <p>Pomijamy promocje, w których przyznanie nagrody zależy od uznaniowej decyzji banku albo niejasnych zapisów regulaminu.</p>
      </div>
      <div className="method-card">
        <span className="method-num">4</span>
        <h3>Aktualizujemy co tydzień</h3>
        <p>Ranking odświeżamy w każdy poniedziałek oraz natychmiast po publikacji nowej promocji przez którykolwiek bank z zestawienia.</p>
      </div>
    </div>
  </section>;


const Footer = () =>
<footer className="footer">
    <div className="footer-top">
      <div className="footer-brand">
        <Brand inverted />
        <p>Niezależne porównanie promocji bankowych w Polsce. Aktualizowane co tydzień.</p>
      </div>
      <div className="footer-cols">
        <div>
          <h4>Ranking</h4>
          <ul>
            <li><a href="#ranking">Konta z premią</a></li>
            <li><a href="#jak">Jak to działa</a></li>
            <li><a href="#faq">FAQ</a></li>
            <li><a href="#metoda">Metodologia</a></li>
          </ul>
        </div>
        <div>
          <h4>Informacje prawne</h4>
          <ul>
            <li><a href="polityka-prywatnosci.html">Polityka prywatności</a></li>
            <li><a href="polityka-cookies.html">Polityka cookies</a></li>
            <li><a href="regulamin.html">Regulamin serwisu</a></li>
            <li><a href="#" onClick={(e) => { e.preventDefault(); window.openCookieSettings && window.openCookieSettings(); }}>Ustawienia cookies</a></li>
          </ul>
        </div>
        <div>
          <h4>Kontakt</h4>
          <ul>
            <li><a href="kontakt.html">Formularz kontaktowy</a></li>
            <li><a href="mailto:kontakt@ran-king.pl">kontakt@ran-king.pl</a></li>
          </ul>
        </div>
      </div>
    </div>
    <div className="footer-bottom">
      <p>© 2026 ran-king.pl. Serwis ma charakter informacyjny i nie stanowi oferty w rozumieniu art. 66 §1 Kodeksu Cywilnego. Pełne warunki każdej promocji znajdziesz w regulaminie udostępnianym przez bank.</p>
      <p>Korzystając z linków na tej stronie możesz przejść do oferty partnera ComperiaLead — nie wpływa to na ocenę produktu w naszym rankingu.</p>
    </div>
  </footer>;


const App = () => {
  const [sortBy, setSortBy] = useState('premia');
  const [filterDiff, setFilterDiff] = useState('all');
  const [search, setSearch] = useState('');
  const [expandedId, setExpandedId] = useState(null);

  const filtered = useMemo(() => {
    let list = [...window.BANK_OFFERS];
    if (search.trim()) {
      const q = search.toLowerCase();
      list = list.filter((o) =>
      o.bank.toLowerCase().includes(q) ||
      o.product.toLowerCase().includes(q)
      );
    }
    if (filterDiff === 'easy') list = list.filter((o) => o.difficulty <= 2);
    if (filterDiff === 'medium') list = list.filter((o) => o.difficulty === 3);

    if (sortBy === 'premia') list.sort((a, b) => b.premia - a.premia);
    if (sortBy === 'difficulty') list.sort((a, b) => a.difficulty - b.difficulty || b.premia - a.premia);
    if (sortBy === 'expiry') list.sort((a, b) => new Date(a.expiry) - new Date(b.expiry));

    return list;
  }, [sortBy, filterDiff, search]);

  const totalMax = useMemo(() =>
  window.BANK_OFFERS.reduce((s, o) => s + o.premia, 0),
  []);

  const topOffer = window.BANK_OFFERS[0];

  return (
    <div className="app">
      <Hero totalMax={totalMax} bankCount={window.BANK_OFFERS.length} topOffer={topOffer} />

      <main className="main" id="ranking">
        <div className="ranking-head">
          <span className="section-eyebrow">Ranking</span>
          <h2 className="section-title">Wszystkie aktualne promocje — maj 2026</h2>
          <p className="section-sub">Najatrakcyjniejsze oferty na górze. Kliknij „Pokaż warunki", aby zobaczyć dokładne wymagania każdej promocji.</p>
        </div>

        <Filters
          sortBy={sortBy} setSortBy={setSortBy}
          filterDiff={filterDiff} setFilterDiff={setFilterDiff}
          search={search} setSearch={setSearch}
          count={filtered.length} />
        

        <div className="offers">
          {filtered.length === 0 &&
          <div className="empty">
              <p>Brak ofert spełniających kryteria.</p>
              <button className="btn-secondary" onClick={() => {setSearch('');setFilterDiff('all');}}>Wyczyść filtry</button>
            </div>
          }
          {filtered.map((offer, idx) =>
          <OfferCard
            key={offer.id}
            offer={offer}
            expanded={expandedId === offer.id}
            onToggle={() => setExpandedId(expandedId === offer.id ? null : offer.id)}
            isFeatured={sortBy === 'premia' && idx < 3} />

          )}
        </div>

        <div className="bottom-cta">
          <h3>Nie wiesz, od czego zacząć?</h3>
          <p>Wybierz ofertę z TOP 3 i załóż konto online w 10 minut. Pierwszą premię odbierzesz już w przyszłym miesiącu.</p>
          <a href={topOffer.url} target="_blank" rel="noopener nofollow sponsored" className="btn-primary big" data-track-bank={topOffer.id} data-track-rank={topOffer.rank} data-track-premia={topOffer.premia} data-track-source="bottom-cta">
            Załóż {topOffer.bank} →
          </a>
        </div>
      </main>

      <HowItWorks />
      <FAQ />
      <Methodology />
      <Footer />
    </div>);

};

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