/* ============================================================
   app.jsx — shell: navigation, screen routing, Tweaks.
   ============================================================ */
const React = window.React;
const { useState, useEffect } = React;
const Icon = window.Icon;

const TWEAK_DEFAULTS = /*EDITMODE-BEGIN*/{
  "navStyle": "rail",
  "scaleVariant": "ring",
  "habitsVariant": "list",
  "libraryLayout": "grid",
  "accent": "#D7321B",
  "showFootRing": true
}/*EDITMODE-END*/;

/* ---- Login screen (no public registration) -------------------- */
function LoginScreen({ onAuth }) {
  const [login, setLogin] = useState("");
  const [password, setPassword] = useState("");
  const [error, setError] = useState(null);
  const [busy, setBusy] = useState(false);

  const submit = async (e) => {
    e.preventDefault();
    setError(null);
    setBusy(true);
    try {
      await window.authLogin(login, password);
      onAuth();
    } catch (err) {
      const msg = err.message;
      if (msg === "wrong login or password") setError("Неверный логин или пароль");
      else if (msg === "account disabled") setError("Аккаунт отключён");
      else setError(msg);
    } finally {
      setBusy(false);
    }
  };

  return (
    <div style={{ display: "grid", placeItems: "center", minHeight: "100vh", background: "var(--paper-00)", padding: 20 }}>
      <div style={{ width: "100%", maxWidth: 380 }}>
        <div style={{ textAlign: "center", marginBottom: 40 }}>
          <div style={{ width: 48, height: 48, background: "var(--ink-100)", display: "inline-grid", placeItems: "center", marginBottom: 16 }}>
            <span style={{ color: "var(--signal)", fontFamily: "var(--font-slab)", fontWeight: 700, fontSize: 30, lineHeight: 1 }}>П</span>
          </div>
          <div style={{ fontFamily: "var(--font-slab)", fontWeight: 700, fontSize: 26 }}>ПЛАНЕР</div>
          <div className="e-label" style={{ letterSpacing: "0.2em", marginTop: 4 }}>СВОД №.06</div>
        </div>

        <form onSubmit={submit} style={{ display: "flex", flexDirection: "column", gap: 12 }}>
          <div className="e-label" style={{ textAlign: "center", fontSize: 14, marginBottom: 4 }}>Вход</div>

          <input value={login} onChange={(e) => setLogin(e.target.value)} placeholder="Логин" autoFocus autoComplete="username"
            style={{ width: "100%", border: "2px solid var(--ink-100)", background: "var(--paper-00)", padding: "12px 14px", fontFamily: "var(--font-slab)", fontSize: 16, outline: "none", boxSizing: "border-box" }} />

          <input type="password" value={password} onChange={(e) => setPassword(e.target.value)} placeholder="Пароль" autoComplete="current-password"
            style={{ width: "100%", border: "2px solid var(--ink-100)", background: "var(--paper-00)", padding: "12px 14px", fontFamily: "var(--font-slab)", fontSize: 16, outline: "none", boxSizing: "border-box" }} />

          {error && (
            <div style={{ color: "var(--signal)", fontFamily: "var(--font-mono)", fontSize: 13, textAlign: "center" }}>{error}</div>
          )}

          <button type="submit" disabled={busy}
            style={{ width: "100%", padding: "12px 14px", border: "2px solid var(--ink-100)", background: "var(--ink-100)", color: "var(--paper-00)", fontFamily: "var(--font-mono)", fontSize: 14, letterSpacing: "0.06em", textTransform: "uppercase", cursor: "pointer" }}>
            {busy ? "..." : "Войти"}
          </button>
        </form>
      </div>
    </div>
  );
}

/* ---- Admin Panel ----------------------------------------------- */
function AdminPanel() {
  const [users, setUsers] = useState([]);
  const [newLogin, setNewLogin] = useState("");
  const [newPassword, setNewPassword] = useState("");
  const [newName, setNewName] = useState("");
  const [pwUserId, setPwUserId] = useState(null);
  const [pwValue, setPwValue] = useState("");
  const [error, setError] = useState(null);
  const [msg, setMsg] = useState(null);

  const load = async () => {
    const r = await window.authFetch("/api/admin/users");
    const d = await r.json();
    if (d.users) setUsers(d.users);
  };

  useEffect(() => { load(); }, []);

  const flash = (text) => { setMsg(text); setTimeout(() => setMsg(null), 2500); };

  const createUser = async (e) => {
    e.preventDefault();
    setError(null);
    if (!newLogin.trim() || !newPassword) { setError("Введите логин и пароль"); return; }
    const r = await window.authFetch("/api/admin/users", {
      method: "POST",
      headers: { "Content-Type": "application/json" },
      body: JSON.stringify({ login: newLogin.trim(), password: newPassword, name: newName.trim() || newLogin.trim() }),
    });
    const d = await r.json();
    if (d.error) { setError(d.error === "login already taken" ? "Логин уже занят" : d.error); return; }
    setNewLogin(""); setNewPassword(""); setNewName("");
    flash("Пользователь создан");
    load();
  };

  const toggleUser = async (id) => {
    await window.authFetch("/api/admin/users/" + id + "/toggle", { method: "POST" });
    load();
  };

  const changePassword = async (id) => {
    if (!pwValue || pwValue.length < 4) { setError("Пароль мин. 4 символа"); return; }
    setError(null);
    const r = await window.authFetch("/api/admin/users/" + id + "/password", {
      method: "POST",
      headers: { "Content-Type": "application/json" },
      body: JSON.stringify({ password: pwValue }),
    });
    const d = await r.json();
    if (d.error) { setError(d.error); return; }
    setPwUserId(null); setPwValue("");
    flash("Пароль изменён");
  };

  const inputStyle = { border: "2px solid var(--ink-100)", background: "var(--paper-00)", padding: "10px 12px", fontFamily: "var(--font-slab)", fontSize: 15, outline: "none", boxSizing: "border-box", width: "100%" };
  const btnStyle = { padding: "10px 16px", border: "2px solid var(--ink-100)", background: "var(--ink-100)", color: "var(--paper-00)", fontFamily: "var(--font-mono)", fontSize: 13, letterSpacing: "0.06em", textTransform: "uppercase", cursor: "pointer" };
  const ghostBtn = { ...btnStyle, background: "transparent", color: "var(--ink-100)" };

  return (
    <div style={{ display: "grid", placeItems: "center start", minHeight: "100vh", background: "var(--paper-00)", padding: "40px 20px" }}>
      <div style={{ width: "100%", maxWidth: 600, margin: "0 auto" }}>
        <div style={{ display: "flex", alignItems: "center", justifyContent: "space-between", marginBottom: 32 }}>
          <div>
            <div style={{ fontFamily: "var(--font-slab)", fontWeight: 700, fontSize: 24 }}>Панель администратора</div>
            <div className="e-label" style={{ marginTop: 4 }}>Управление пользователями</div>
          </div>
          <button onClick={() => window.authLogout()} style={ghostBtn}>Выйти</button>
        </div>

        {msg && <div style={{ background: "var(--ink-100)", color: "var(--paper-00)", padding: "10px 14px", fontFamily: "var(--font-mono)", fontSize: 13, marginBottom: 16 }}>{msg}</div>}

        {/* create user form */}
        <div style={{ border: "2px solid var(--ink-100)", padding: 20, marginBottom: 32 }}>
          <div className="e-label" style={{ marginBottom: 12, fontSize: 13 }}>Создать пользователя</div>
          <form onSubmit={createUser} style={{ display: "flex", flexDirection: "column", gap: 10 }}>
            <input value={newLogin} onChange={(e) => setNewLogin(e.target.value)} placeholder="Логин" style={inputStyle} />
            <input value={newName} onChange={(e) => setNewName(e.target.value)} placeholder="Имя (необязательно)" style={{ ...inputStyle, borderColor: "var(--ink-40)" }} />
            <input type="password" value={newPassword} onChange={(e) => setNewPassword(e.target.value)} placeholder="Пароль" style={inputStyle} />
            {error && <div style={{ color: "var(--signal)", fontFamily: "var(--font-mono)", fontSize: 13 }}>{error}</div>}
            <button type="submit" style={btnStyle}>Создать</button>
          </form>
        </div>

        {/* user list */}
        <div className="e-label" style={{ marginBottom: 12, fontSize: 13 }}>Пользователи ({users.length})</div>
        <div style={{ display: "flex", flexDirection: "column", gap: 8 }}>
          {users.map((u) => (
            <div key={u.id} style={{ border: "2px solid " + (u.disabled ? "var(--ink-40)" : "var(--ink-100)"), padding: "12px 16px", opacity: u.disabled ? 0.5 : 1 }}>
              <div style={{ display: "flex", alignItems: "center", justifyContent: "space-between", gap: 12 }}>
                <div style={{ flex: 1 }}>
                  <span style={{ fontFamily: "var(--font-slab)", fontWeight: 700, fontSize: 16 }}>{u.login}</span>
                  {u.name && u.name !== u.login && <span style={{ marginLeft: 8, color: "var(--text-muted)", fontSize: 14 }}>{u.name}</span>}
                  {u.is_admin && <span style={{ marginLeft: 8, fontFamily: "var(--font-mono)", fontSize: 11, color: "var(--signal)", letterSpacing: "0.05em" }}>ADMIN</span>}
                  {u.disabled && <span style={{ marginLeft: 8, fontFamily: "var(--font-mono)", fontSize: 11, color: "var(--text-muted)" }}>ОТКЛЮЧЁН</span>}
                </div>
                <div style={{ display: "flex", gap: 6 }}>
                  {!u.is_admin && (
                    <>
                      <button onClick={() => toggleUser(u.id)} style={{ ...ghostBtn, padding: "6px 10px", fontSize: 11 }}>
                        {u.disabled ? "Включить" : "Отключить"}
                      </button>
                      <button onClick={() => { setPwUserId(pwUserId === u.id ? null : u.id); setPwValue(""); setError(null); }} style={{ ...ghostBtn, padding: "6px 10px", fontSize: 11 }}>
                        Пароль
                      </button>
                    </>
                  )}
                </div>
              </div>
              {pwUserId === u.id && (
                <div style={{ display: "flex", gap: 8, marginTop: 10 }}>
                  <input type="password" value={pwValue} onChange={(e) => setPwValue(e.target.value)} placeholder="Новый пароль"
                    style={{ ...inputStyle, flex: 1 }} />
                  <button onClick={() => changePassword(u.id)} style={{ ...btnStyle, padding: "8px 14px", fontSize: 12 }}>Сменить</button>
                </div>
              )}
            </div>
          ))}
        </div>
      </div>
    </div>
  );
}

const NAV = [
  { group: "Планер", items: [
    { id: "today", label: "Сегодня", icon: "today" },
    { id: "calendar", label: "Расписание", icon: "calendar" },
    { id: "habits", label: "Привычки", icon: "habits" },
  ]},
  { group: "Знание", items: [
    { id: "library", label: "Библиотека", icon: "library" },
    { id: "courses", label: "Курсы", icon: "course" },
    { id: "notes", label: "Заметки", icon: "notes" },
  ]},
  { group: "Обзор", items: [
    { id: "graph", label: "Граф связей", icon: "graph" },
    { id: "achievements", label: "Достижения", icon: "star" },
    { id: "stats", label: "Статистика", icon: "stats" },
    { id: "cabinet", label: "Кабинет", icon: "user" },
  ]},
];

/* which top-level nav item is highlighted for a given route */
const ROUTE_PARENT = { material: "library", addMaterial: "library", course: "courses" };

function App() {
  const [authState, setAuthState] = useState(window.AuthToken ? "checking" : "login");

  const handleAuth = () => {
    if (window.AuthUser && window.AuthUser.is_admin) {
      setAuthState("admin");
    } else {
      window.loadServerState();
      setAuthState("ready");
    }
  };

  useEffect(() => {
    if (authState !== "checking") return;
    window.authCheck().then((user) => {
      if (user) {
        handleAuth();
      } else {
        setAuthState("login");
      }
    });
  }, [authState]);

  if (authState === "checking") {
    return (
      <div style={{ display: "grid", placeItems: "center", minHeight: "100vh", background: "var(--paper-00)" }}>
        <div style={{ fontFamily: "var(--font-slab)", fontSize: 18, color: "var(--text-muted)" }}>Загрузка...</div>
      </div>
    );
  }

  if (authState === "login") {
    return <LoginScreen onAuth={handleAuth} />;
  }

  if (authState === "admin") {
    return <AdminPanel />;
  }

  return <AppInner />;
}

function AppInner() {
  const [t, setTweak] = window.useTweaks(TWEAK_DEFAULTS);
  const state = window.useStore();
  const day = window.computeDay(state);

  // tick every second while a stopwatch is running, so live clocks update
  const [, forceTick] = useState(0);
  useEffect(() => {
    if (!state.timer) return;
    const iv = setInterval(() => forceTick((n) => n + 1), 1000);
    return () => clearInterval(iv);
  }, [state.timer]);

  const [route, setRoute] = useState(() => {
    try { const r = JSON.parse(localStorage.getItem("planer-route")); if (r && r.screen) return r; } catch (e) {}
    return { screen: "today" };
  });
  const nav = (r) => {
    setRoute(r);
    try { localStorage.setItem("planer-route", JSON.stringify(r)); } catch (e) {}
    const main = document.querySelector(".main");
    if (main) main.scrollTop = 0;
  };

  // live accent override
  useEffect(() => {
    document.documentElement.style.setProperty("--signal", t.accent);
  }, [t.accent]);

  const Screen = window.Screens[route.screen] || window.Screens.today;
  const activeTop = ROUTE_PARENT[route.screen] || route.screen;
  const counts = {
    today: state.tasks.filter((x) => !x.done).length,
    library: state.materials.length,
    courses: state.courses.length,
    notes: state.notes.length,
    achievements: (state.achievements || []).length,
  };

  const navProps = { state, day, tweaks: t, nav, id: route.id, focus: route.focus, focusId: route.id };
  const topNav = t.navStyle === "topnav";

  const NavItems = ({ horizontal }) => (
    <>
      {NAV.map((grp) => (
        <React.Fragment key={grp.group}>
          {!horizontal && <div className="nav__group-label">{grp.group}</div>}
          {grp.items.map((it) => (
            <button key={it.id} className={"nav__item" + (activeTop === it.id ? " nav__item--active" : "")}
              onClick={() => nav({ screen: it.id })}>
              <span className="nav__icon"><Icon name={it.icon} size={20} /></span>
              <span className="nav__label">{it.label}</span>
              {!horizontal && counts[it.id] != null && <span className="nav__count">{counts[it.id]}</span>}
            </button>
          ))}
        </React.Fragment>
      ))}
    </>
  );

  return (
    <div className={"app" + (topNav ? " app--topnav" : t.navStyle === "wide" ? " app--rail-wide" : "")}>
      {topNav ? (
        <div className="topnav">
          <div className="topnav__brand"><Wordmark /></div>
          <NavItems horizontal />
          <div className="topnav__spacer" />
          <FootRing day={day} onClick={() => nav({ screen: "cabinet" })} compact />
          <WorkRing state={state} nav={nav} compact />
        </div>
      ) : (
        <nav className="nav">
          <div className="nav__brand"><Wordmark /></div>
          <div className="nav__list"><NavItems /></div>
          {t.showFootRing && <FootRing day={day} onClick={() => nav({ screen: "cabinet" })} />}
          <WorkRing state={state} nav={nav} />
        </nav>
      )}

      <main className="main">
        <Screen {...navProps} />
      </main>

      <window.Toaster />

      <window.TweaksPanel>
        <window.TweakSection label="Навигация" />
        <window.TweakRadio label="Меню" value={t.navStyle} options={["rail", "wide", "topnav"]} onChange={(v) => setTweak("navStyle", v)} />
        <window.TweakToggle label="Кольцо баллов в меню" value={t.showFootRing} onChange={(v) => setTweak("showFootRing", v)} />
        <window.TweakSection label="Шкала баллов" />
        <window.TweakRadio label="Вид" value={t.scaleVariant} options={["ring", "bar", "thermo"]} onChange={(v) => setTweak("scaleVariant", v)} />
        <window.TweakSection label="Журнал привычек" />
        <window.TweakRadio label="Раскладка" value={t.habitsVariant} options={["list", "week"]} onChange={(v) => setTweak("habitsVariant", v)} />
        <window.TweakSection label="Библиотека" />
        <window.TweakRadio label="Вид по умолчанию" value={t.libraryLayout} options={["grid", "list", "shelf"]} onChange={(v) => setTweak("libraryLayout", v)} />
        <window.TweakSection label="Акцент" />
        <window.TweakColor label="Сигнальный цвет" value={t.accent} options={["#D7321B", "#1F6FEB", "#1F8A5B", "#C2410C", "#16140F"]} onChange={(v) => setTweak("accent", v)} />
        <window.TweakSection label="Данные" />
        <window.TweakButton label="Сбросить демо-данные" onClick={() => window.PlannerActions.reset()}>Сбросить</window.TweakButton>
      </window.TweaksPanel>
    </div>
  );
}

function Wordmark() {
  return (
    <div style={{ display: "flex", alignItems: "center", gap: 10 }}>
      <div style={{ width: 30, height: 30, background: "var(--ink-100)", display: "grid", placeItems: "center", flex: "0 0 30px" }}>
        <span style={{ color: "var(--signal)", fontFamily: "var(--font-slab)", fontWeight: 700, fontSize: 20, lineHeight: 1 }}>П</span>
      </div>
      <div style={{ lineHeight: 1 }}>
        <div style={{ fontFamily: "var(--font-slab)", fontWeight: 700, fontSize: 18, letterSpacing: "-0.01em" }}>ПЛАНЕР</div>
        <div className="e-label" style={{ fontSize: 10, letterSpacing: "0.2em" }}>СВОД №.06</div>
      </div>
    </div>
  );
}

function WorkRing({ state, nav, compact }) {
  const workCourse = (state.courses || []).find((c) => c.isWork);
  if (!workCourse) return null;
  const allLog = window.courseTimeLog(workCourse);
  const weekSec = allLog.reduce((s, e) => s + window.entrySec(e), 0);
  const target = workCourse.weekTarget || 15 * 3600;

  const frac = Math.max(0, Math.min(weekSec / Math.max(target, 1), 1));
  const over = weekSec >= target;
  const hh = (sec) => { const h = Math.floor(sec / 3600); const m = Math.floor((sec % 3600) / 60); return h + "ч " + (m < 10 ? "0" : "") + m + "м"; };

  const size = compact ? 34 : 44;
  const thick = size * 0.16;
  const r = (size - thick) / 2;
  const c = 2 * Math.PI * r;
  const cx = size / 2;

  const ring = (
    <svg width={size} height={size} style={{ flex: "0 0 " + size + "px" }}>
      <circle cx={cx} cy={cx} r={r} fill="none" stroke="var(--paper-20)" strokeWidth={thick} />
      <circle cx={cx} cy={cx} r={r} fill="none" stroke={over ? "var(--ok, var(--signal))" : "var(--ink-60, var(--ink-100))"} strokeWidth={thick}
        strokeDasharray={`${c * frac} ${c}`} transform={`rotate(-90 ${cx} ${cx})`} />
    </svg>
  );

  const go = () => nav && nav({ screen: "course", id: workCourse.id });

  if (compact) {
    return (
      <div onClick={go} style={{ display: "flex", alignItems: "center", gap: 12, cursor: "pointer" }}>
        {ring}
        <div style={{ lineHeight: 1 }}>
          <div className="nav__foot-score" style={{ fontSize: 16 }}>{hh(weekSec)}</div>
          <div className="e-label" style={{ fontSize: 10 }}>/{hh(target)}</div>
        </div>
      </div>
    );
  }

  return (
    <div className="nav__foot" onClick={go} style={{ borderTop: "none", paddingTop: 0, marginTop: -4, cursor: "pointer" }}>
      {ring}
      <div className="nav__foot-meta">
        <span className="e-label">Работа</span>
        <span className="nav__foot-score" style={{ fontSize: 18 }}>{hh(weekSec)}<span style={{ fontSize: 12, color: "var(--text-faint)", fontWeight: 400 }}> /{hh(target)}</span></span>
      </div>
      <Icon name="arrow" size={14} style={{ marginLeft: "auto", color: "var(--text-faint)" }} />
    </div>
  );
}

function FootRing({ day, onClick, compact }) {
  const pct = Math.round((day.net / day.target) * 100);
  if (compact) {
    return (
      <div onClick={onClick} style={{ display: "flex", alignItems: "center", gap: 12, cursor: "pointer" }}>
        <MiniRing day={day} size={34} />
        <div style={{ lineHeight: 1 }}>
          <div className="nav__foot-score" style={{ fontSize: 20 }}>{day.net}</div>
          <div className="e-label" style={{ fontSize: 10 }}>{pct}% цели</div>
        </div>
      </div>
    );
  }
  return (
    <div className="nav__foot" onClick={onClick}>
      <MiniRing day={day} size={44} />
      <div className="nav__foot-meta">
        <span className="e-label">Сегодня</span>
        <span className="nav__foot-score">{day.net}<span style={{ fontSize: 13, color: "var(--text-faint)", fontWeight: 400 }}> /{day.target}</span></span>
      </div>
      <Icon name="arrow" size={16} style={{ marginLeft: "auto", color: "var(--text-faint)" }} />
    </div>
  );
}

function MiniRing({ day, size = 44 }) {
  const thick = size * 0.16;
  const r = (size - thick) / 2;
  const c = 2 * Math.PI * r;
  const frac = Math.max(0, Math.min(day.net / Math.max(day.target, 1), 1));
  const over = day.net >= day.target;
  const cx = size / 2;
  return (
    <svg width={size} height={size} style={{ flex: "0 0 " + size + "px" }}>
      <circle cx={cx} cy={cx} r={r} fill="none" stroke="var(--paper-20)" strokeWidth={thick} />
      <circle cx={cx} cy={cx} r={r} fill="none" stroke={over ? "var(--signal)" : "var(--ink-100)"} strokeWidth={thick}
        strokeDasharray={`${c * frac} ${c}`} transform={`rotate(-90 ${cx} ${cx})`} />
    </svg>
  );
}

window.PlannerApp = App;
