/* ============================================================
   Paella — аккаунты «фуди»: регистрация/вход + синхронизация профиля.
   Бэкенд: window.PAELLA_API (сейчас ноут через Cloudflare-туннель, позже Timeweb).
   Токен: paella_auth_v1. Состояние профиля (сохранёнки, рестораны, паспорт,
   аватар) мёржится с сервером при входе и дозаписывается раз в 15 секунд.
   Тон онбординга: «сообщество фуди» — тепло и с характером, без сюсюканья.
   ============================================================ */

const PAELLA_API = window.PAELLA_API || "http://localhost:8787";

/* реферальная ссылка: paellafood.ru/?ref=<id> — запоминаем до регистрации */
(function () {
  try {
    const m = location.search.match(/[?&]ref=(\d+)/);
    if (m) localStorage.setItem("paella_ref", m[1]);
  } catch (e) {}
})();

async function paellaApi(path, { method = "GET", body, token } = {}) {
  const ctrl = new AbortController();
  const t = setTimeout(() => ctrl.abort(), 12000);
  try {
    const res = await fetch(PAELLA_API + path, {
      method,
      signal: ctrl.signal,
      headers: {
        "Content-Type": "application/json",
        ...(token ? { Authorization: "Bearer " + token } : {}),
      },
      body: body ? JSON.stringify(body) : undefined,
    });
    const data = await res.json().catch(() => ({}));
    if (!res.ok) throw { api: true, status: res.status, message: data.error || "Что-то пошло не так" };
    return data;
  } catch (e) {
    if (e.api) throw e;
    throw { offline: true, message: "Сервер отдыхает 😴 Попробуй через минуту — пока всё сохраняется на этом устройстве." };
  } finally { clearTimeout(t); }
}

/* ---------- стор аккаунта (observable, как VisitedStore) ---------- */
const AuthStore = (function () {
  const KEY = "paella_auth_v1";
  let data = null;
  try { data = JSON.parse(localStorage.getItem(KEY) || "null"); } catch (e) { data = null; }
  const subs = new Set();
  const save = () => { try { data ? localStorage.setItem(KEY, JSON.stringify(data)) : localStorage.removeItem(KEY); } catch (e) {} subs.forEach(f => f()); };
  return {
    user: () => data && data.user || null,
    token: () => data && data.token || null,
    set: (token, user) => { data = { token, user }; save(); },
    logout: () => { data = null; save(); },
    subscribe: (f) => { subs.add(f); return () => subs.delete(f); },
  };
})();
function useAuth() {
  const [, force] = useState(0);
  useEffect(() => AuthStore.subscribe(() => force(x => x + 1)), []);
  return AuthStore;
}

/* ---------- синхронизация состояния профиля ---------- */
const SYNC_KEYS = {
  saved: "paella_saved_v1",            // блюда (массив id)
  savedRests: "paella_saved_rests_v1", // рестораны (массив id)
  visited: "paella_visited_v1",        // паспорт мест (объект)
  avatar: "paella_avatar_v1",          // аватар
};
function collectLocalState() {
  const out = {};
  for (const [k, key] of Object.entries(SYNC_KEYS)) {
    try { out[k] = JSON.parse(localStorage.getItem(key) || "null"); } catch (e) { out[k] = null; }
  }
  return out;
}
function mergeStates(server, local) {
  const uniq = (a, b) => [...new Set([...(a || []), ...(b || [])])];
  const visited = { ...(server.visited || {}) };
  for (const [id, v] of Object.entries(local.visited || {})) {
    const sv = visited[id];
    // берём запись с бОльшим числом отзывов, при равенстве — более свежую
    if (!sv || (v.reviews || []).length > (sv.reviews || []).length ||
        ((v.reviews || []).length === (sv.reviews || []).length && (v.visitedAt || 0) >= (sv.visitedAt || 0))) visited[id] = v;
  }
  return {
    saved: uniq(server.saved, local.saved),
    savedRests: uniq(server.savedRests, local.savedRests),
    visited,
    avatar: local.avatar || server.avatar || null,
  };
}
async function pullMergeApply(token) {
  const { state: server } = await paellaApi("/api/me/state", { token });
  const merged = mergeStates(server || {}, collectLocalState());
  for (const [k, key] of Object.entries(SYNC_KEYS)) {
    try { merged[k] == null ? localStorage.removeItem(key) : localStorage.setItem(key, JSON.stringify(merged[k])); } catch (e) {}
  }
  await paellaApi("/api/me/state", { method: "PUT", token, body: { state: merged } });
}
/* фоновая дозапись: раз в 15 с (если что-то поменялось) + при сворачивании вкладки */
(function startPushLoop() {
  let last = "";
  const push = async () => {
    const token = AuthStore.token();
    if (!token) return;
    const snap = JSON.stringify(collectLocalState());
    if (snap === last) return;
    try { await paellaApi("/api/me/state", { method: "PUT", token, body: { state: JSON.parse(snap) } }); last = snap; } catch (e) {}
  };
  setInterval(push, 15000);
  document.addEventListener("visibilitychange", () => { if (document.visibilityState === "hidden") push(); });
})();

/* ---------- нормализация логина (зеркало серверной) ---------- */
function normLoginClient(raw) {
  const s = (raw || "").trim();
  if (!s) return { ok: false, err: "Укажи почту или телефон" };
  if (s.includes("@")) {
    if (!/^[^\s@]+@[^\s@]+\.[^\s@]{2,}$/.test(s)) return { ok: false, err: "Это не похоже на почту 🤔" };
    return { ok: true, value: s.toLowerCase() };
  }
  const digits = s.replace(/\D/g, "");
  if (digits.length < 10) return { ok: false, err: "Это не похоже на почту или телефон 🤔" };
  return { ok: true, value: s };
}

/* ---------- онбординг + форма ---------- */
function FoodieAuth({ ctx }) {
  const [mode, setMode] = useState("register");   // register | login
  const [name, setName] = useState("");
  const [login, setLogin] = useState("");
  const [pass, setPass] = useState("");
  const [showPass, setShowPass] = useState(false);
  const [busy, setBusy] = useState(false);
  const [err, setErr] = useState("");

  const submit = async () => {
    setErr("");
    const nl = normLoginClient(login);
    if (!nl.ok) { setErr(nl.err); return; }
    if ((pass || "").length < 6) { setErr("Пароль — минимум 6 символов"); return; }
    if (mode === "register" && !(name || "").trim()) { setErr("Скажи, как тебя зовут — так теплее"); return; }
    setBusy(true);
    try {
      const path = mode === "register" ? "/api/auth/register" : "/api/auth/login";
      let refCode = null;
      try { refCode = localStorage.getItem("paella_ref"); } catch (e) {}
      const body = mode === "register" ? { login: nl.value, password: pass, name: name.trim(), ref: refCode || undefined } : { login: nl.value, password: pass };
      const r = await paellaApi(path, { method: "POST", body });
      if (mode === "register") { try { localStorage.removeItem("paella_ref"); } catch (e) {} }
      AuthStore.set(r.token, r.user);
      try { await pullMergeApply(r.token); } catch (e) {}
      ctx.toast && ctx.toast(mode === "register" ? "Добро пожаловать в фуди, " + r.user.name + "!" : "С возвращением, " + r.user.name + "!");
      setTimeout(() => window.location.reload(), 700);   // сторы перечитывают смёрженное состояние
    } catch (e) {
      setErr(e.message || "Что-то пошло не так");
    } finally { setBusy(false); }
  };

  return (
    <section className="sec">
      <div className="panel foodie-hero">
        <div className="foodie-copy">
          <span className="eyebrow">Сообщество Paella</span>
          <h2 className="foodie-title">Привет, фуди! 👋</h2>
          <p>
            Фуди ходят не «в ресторан» — они идут <b>за блюдом</b>. Мы собрали {""}
            <b>9 500 блюд</b> и <b>85 000 честных оценок</b>, чтобы твой следующий обед не был лотереей.
          </p>
          <div className="foodie-perks">
            <div><span>🔖</span> Сохранённые блюда и рестораны — на любом устройстве</div>
            <div><span>🚩</span> Паспорт мест: где был, что ел, что зашло</div>
            <div><span>✨</span> AI выучит твой вкус и будет подкидывать «твоё» <i>(скоро)</i></div>
          </div>
        </div>

        <div className="foodie-form">
          <div className="foodie-tabs">
            <button className={mode === "register" ? "on" : ""} onClick={() => { setMode("register"); setErr(""); }}>Стать фуди</button>
            <button className={mode === "login" ? "on" : ""} onClick={() => { setMode("login"); setErr(""); }}>Я уже фуди</button>
          </div>
          {mode === "register" && (
            <div className="field">
              <label>Имя</label>
              <input value={name} onChange={(e) => setName(e.target.value)} placeholder="Как тебя зовут?" autoComplete="name" />
            </div>
          )}
          <div className="field">
            <label>Почта или телефон</label>
            <input value={login} onChange={(e) => setLogin(e.target.value)} placeholder="foodie@mail.ru или +7 999 …" autoComplete="username" inputMode="email" />
          </div>
          <div className="field">
            <label>Пароль</label>
            <div style={{ position: "relative" }}>
              <input type={showPass ? "text" : "password"} value={pass} onChange={(e) => setPass(e.target.value)}
                placeholder={mode === "register" ? "Придумай, минимум 6 символов" : "Твой пароль"}
                autoComplete={mode === "register" ? "new-password" : "current-password"}
                onKeyDown={(e) => e.key === "Enter" && submit()} style={{ width: "100%", paddingRight: 42 }} />
              <button onClick={() => setShowPass(v => !v)} aria-label="Показать пароль"
                style={{ position: "absolute", right: 10, top: "50%", transform: "translateY(-50%)", color: "var(--ink-3)" }}>
                <Icon name="eye" size={17} />
              </button>
            </div>
          </div>
          {err && <div className="foodie-err">{err}</div>}
          <button className="foodie-cta" disabled={busy} onClick={submit}>
            {busy ? "Секунду…" : mode === "register" ? <>Вступить в сообщество 🥘</> : <>Войти <Icon name="arrowRight" size={16} /></>}
          </button>
          <p className="muted" style={{ fontSize: 11.5, margin: "10px 0 0", lineHeight: 1.45, textAlign: "center" }}>
            Никакого спама — только еда. Гостевые сохранёнки с этого устройства заберём с собой.
          </p>
        </div>
      </div>
    </section>
  );
}

Object.assign(window, { AuthStore, useAuth, FoodieAuth, paellaApi });
