/* global React, ReactDOM, Henrieta, HexFrame, CardSigil, HenrietaResults, IdleBubble */

const { useState, useMemo, useEffect, useRef } = React;
const { lifePathNumber } = window.numerology;
// Wszystkie zestawy tekstów żyją w data.mjs i są wstawiane do window.henData
// przez bootstrap module w index.html (uruchamia się przed Babel standalone).
const { PROFILES_F, PROFILES_M, EXTRAS_F, EXTRAS_M, QUIPS_F, QUIPS_M } = window.henData;
const PROFILES_BY_GENDER = { f: PROFILES_F, m: PROFILES_M };
const EXTRAS_BY_GENDER = { f: EXTRAS_F, m: EXTRAS_M };
const QUIPS_BY_GENDER = { f: QUIPS_F, m: QUIPS_M };

const TWEAKS = {
  theme: "noc",
  showMath: true,
  showStars: true,
  tone: "henrieta",
  buzz: false,
};

const MONTHS_PL = [
  "stycznia", "lutego", "marca", "kwietnia", "maja", "czerwca",
  "lipca", "sierpnia", "września", "października", "listopada", "grudnia",
];

const CASTING_LINES = [
  "Henrieta liczy plastry...",
  "Konsultuje się z Wielką Królową Pasieki...",
  "Sprawdza wibracje rumianku...",
  "Trzepie skrzydłami w stronę kosmosu...",
  "Otwiera słoik z 1987 roku...",
  "Pyta królową, ale królowa drzemie...",
];

// Krótkie zachęty pszczoły wyświetlane jako bubble nad pszczołą na ekranie startowym.
// Rotują co kilka sekund, fade in/out — nie przesuwają pszczoły.
const IDLE_HOOKS = [
  "Cześć, jestem Henrieta.\nWpisz datę - reszta to mój zawód.",
  "Twoja liczba życiowa już na Ciebie patrzy.\nNie patrz w drugą stronę.",
  "Mów mi Henrieta.\n\n Henrieta Brzęczyszczyszczykiewicz.\nDla Ciebie Heńka.",
  "Brzęcz mi mówi, że dziś dowiesz się czegoś o sobie.",
  "Wieszczbiarska pasieka otwarta. Wejdź.",
  "Mam dla Ciebie coś, czego nawet Linkedin Premium nie wie.",
  "Henrieta liczy plastry od 1834.\nTwojej daty jeszcze nie miała.",
  "Twoja liczba życiowa to nie wróżba - to lustro z miodem.",
  "Pszczoły wiedzą, kiedy ktoś się zbliża.\nTy się zbliżyłaś.",
  "Plaster mi się uśmiecha. Spróbuj.",
  "Come to Mummy! Będzie Yummy!",
];



const SCEPTYK_OVERRIDE = {
  nature:
    "Numerologia nie ma żadnego oparcia w empirii. Cyfry w twojej dacie urodzenia to po prostu cyfry. Henrieta jednak uznaje, że jesteś osobą z tendencją do refleksji, bo czytasz to z własnej woli.",
  week:
    "W tym tygodniu wydarzą się rzeczy zgodne z prawdopodobieństwem warunkowym. Trochę przyjemnych, trochę nudnych, jedna lekko irytująca. Statystyka i tyle.",
  advice:
    "Pij wodę, śpij 7–9 godzin, rób trzy razy w tygodniu coś, w czym czujesz przepływ. To nie magia. To tylko najnudniejsza prawda, jaką Henrieta zna.",
};

// ============================================================
// Płeć z imienia
// ============================================================
// Heurystyka po PL imionach: kończą się na "a/ą" → kobieta, z wyjątkami:
// Kuba, Barnaba, Kosma, Jarema, Bonawentura. Bez imienia: kobieta.
const MALE_ENDS_A = new Set([
  "kuba", "barnaba", "kosma", "jarema", "bonawentura", "ilia", "aza",
]);

function inferGender(name) {
  const n = (name || "").trim().toLowerCase();
  if (!n) return "f";
  if (MALE_ENDS_A.has(n)) return "m";
  return /[aą]$/i.test(n) ? "f" : "m";
}

// Normalizacja imienia: trim, weź pierwsze słowo (odcina „Anna Maria" → „Anna"),
// pierwsza wielka, reszta małe. Locale="pl-PL" dla pewności polskich diakrytyków.
function normalizeName(raw) {
  if (!raw) return "";
  const first = raw.trim().split(/\s+/)[0] || "";
  if (!first) return "";
  return (
    first.charAt(0).toLocaleUpperCase("pl-PL") +
    first.slice(1).toLocaleLowerCase("pl-PL")
  );
}

// ============================================================
// Pole formularza
// ============================================================
function DateForm({ value, onChange, onSubmit, error }) {
  const { name, d, m, y } = value;
  const handle = (k) => (e) => onChange({ ...value, [k]: e.target.value });

  return (
    <form
      className="date-form"
      onSubmit={(e) => {
        e.preventDefault();
        onSubmit();
      }}
    >
      <div className="date-field name">
        <label htmlFor="n">Imię</label>
        <input
          id="n"
          type="text"
          placeholder="Twoje imię"
          value={name}
          onChange={handle("name")}
          autoComplete="given-name"
          autoFocus
          maxLength={32}
        />
      </div>
      <div className="date-field day">
        <label htmlFor="d">Dzień</label>
        <input
          id="d"
          type="number"
          min="1"
          max="31"
          inputMode="numeric"
          placeholder="—"
          value={d}
          onChange={handle("d")}
        />
      </div>
      <div className="date-field month">
        <label htmlFor="m">Miesiąc</label>
        <select id="m" value={m} onChange={handle("m")}>
          <option value="">— wybierz —</option>
          {MONTHS_PL.map((label, i) => (
            <option key={i} value={String(i + 1)}>
              {label}
            </option>
          ))}
        </select>
      </div>
      <div className="date-field year">
        <label htmlFor="y">Rok</label>
        <input
          id="y"
          type="number"
          min="1900"
          max="2099"
          inputMode="numeric"
          placeholder="rrrr"
          value={y}
          onChange={handle("y")}
        />
      </div>
      {/* Ukryty submit żeby Enter wewnątrz formularza wystrzelił onSubmit
          (browser implicit submission wymaga submit-eligible buttona). */}
      <button type="submit" aria-hidden="true" tabIndex={-1} style={{
        position: "absolute",
        width: 1,
        height: 1,
        padding: 0,
        margin: -1,
        overflow: "hidden",
        clip: "rect(0 0 0 0)",
        border: 0,
      }} />
    </form>
  );
}

// ============================================================
// Etap obliczania
// ============================================================
function Casting({ tickKey }) {
  const [idx, setIdx] = useState(0);
  useEffect(() => {
    const t = setInterval(
      () => setIdx((i) => (i + 1) % CASTING_LINES.length),
      900
    );
    return () => clearInterval(t);
  }, [tickKey]);

  return (
    <div className="casting">
      <div className="orb-wrap">
        <div className="orb-aura" />
        <Henrieta buzzing eyes="closed" />
      </div>
      <p className="casting-line">{CASTING_LINES[idx]}</p>
      <div className="casting-dots">
        <span className="casting-dot" />
        <span className="casting-dot" />
        <span className="casting-dot" />
        <span className="casting-dot" />
      </div>
    </div>
  );
}

// ============================================================
// Mały bubble nad pszczołą na ekranie startowym — rotuje zachęty.
// Pozycjonowany absolute żeby nie przesuwał Henriety.
// ============================================================
function IdleBubble() {
  const [idx, setIdx] = useState(() =>
    Math.floor(Math.random() * IDLE_HOOKS.length)
  );
  // Start jako hidden — fade-in dopiero po krótkiej chwili od mountu.
  const [visible, setVisible] = useState(false);

  useEffect(() => {
    let timer;
    let mounted = true;

    // Cykl: pokaż na 5.5s → fade out → cisza ~4s → zmień tekst → pokaż znowu.
    // Transition opacity 0.4s w CSS dba o sam fade.
    const VISIBLE_MS = 5500;
    const HIDDEN_MS = 4000;
    const INITIAL_DELAY = 1600;

    function showNext() {
      if (!mounted) return;
      setVisible(true);
      timer = setTimeout(() => {
        if (!mounted) return;
        setVisible(false);
        timer = setTimeout(() => {
          if (!mounted) return;
          setIdx((i) => (i + 1) % IDLE_HOOKS.length);
          showNext();
        }, HIDDEN_MS);
      }, VISIBLE_MS);
    }

    timer = setTimeout(showNext, INITIAL_DELAY);

    return () => {
      mounted = false;
      clearTimeout(timer);
    };
  }, []);

  return (
    <div
      className={"idle-bubble" + (visible ? " is-visible" : " is-hidden")}
      role="note"
      aria-live="polite"
    >
      {IDLE_HOOKS[idx]}
    </div>
  );
}

// ============================================================
// Pasek pokazujący obliczenia
// ============================================================
function MathStrip({ date, number }) {
  if (!date) return null;
  const [y, m, d] = date.split("-").map(Number);
  const allDigits = `${y}${String(m).padStart(2, "0")}${String(d).padStart(2, "0")}`
    .split("")
    .map(Number);
  const sum = allDigits.reduce((s, n) => s + n, 0);
  return (
    <div className="math-strip">
      {allDigits.join(" + ")} = <strong>{sum}</strong>
      {sum !== number && (
        <>
          {" "}
          → … → <strong>{number}</strong>
        </>
      )}
      
    </div>
  );
}

// Pszczoła z dymkiem — pokazuje się obok wyniku
function HenrietaBubble({ number, tone, gender, name }) {
  const quipsSet = QUIPS_BY_GENDER[gender] || QUIPS_BY_GENDER.f;
  const variants = quipsSet[number] || [
    "Liczby nie kłamią. Najwyżej ściemniają w nieoczywisty sposób.",
  ];
  const raw = useMemo(
    () =>
      tone === "sceptyk"
        ? "Liczby to liczby. Twój horoskop to też tekst. Mózg lubi wzorce. Henrieta tylko podaje cyfrę."
        : variants[Math.floor(Math.random() * variants.length)],
    [number, tone, gender]
  );
  const quip = (name ? `${name}, ` : "") + raw;
  return (
    <div className="henrieta-pod">
      <div className="orb-wrap small">
        <div className="orb-aura" />
        <HenrietaResults />
      </div>
      <div className="henrieta-bubble" role="note" aria-label="Komentarz Henriety">
        <p>{quip}</p>
        <span className="henrieta-bubble-sig">- Henrieta, dyplomowana pszczelarka</span>
      </div>
    </div>
  );
}

// ============================================================
// Wynik
// ============================================================
function Result({ number, date, name, gender, onReset, tone, showMath }) {
  const profiles = PROFILES_BY_GENDER[gender] || PROFILES_BY_GENDER.f;
  const profile = profiles[number];
  const extrasSet = EXTRAS_BY_GENDER[gender] || EXTRAS_BY_GENDER.f;
  const picked = useMemo(() => {
    if (!profile) return { nature: "", week: "", advice: "", ni: 0, wi: 0, ai: 0 };
    const ex = extrasSet[number] || {};
    const nList = [profile.nature, ...(ex.nature || [])];
    const wList = [profile.week, ...(ex.week || [])];
    const aList = [profile.advice, ...(ex.advice || [])];
    const ni = Math.floor(Math.random() * nList.length);
    const wi = Math.floor(Math.random() * wList.length);
    const ai = Math.floor(Math.random() * aList.length);
    return { nature: nList[ni], week: wList[wi], advice: aList[ai], ni, wi, ai };
  }, [number, profile, extrasSet]);

  if (!profile) return null;

  const useScept = tone === "sceptyk";
  const nature = useScept ? SCEPTYK_OVERRIDE.nature : picked.nature;
  const week = useScept ? SCEPTYK_OVERRIDE.week : picked.week;
  const advice = useScept ? SCEPTYK_OVERRIDE.advice : picked.advice;
  const cardUrl =
    `/api/share?number=${number}` +
    `&n=${picked.ni}&a=${picked.ai}` +
    `&name=${encodeURIComponent(name || "")}` +
    `&g=${gender}`;

  return (
    <div className="reveal">
      <div className="crest" style={{ marginBottom: 8 }}>
        <span className="crest-label">Wieszczba dla duszy</span>
      </div>

      {name && <h2 className="result-greeting">{name}, jesteś {number}-ką!</h2>}

      <HenrietaBubble number={number} tone={tone} gender={gender} name={name} />

      <div className="result-hero-grid">
        <div className="result-hero-left">
          <div className="hero-number">
            <HexFrame />
            <span className={"hero-digit" + (number > 9 ? " tiny" : "")}>
              {number}
            </span>
            <span className="hero-glyph">{profile.glyph}</span>
          </div>
        </div>
        <div className="result-hero-right">
          <h2 className="profile-title">{profile.title}</h2>
          <div className="profile-sub">{profile.subtitle}</div>
          <p className="profile-motto">{profile.motto}</p>
          {showMath && <MathStrip date={date} number={number} />}
        </div>
      </div>

      <div className="cards">
        <article className="card">
          <div className="card-eyebrow">
            <CardSigil glyph="I" />
            Twoja natura według Henriety
          </div>
          <div className="card-body">
            <p>{nature}</p>
          </div>
        </article>

        <article className="card">
          <div className="card-eyebrow">
            <CardSigil glyph="II" />
            Wieszczba na tydzień
          </div>
          <div className="card-body">
            <p>{week}</p>
          </div>
        </article>

        <article className="card">
          <div className="card-eyebrow">
            <CardSigil glyph="III" />
            Złota rada Henriety
          </div>
          <div className="card-body">
            <p>{advice}</p>
          </div>
        </article>
      </div>

      <div className="actions">
        <button className="btn-ghost" onClick={onReset}>
          ← Zapytaj o inną duszę
        </button>
        <button
          className="btn-ghost"
          onClick={() => {
            if (navigator.share) {
              navigator
                .share({
                  title: "Pszczoła Henrieta",
                  text: `Moja liczba życiowa według Pszczoły Henriety to ${number} — ${profile.title}. „${profile.motto}”`,
                })
                .catch(() => {});
            } else {
              navigator.clipboard?.writeText(
                `Moja liczba życiowa to ${number} — ${profile.title}. „${profile.motto}” — wg Pszczoły Henriety`
              );
              alert("Skopiowane do schowka. Henrieta gratuluje gestu.");
            }
          }}
        >
          Udostępnij wieszczbę
        </button>
      </div>

      <section className="share-preview" aria-label="Karta na LinkedIn">
        <div className="share-preview-eyebrow">
          Twoja karta na LinkedIn
        </div>
        <img
          src={cardUrl}
          alt={`Karta numerologiczna — liczba ${number}, ${profile.title}`}
          className="share-preview-img"
        />
        <a
          className="btn-ask btn-ask-download"
          href={cardUrl}
          download={`henrieta-${number}.png`}
          target="_blank"
          rel="noopener"
        >
          Pobierz grafikę
        </a>
      </section>
    </div>
  );
}

// ============================================================
// Tła ozdobne
// ============================================================
function Stars({ count = 24 }) {
  const stars = useMemo(
    () =>
      Array.from({ length: count }, (_, i) => ({
        x: Math.random() * 100,
        y: Math.random() * 100,
        size: 1 + Math.random() * 2.5,
        delay: Math.random() * 7,
        dur: 5 + Math.random() * 4,
      })),
    [count]
  );
  return (
    <div className="stars" aria-hidden="true">
      {stars.map((s, i) => (
        <span
          key={i}
          className="star"
          style={{
            left: s.x + "%",
            top: s.y + "%",
            width: s.size + "px",
            height: s.size + "px",
            animationDelay: s.delay + "s",
            animationDuration: s.dur + "s",
          }}
        />
      ))}
    </div>
  );
}

function HoneycombPattern() {
  return (
    <svg
      className="honeycomb-pattern"
      aria-hidden="true"
      xmlns="http://www.w3.org/2000/svg"
    >
      <defs>
        <pattern
          id="hex-grid"
          width="56"
          height="48"
          patternUnits="userSpaceOnUse"
        >
          <path
            d="M28 0 L56 14 L56 34 L28 48 L0 34 L0 14 Z"
            fill="none"
            stroke="var(--hex-line)"
            strokeWidth="1"
          />
        </pattern>
      </defs>
      <rect width="100%" height="100%" fill="url(#hex-grid)" />
    </svg>
  );
}

// ============================================================
// Aplikacja
// ============================================================
const MUTE_KEY = "henrieta.muted.v1";

function App() {
  const tweaks = TWEAKS;
  const [stage, setStage] = useState("idle"); // idle | casting | result
  const [form, setForm] = useState({ name: "", d: "", m: "", y: "" });
  const [date, setDate] = useState(null);
  const [number, setNumber] = useState(null);
  const [name, setName] = useState("");
  const [gender, setGender] = useState("f");
  const [error, setError] = useState("");
  const [muted, setMuted] = useState(() => {
    try { return localStorage.getItem(MUTE_KEY) === "1"; } catch (e) { return false; }
  });
  const audioRef = useRef(null);

  // motyw na <body>
  useEffect(() => {
    const themeClasses = ["theme-sad", "theme-czarna"];
    document.body.classList.remove(...themeClasses);
    if (tweaks.theme === "sad") document.body.classList.add("theme-sad");
    if (tweaks.theme === "czarna") document.body.classList.add("theme-czarna");
  }, [tweaks.theme]);

  // muzyka tła — autoplay przy pierwszej interakcji (przeglądarki blokują wcześniej)
  useEffect(() => {
    const audio = audioRef.current;
    if (!audio) return;
    audio.volume = 0.28;
    audio.muted = muted;
    const tryPlay = () => { audio.play().catch(() => {}); };
    tryPlay();
    const onGesture = () => {
      tryPlay();
      window.removeEventListener("pointerdown", onGesture);
      window.removeEventListener("keydown", onGesture);
      window.removeEventListener("touchstart", onGesture);
    };
    window.addEventListener("pointerdown", onGesture, { once: false });
    window.addEventListener("keydown", onGesture, { once: false });
    window.addEventListener("touchstart", onGesture, { once: false });
    return () => {
      window.removeEventListener("pointerdown", onGesture);
      window.removeEventListener("keydown", onGesture);
      window.removeEventListener("touchstart", onGesture);
    };
  }, []);

  // sync muted → audio + localStorage
  useEffect(() => {
    if (audioRef.current) audioRef.current.muted = muted;
    try { localStorage.setItem(MUTE_KEY, muted ? "1" : "0"); } catch (e) {}
  }, [muted]);

  const handleAsk = () => {
    setError("");
    const nm = normalizeName(form.name);
    if (!nm) {
      setError("Henrieta lubi po imieniu. Przedstaw się, a ona przedstawi Ci swoją mądrość.");
      return;
    }
    const d = parseInt(form.d, 10);
    const m = parseInt(form.m, 10);
    const y = parseInt(form.y, 10);
    if (!d || !m || !y) {
      setError("Henrieta potrzebuje pełnej daty. Inaczej tylko zgaduje.");
      return;
    }
    if (d < 1 || d > 31 || m < 1 || m > 12) {
      setError("Ta data wygląda jak z innego wymiaru. Spróbuj jeszcze raz.");
      return;
    }
    if (y < 1900 || y > 2099) {
      setError("Henrieta nie czyta z dat sprzed 1900 i z przyszłości po 2099. Jesteśmy poważni, prawda?!");
      return;
    }
    const iso = `${y}-${String(m).padStart(2, "0")}-${String(d).padStart(2, "0")}`;
    const n = lifePathNumber(iso);
    if (!n) {
      setError("Coś się posypało w plastrze. Henrieta prosi spróbować ponownie.");
      return;
    }
    setName(nm);
    setGender(inferGender(nm));
    setDate(iso);
    setNumber(n);
    setStage("casting");
    setTimeout(() => setStage("result"), 2600);
  };

  const handleReset = () => {
    setStage("idle");
    setNumber(null);
    setError("");
    window.scrollTo({ top: 0, behavior: "smooth" });
  };

  return (
    <>
      <audio
        ref={audioRef}
        src="fairytale.mp3"
        loop
        preload="auto"
        aria-hidden="true"
      />

      <div className="honeycomb-bg" />
      <HoneycombPattern />
      {tweaks.showStars && <Stars count={26} />}

      <main className="app">
        {/* <header className="crest">
          <span className="crest-label">Pasieka Wieszczbiarska ✦ ad. {new Date().getFullYear()}</span>
        </header> */}

        <h1 className="title-wordmark">Pszczoła Henrieta</h1>
        <div className="title-pszczola">numerologia z ula ✦ od 1834 roku</div>

        {stage === "idle" && (
          <div className="stage">
            <div className="orb-wrap">
              <div className="orb-aura" />
              <Henrieta buzzIdle={tweaks.buzz} eyes="open" />
              <IdleBubble />
            </div>

            <div className="invocation">
              <p className="invocation-quote">
                Podaj dzień, w którym świat<br/>po raz pierwszy usłyszał Twoje bzyczenie.
              </p>
              <p className="invocation-sub">
                Henrieta odczyta liczbę życiową, naturę duszy i  da Ci jedną radę, która prawdopodobnie zadziała.
              </p>
            </div>

            <DateForm
              value={form}
              onChange={setForm}
              onSubmit={handleAsk}
            />

            {error && <div className="error-line">{error}</div>}

            <button className="btn-ask" onClick={handleAsk}>
              Zapytaj Henriety
            </button>

            <button
              type="button"
              className="mute-btn"
              onClick={() => setMuted((m) => !m)}
              aria-pressed={muted}
              aria-label={muted ? "Włącz dźwięki" : "Wycisz dźwięki"}
            >
              <span className="mute-ico" aria-hidden="true">{muted ? "🔇" : "🔊"}</span>
              <span>{muted ? "Włącz dźwięki" : "Wycisz dźwięki"}</span>
            </button>

            <p className="disclaimer">
              Henrieta jest pszczołą i nie ponosi odpowiedzialności za sprawdzanie się przepowiedni,
              cudze emocje ani za ewentualne nieprzewidziane spotkania z osami.
            </p>
          </div>
        )}

        {stage === "casting" && <Casting tickKey={number} />}

        {stage === "result" && number !== null && (
          <Result
            number={number}
            date={date}
            name={name}
            gender={gender}
            onReset={handleReset}
            tone={tweaks.tone}
            showMath={tweaks.showMath}
          />
        )}
{/* 
        <div className="bee-footer">
          „Bzz.” — Henrieta
        </div> */}
      </main>

    </>
  );
}

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