/* settings.jsx — раздел «Настройки»: категории-фильтры + базовые опции. */

function SettingsScreen({ theme, onToggleTheme }) {
  const settings = Store.useSettings();
  const cats = settings.categories || [];
  const [adding, setAdding] = React.useState(false);

  const setDensity = (d) => Store.patchSettings({ density: d });
  const setDefault = (k) => Store.patchSettings({ defaultCategory: k });
  const toggle = (k) => Store.patchSettings({ [k]: !settings[k] });

  return (
    <div>
      <ScreenHead title="Настройки" sub="Категории, внешний вид и поведение ИИ" />

      {/* --------------------------------------------------- КАТЕГОРИИ */}
      <Section title="Категории-фильтры" desc="По ним ИИ раскладывает записи. Встроенные можно переименовать и перекрасить, свои — удалить.">
        <div className="grid gap-2">
          {cats.map((c) => <CategoryRow key={c.key} cat={c} canDelete={!c.system} />)}
        </div>
        {adding ? (
          <CategoryRow draft onDone={() => setAdding(false)} />
        ) : (
          <button onClick={() => setAdding(true)} className="mt-2 inline-flex items-center gap-1.5 h-9 px-3 rounded-xl border border-dashed border-[var(--border-strong)] text-[13px] font-semibold text-[var(--muted)] hover:text-[var(--accent)] hover:border-[var(--accent)] transition">
            <Icon name="plus" size={16} /> Добавить категорию
          </button>
        )}
      </Section>

      {/* --------------------------------------------------- ВНЕШНИЙ ВИД */}
      <Section title="Внешний вид">
        <Row label="Тема" desc="Светлая или тёмная">
          <Segmented
            value={theme}
            onChange={(v) => { if (v !== theme) onToggleTheme(); }}
            options={[{ v: "light", label: "Светлая", icon: "sun" }, { v: "dark", label: "Тёмная", icon: "moon" }]}
          />
        </Row>
        <Row label="Плотность ленты" desc="Насколько компактны карточки">
          <Segmented
            value={settings.density}
            onChange={setDensity}
            options={[{ v: "cozy", label: "Просторно", icon: "rows" }, { v: "compact", label: "Компактно", icon: "grid" }]}
          />
        </Row>
        <Row label="Значок источника" desc="Показывать, откуда запись — Telegram или веб">
          <Toggle on={settings.showSource} onClick={() => toggle("showSource")} />
        </Row>
      </Section>

      {/* --------------------------------------------------- ИИ */}
      <Section title="Поведение ИИ">
        <Row label="Категория по умолчанию" desc="Куда падает запись, если ИИ не уверен">
          <div className="relative">
            <select value={settings.defaultCategory} onChange={(e) => setDefault(e.target.value)}
              className="appearance-none rounded-xl border border-[var(--border)] bg-[var(--surface-2)] pl-3 pr-8 h-10 text-sm text-[var(--text)] outline-none focus:border-[var(--accent)] transition cursor-pointer">
              {cats.map((c) => <option key={c.key} value={c.key}>{c.label}</option>)}
            </select>
            <Icon name="chevron" size={15} className="pointer-events-none absolute right-2.5 top-1/2 -translate-y-1/2 rotate-90 text-[var(--muted)]" />
          </div>
        </Row>
        <Row label="Авто-напоминания" desc="ИИ сам предлагает дату, если в тексте есть срок">
          <Toggle on={settings.autoReminders} onClick={() => toggle("autoReminders")} />
        </Row>
      </Section>

      {/* --------------------------------------------------- БЕЗОПАСНОСТЬ */}
      <Section title="Безопасность паролей">
        <Row label="Мастер-пароль" desc="Хранилище шифруется мастер-паролем прямо в браузере (zero-knowledge). Задаётся при первом входе в раздел «Пароли». Восстановить нельзя.">
          <span className="inline-flex items-center gap-1.5 text-[12px] font-semibold str-text-green whitespace-nowrap"><Icon name="lock" size={14} /> включён</span>
        </Row>
        <Row label="Автоскрытие пароля" desc="Скрывать показанный пароль через…">
          <div className="relative">
            <select value={settings.autoHidePw} onChange={(e) => Store.patchSettings({ autoHidePw: +e.target.value })}
              className="appearance-none rounded-xl border border-[var(--border)] bg-[var(--surface-2)] pl-3 pr-8 h-10 text-sm text-[var(--text)] outline-none focus:border-[var(--accent)] transition cursor-pointer">
              <option value={0}>не скрывать</option>
              <option value={10}>10 секунд</option>
              <option value={15}>15 секунд</option>
              <option value={30}>30 секунд</option>
            </select>
            <Icon name="chevron" size={15} className="pointer-events-none absolute right-2.5 top-1/2 -translate-y-1/2 rotate-90 text-[var(--muted)]" />
          </div>
        </Row>
      </Section>

      {/* --------------------------------------------------- АККАУНТ */}
      <AccountSection />

      {/* --------------------------------------------------- АДМИН */}
      <AdminSection />

      {/* --------------------------------------------------- ДАННЫЕ */}
      <Section title="Данные" desc="Архив и корзина доступны в разделе «Записи» переключателем сверху.">
        <Row label="Экспорт / бэкап" desc="Скачать все записи, напоминания и пароли в JSON">
          <ExportButton />
        </Row>
      </Section>
    </div>
  );
}

/* ----------------------------------------------------------- аккаунт: логин/пароль */
function AccountSection() {
  const [me, setMe] = React.useState(null);
  const [username, setUsername] = React.useState("");
  const [password, setPassword] = React.useState("");
  const [busy, setBusy] = React.useState(false);
  const [msg, setMsg] = React.useState(null); // {ok, text}

  React.useEffect(() => { api.getMe().then((u) => { setMe(u); setUsername(u.username || ""); }).catch(() => {}); }, []);

  const save = async () => {
    setMsg(null); setBusy(true);
    try {
      const r = await api.setCredentials({ username: username.trim(), password });
      setMe((m) => ({ ...m, username: (r.user && r.user.username) || username.trim(), has_password: true }));
      setPassword("");
      setMsg({ ok: true, text: "Сохранено. Теперь можно входить по логину и паролю." });
    } catch (e) {
      const code = e && e.status;
      setMsg({ ok: false, text: code === 409 ? "Этот логин уже занят." : code === 422 ? "Логин 3–64 символа (буквы/цифры/._-), пароль от 6 символов." : "Не удалось сохранить." });
    } finally { setBusy(false); }
  };

  return (
    <Section title="Аккаунт" desc="Задай логин и пароль, чтобы входить без Telegram. Доступно, потому что ты вошёл через Telegram.">
      {me && me.username && (
        <Row label="Текущий логин" desc="Используется для входа без Telegram">
          <span className="text-[13px] font-semibold text-[var(--text)] mono">{me.username}</span>
        </Row>
      )}
      <div className="grid sm:grid-cols-2 gap-3 mt-1">
        <input value={username} onChange={(e) => setUsername(e.target.value)} placeholder="логин" autoCapitalize="none"
          className="w-full rounded-xl border border-[var(--border)] bg-[var(--surface-2)] px-3.5 h-11 text-sm text-[var(--text)] outline-none focus:border-[var(--accent)] transition" />
        <input type="password" value={password} onChange={(e) => setPassword(e.target.value)} placeholder={me && me.has_password ? "новый пароль" : "пароль"}
          className="w-full rounded-xl border border-[var(--border)] bg-[var(--surface-2)] px-3.5 h-11 text-sm text-[var(--text)] outline-none focus:border-[var(--accent)] transition" />
      </div>
      {msg && <p className={`mt-2 text-[12px] font-semibold ${msg.ok ? "str-text-green" : "str-text-red"}`}>{msg.text}</p>}
      <Button variant="primary" size="md" className="mt-3" onClick={save} disabled={busy || !username.trim() || !password}>
        {busy ? <Spinner size={15} /> : <Icon name="check" size={16} />} Сохранить логин и пароль
      </Button>
    </Section>
  );
}

/* ----------------------------------------------------------- админ-панель */
function AdminSection() {
  const [me, setMe] = React.useState(null);
  const [data, setData] = React.useState(null); // {users, pending}
  const [tgId, setTgId] = React.useState("");
  const [note, setNote] = React.useState("");
  const [busy, setBusy] = React.useState(false);
  const [err, setErr] = React.useState("");

  const load = React.useCallback(async () => {
    try { setData(await api.adminListUsers()); } catch (e) {}
  }, []);

  React.useEffect(() => {
    api.getMe().then((u) => { setMe(u); if (u.is_admin) load(); }).catch(() => {});
  }, [load]);

  if (!me || !me.is_admin) return null;

  const invite = async () => {
    setErr("");
    const id = parseInt(String(tgId).replace(/\D/g, ""), 10);
    if (!id) { setErr("Введи числовой Telegram ID."); return; }
    setBusy(true);
    try { await api.adminInvite({ telegram_id: id, note: note.trim() }); setTgId(""); setNote(""); await load(); }
    catch (e) { setErr("Не удалось пригласить."); }
    finally { setBusy(false); }
  };
  const revoke = async (id) => { await api.adminRevoke(id); load(); };

  return (
    <Section title="Админ-панель" desc="Пригласи пользователя по его Telegram ID — после этого он сможет войти в бот и веб.">
      <div className="rounded-xl border border-[var(--border)] bg-[var(--surface)] p-3 mb-3">
        <div className="grid sm:grid-cols-[1fr_1fr_auto] gap-2 items-center">
          <input value={tgId} onChange={(e) => setTgId(e.target.value)} inputMode="numeric" placeholder="Telegram ID (напр. 123456789)"
            className="w-full rounded-lg border border-[var(--border)] bg-[var(--surface-2)] px-3 h-10 text-sm text-[var(--text)] outline-none focus:border-[var(--accent)] transition mono" />
          <input value={note} onChange={(e) => setNote(e.target.value)} placeholder="имя/заметка (необязательно)"
            className="w-full rounded-lg border border-[var(--border)] bg-[var(--surface-2)] px-3 h-10 text-sm text-[var(--text)] outline-none focus:border-[var(--accent)] transition" />
          <Button variant="primary" size="md" onClick={invite} disabled={busy || !tgId}>
            {busy ? <Spinner size={15} /> : <Icon name="plus" size={16} />} Пригласить
          </Button>
        </div>
        {err && <p className="mt-2 text-[12px] str-text-red font-semibold">{err}</p>}
        <p className="mt-2 text-[12px] text-[var(--muted)]">Свой Telegram ID можно узнать у @userinfobot.</p>
      </div>

      {data && (
        <div className="space-y-2">
          {data.users.map((u) => (
            <div key={u.id} className="flex items-center gap-3 rounded-xl border border-[var(--border)] bg-[var(--surface)] px-3 py-2.5">
              <span className="grid place-items-center w-8 h-8 rounded-full bg-[var(--accent-weak)] text-[var(--accent)] font-bold text-sm shrink-0">{(u.name || "?").slice(0, 1).toUpperCase()}</span>
              <div className="min-w-0 flex-1">
                <div className="text-[14px] font-semibold text-[var(--text)] truncate">{u.name || "Без имени"} {u.is_admin && <span className="text-[11px] font-bold str-text-amber">· админ</span>}{!u.is_allowed && <span className="text-[11px] font-bold str-text-red">· заблокирован</span>}</div>
                <div className="text-[12px] text-[var(--muted)] mono truncate">ID {u.telegram_id}{u.username ? " · @" + u.username : ""}</div>
              </div>
              {!u.is_admin && (
                <button onClick={() => revoke(u.telegram_id)} className="shrink-0 text-[12px] font-semibold text-[var(--muted)] hover:text-[var(--danger)] transition px-2 py-1 rounded-lg hover:bg-[var(--surface-2)]" title="Отозвать доступ">
                  {u.is_allowed ? "Отозвать" : "Вернуть"}
                </button>
              )}
            </div>
          ))}
          {data.pending.length > 0 && (
            <>
              <h3 className="text-[12px] font-bold uppercase tracking-wide text-[var(--muted)] pt-2">Приглашены (ещё не заходили)</h3>
              {data.pending.map((p) => (
                <div key={p.telegram_id} className="flex items-center gap-3 rounded-xl border border-dashed border-[var(--border-strong)] bg-[var(--surface-2)] px-3 py-2.5">
                  <Icon name="telegram" size={16} className="text-[var(--muted)] shrink-0" />
                  <div className="min-w-0 flex-1">
                    <div className="text-[13px] text-[var(--text)] mono">ID {p.telegram_id}</div>
                    {p.note && <div className="text-[12px] text-[var(--muted)] truncate">{p.note}</div>}
                  </div>
                  <button onClick={() => revoke(p.telegram_id)} className="shrink-0 text-[12px] font-semibold text-[var(--muted)] hover:text-[var(--danger)] transition px-2 py-1 rounded-lg hover:bg-[var(--surface)]">Удалить</button>
                </div>
              ))}
            </>
          )}
        </div>
      )}
    </Section>
  );
}

/* ----------------------------------------------------------- экспорт */
function ExportButton() {
  const [busy, setBusy] = React.useState(false);
  const go = async () => {
    setBusy(true);
    const data = await api.exportData();
    setBusy(false);
    const blob = new Blob([JSON.stringify(data, null, 2)], { type: "application/json" });
    const a = document.createElement("a");
    a.href = URL.createObjectURL(blob);
    a.download = "bloknot-backup-" + new Date().toISOString().slice(0, 10) + ".json";
    a.click();
    setTimeout(() => URL.revokeObjectURL(a.href), 1000);
  };
  return (
    <Button variant="ghost" size="md" onClick={go} disabled={busy}>
      {busy ? <Spinner size={15} /> : <Icon name="logout" size={16} className="rotate-90" />} Скачать
    </Button>
  );
}

/* ----------------------------------------------------------- строка категории */
function CategoryRow({ cat, canDelete, draft, onDone }) {
  const [editing, setEditing] = React.useState(!!draft);
  const [label, setLabel] = React.useState(draft ? "" : cat.label);
  const [color, setColor] = React.useState(draft ? "amber" : cat.color);
  const [confirmDel, setConfirmDel] = React.useState(false);
  const [busy, setBusy] = React.useState(false);

  const save = async () => {
    if (!label.trim()) return;
    setBusy(true);
    if (draft) await Store.addCategory(label.trim(), color);
    else await Store.editCategory(cat.key, { label: label.trim(), color });
    setBusy(false);
    setEditing(false);
    onDone && onDone();
  };
  const del = async () => { setBusy(true); await Store.removeCategory(cat.key); setBusy(false); };

  if (editing) {
    return (
      <div className="rounded-xl border border-[var(--accent)] bg-[var(--surface)] p-3 space-y-3">
        <div className="flex items-center gap-2">
          <span className={`w-8 h-8 rounded-lg shrink-0 ${Store.colorClass(color)}`} />
          <input autoFocus value={label} onChange={(e) => setLabel(e.target.value)}
            onKeyDown={(e) => { if (e.key === "Enter") save(); if (e.key === "Escape") { draft ? onDone() : setEditing(false); } }}
            placeholder="Название категории"
            className="flex-1 rounded-lg border border-[var(--border)] bg-[var(--surface-2)] px-3 h-9 text-sm text-[var(--text)] outline-none focus:border-[var(--accent)] transition" />
        </div>
        <div className="flex flex-wrap gap-1.5">
          {Store.COLORS.map((cl) => (
            <button key={cl} onClick={() => setColor(cl)} title={Store.COLOR_LABEL[cl]}
              className={`w-7 h-7 rounded-lg sw-${cl} transition ${color === cl ? "ring-2 ring-offset-2 ring-[var(--accent)] ring-offset-[var(--surface)]" : "opacity-80 hover:opacity-100"}`} />
          ))}
        </div>
        <div className="flex items-center gap-2">
          <Button size="sm" variant="primary" onClick={save} disabled={busy || !label.trim()}>{busy ? <Spinner size={14} /> : <Icon name="check" size={15} />} Сохранить</Button>
          <Button size="sm" variant="ghost" onClick={() => (draft ? onDone() : setEditing(false))}>Отмена</Button>
        </div>
      </div>
    );
  }

  return (
    <div className="flex items-center gap-3 rounded-xl border border-[var(--border)] bg-[var(--surface)] px-3 py-2.5">
      <span className={`inline-flex items-center gap-1.5 rounded-full px-2.5 py-1 text-xs font-semibold ${Store.colorClass(cat.color)}`}>
        <span className="cat-dot" /> {cat.label}
      </span>
      {cat.system && <span className="text-[11px] text-[var(--muted)]">встроенная</span>}
      <div className="ml-auto flex items-center gap-1">
        <button onClick={() => setEditing(true)} className="grid place-items-center w-8 h-8 rounded-lg text-[var(--muted)] hover:text-[var(--text)] hover:bg-[var(--surface-2)] transition" title="Изменить"><Icon name="edit" size={15} /></button>
        {canDelete && (confirmDel ? (
          <div className="flex items-center gap-1">
            <button onClick={del} disabled={busy} className="text-[12px] font-semibold text-[var(--danger)] px-2 h-8 rounded-lg hover:bg-[var(--surface-2)]">Удалить</button>
            <button onClick={() => setConfirmDel(false)} className="text-[12px] text-[var(--muted)] px-1.5 h-8 rounded-lg hover:bg-[var(--surface-2)]">нет</button>
          </div>
        ) : (
          <button onClick={() => setConfirmDel(true)} className="grid place-items-center w-8 h-8 rounded-lg text-[var(--muted)] hover:text-[var(--danger)] hover:bg-[var(--surface-2)] transition" title="Удалить"><Icon name="trash" size={15} /></button>
        ))}
      </div>
    </div>
  );
}

/* ----------------------------------------------------------- примитивы настроек */
function Section({ title, desc, children }) {
  return (
    <section className="mb-7">
      <h2 className="text-[13px] font-bold uppercase tracking-wide text-[var(--muted)] mb-1">{title}</h2>
      {desc && <p className="text-[13px] text-[var(--muted)] mb-3 leading-relaxed" style={{ textWrap: "pretty" }}>{desc}</p>}
      {!desc && <div className="mb-3" />}
      {children}
    </section>
  );
}

function Row({ label, desc, children }) {
  return (
    <div className="flex items-center gap-4 py-2.5 border-b border-[var(--border)] last:border-0">
      <div className="min-w-0">
        <div className="text-[14px] font-semibold text-[var(--text)]">{label}</div>
        {desc && <div className="text-[12px] text-[var(--muted)] mt-0.5">{desc}</div>}
      </div>
      <div className="ml-auto shrink-0">{children}</div>
    </div>
  );
}

function Toggle({ on, onClick }) {
  return <button onClick={onClick} className={`nb-toggle ${on ? "on" : ""}`} aria-pressed={on} />;
}

function Segmented({ value, onChange, options }) {
  return (
    <div className="inline-flex p-0.5 rounded-xl bg-[var(--surface-2)] border border-[var(--border)]">
      {options.map((o) => {
        const active = value === o.v;
        return (
          <button key={o.v} onClick={() => onChange(o.v)}
            className={`inline-flex items-center gap-1.5 px-3 h-9 rounded-[10px] text-[13px] font-semibold transition ${active ? "bg-[var(--surface)] text-[var(--text)] shadow-[0_1px_4px_var(--shadow)]" : "text-[var(--muted)] hover:text-[var(--text)]"}`}>
            {o.icon && <Icon name={o.icon} size={15} />}{o.label}
          </button>
        );
      })}
    </div>
  );
}

Object.assign(window, { SettingsScreen });
