/* passwords.jsx — раздел «Пароли»: список, показать/скрыть, копировать,
 * генератор случайных паролей, индикатор надёжности. */

/* ----------------------------------------------------------- копирование с тостом */
function useCopied() {
  const [copied, setCopied] = React.useState(null);
  const copy = (text, key) => {
    copyToClipboard(text).then(() => {
      setCopied(key);
      setTimeout(() => setCopied((c) => (c === key ? null : c)), 1400);
    });
  };
  return [copied, copy];
}

/* ----------------------------------------------------------- индикатор силы */
function StrengthBar({ value }) {
  const s = passwordStrength(value);
  return (
    <div className="flex items-center gap-2">
      <div className="flex gap-1 flex-1">
        {[0, 1, 2, 3].map((i) => (
          <span key={i} className={`h-1.5 flex-1 rounded-full ${i < s.score ? "str-" + s.tone : "str-gray"}`} />
        ))}
      </div>
      <span className={`text-[12px] font-semibold str-text-${s.tone} w-16 text-right`}>{s.label}</span>
    </div>
  );
}

/* ----------------------------------------------------------- генератор (панель) */
function GeneratorPanel({ onUse }) {
  const [length, setLength] = React.useState(16);
  const [upper, setUpper] = React.useState(true);
  const [digits, setDigits] = React.useState(true);
  const [symbols, setSymbols] = React.useState(true);
  const [value, setValue] = React.useState(() => generatePassword({ length: 16 }));

  const regen = React.useCallback(() => {
    setValue(generatePassword({ length, upper, digits, symbols }));
  }, [length, upper, digits, symbols]);
  React.useEffect(() => { regen(); }, [length, upper, digits, symbols]);

  const [copied, copy] = useCopied();

  const Toggle = ({ on, set, label }) => (
    <button type="button" onClick={() => set(!on)} className="flex items-center gap-2 select-none">
      <span className={`nb-toggle ${on ? "on" : ""}`} />
      <span className="text-[13px] text-[var(--text)]">{label}</span>
    </button>
  );

  return (
    <div className="rounded-xl border border-[var(--border)] bg-[var(--surface-2)] p-3.5 space-y-3">
      <div className="flex items-center gap-2 rounded-lg bg-[var(--surface)] border border-[var(--border)] px-3 h-11">
        <span className="mono text-[15px] text-[var(--text)] truncate flex-1">{value}</span>
        <button type="button" onClick={regen} className="grid place-items-center w-8 h-8 rounded-lg text-[var(--muted)] hover:text-[var(--accent)] hover:bg-[var(--surface-2)] transition" title="Сгенерировать заново">
          <Icon name="refresh" size={17} />
        </button>
        <button type="button" onClick={() => copy(value, "gen")} className="grid place-items-center w-8 h-8 rounded-lg text-[var(--muted)] hover:text-[var(--accent)] hover:bg-[var(--surface-2)] transition" title="Копировать">
          <Icon name={copied === "gen" ? "check" : "copy"} size={16} />
        </button>
      </div>

      <StrengthBar value={value} />

      <div>
        <div className="flex items-center justify-between mb-1.5">
          <span className="text-[13px] text-[var(--muted)]">Длина</span>
          <span className="text-[13px] font-bold text-[var(--text)] mono">{length}</span>
        </div>
        <input type="range" min="8" max="32" value={length} onChange={(e) => setLength(+e.target.value)} className="nb-range w-full" />
      </div>

      <div className="flex flex-wrap gap-x-5 gap-y-2.5 pt-0.5">
        <Toggle on={upper} set={setUpper} label="A–Z" />
        <Toggle on={digits} set={setDigits} label="0–9" />
        <Toggle on={symbols} set={setSymbols} label="!@#$" />
      </div>

      {onUse && (
        <Button variant="soft" size="md" className="w-full" onClick={() => onUse(value)}>
          <Icon name="check" size={16} /> Использовать этот пароль
        </Button>
      )}
    </div>
  );
}

/* ----------------------------------------------------------- карточка пароля */
function PasswordCard({ item, onEdit, onToggleFav, flags = [], index = 0 }) {
  const settings = Store.useSettings();
  const [show, setShow] = React.useState(false);
  const [copied, copy] = useCopied();
  const initials = (item.title || "?").trim().slice(0, 1).toUpperCase();

  // автоскрытие открытого пароля
  React.useEffect(() => {
    if (!show) return;
    const secs = settings.autoHidePw || 0;
    if (!secs) return;
    const t = setTimeout(() => setShow(false), secs * 1000);
    return () => clearTimeout(t);
  }, [show, settings.autoHidePw]);

  const flagLabel = { weak: "слабый", reused: "повтор", old: "давно не менялся" };
  return (
    <article
      style={{ animationDelay: `${Math.min(index, 10) * 30}ms` }}
      className="card-in rounded-2xl border border-[var(--border)] bg-[var(--surface)] p-4 hover:border-[var(--border-strong)] transition-colors"
    >
      <div className="flex items-center gap-3">
        <span className="grid place-items-center w-10 h-10 rounded-xl bg-[var(--accent-weak)] text-[var(--accent)] font-bold shrink-0">{initials}</span>
        <div className="min-w-0 flex-1">
          <div className="flex items-center gap-1.5">
            <h3 className="text-[15px] font-bold text-[var(--text)] truncate">{item.title}</h3>
            {item.url && (
              <a href={item.url} target="_blank" rel="noreferrer" className="text-[var(--muted)] hover:text-[var(--accent)] transition shrink-0" title={item.url}>
                <Icon name="external" size={14} />
              </a>
            )}
          </div>
          {item.login && <p className="text-[13px] text-[var(--muted)] truncate">{item.login}</p>}
          {flags.length > 0 && (
            <div className="flex flex-wrap gap-1 mt-1">
              {flags.map((fl) => (
                <span key={fl} className="inline-flex items-center gap-1 rounded-full px-1.5 py-0.5 text-[10px] font-bold str-text-red" style={{ background: "var(--c-red-bg)" }}>
                  <Icon name="key" size={10} /> {flagLabel[fl]}
                </span>
              ))}
            </div>
          )}
        </div>
        <button onClick={() => onToggleFav(item)} className={`grid place-items-center w-8 h-8 rounded-lg transition shrink-0 ${item.favorite ? "str-text-amber" : "text-[var(--muted)] hover:text-[var(--text)]"}`} title="В избранное">
          <Icon name="star" size={17} strokeWidth={item.favorite ? 2.2 : 1.7} />
        </button>
      </div>

      <div className="mt-3 flex items-center gap-2 rounded-xl bg-[var(--surface-2)] border border-[var(--border)] px-3 h-11">
        <Icon name="key" size={15} className="text-[var(--muted)] shrink-0" />
        <span className="mono text-[14px] text-[var(--text)] truncate flex-1">{show ? item.password : "••••••••••••"}</span>
        <button onClick={() => setShow((s) => !s)} className="grid place-items-center w-8 h-8 rounded-lg text-[var(--muted)] hover:text-[var(--accent)] transition" title={show ? "Скрыть" : "Показать"}>
          <Icon name={show ? "eyeOff" : "eye"} size={16} />
        </button>
        <button onClick={() => copy(item.password, item.id)} className="grid place-items-center w-8 h-8 rounded-lg text-[var(--muted)] hover:text-[var(--accent)] transition" title="Копировать пароль">
          <Icon name={copied === item.id ? "check" : "copy"} size={15} />
        </button>
      </div>

      <div className="mt-2.5 flex items-center gap-2">
        {item.login && (
          <button onClick={() => copy(item.login, item.id + "-l")} className="text-[12px] font-semibold text-[var(--muted)] hover:text-[var(--accent)] transition inline-flex items-center gap-1">
            <Icon name={copied === item.id + "-l" ? "check" : "copy"} size={13} /> логин
          </button>
        )}
        {item.note && <span className="text-[12px] text-[var(--muted)] truncate">· {item.note}</span>}
        <button onClick={() => onEdit(item)} className="ml-auto text-[12px] font-semibold text-[var(--muted)] hover:text-[var(--text)] transition inline-flex items-center gap-1">
          <Icon name="edit" size={13} /> изменить
        </button>
      </div>
    </article>
  );
}

/* ----------------------------------------------------------- модалка пароля */
function PasswordModal({ item, open, onClose, onSaved, onDeleted }) {
  const empty = { title: "", login: "", password: "", url: "", note: "", favorite: false };
  const [form, setForm] = React.useState(empty);
  const [show, setShow] = React.useState(false);
  const [gen, setGen] = React.useState(false);
  const [busy, setBusy] = React.useState(false);
  const [confirmDel, setConfirmDel] = React.useState(false);
  const isEdit = item && item.id;

  React.useEffect(() => {
    if (open) {
      setForm(item ? { ...empty, ...item } : empty);
      setShow(false); setGen(!item); setConfirmDel(false);
    }
  }, [open, item]);

  const set = (k, v) => setForm((f) => ({ ...f, [k]: v }));

  const save = async () => {
    if (!form.title.trim()) return;
    setBusy(true);
    if (isEdit) await api.updatePassword(item.id, form);
    else await api.createPassword(form);
    setBusy(false);
    onSaved && onSaved();
    onClose();
  };
  const del = async () => {
    setBusy(true);
    await api.deletePassword(item.id);
    setBusy(false);
    onDeleted && onDeleted();
    onClose();
  };

  return (
    <Modal open={open} onClose={onClose}>
      <div className="flex items-center gap-2.5 px-5 sm:px-6 pt-5 pb-3 border-b border-[var(--border)] sticky top-0 bg-[var(--surface)]/95 backdrop-blur z-10">
        <span className="grid place-items-center w-8 h-8 rounded-lg bg-[var(--accent-weak)] text-[var(--accent)]"><Icon name="lock" size={17} /></span>
        <h2 className="text-base font-bold text-[var(--text)] whitespace-nowrap">{isEdit ? "Изменить пароль" : "Новый пароль"}</h2>
        <button onClick={onClose} className="ml-auto p-1.5 rounded-lg text-[var(--muted)] hover:bg-[var(--surface-2)] transition" aria-label="Закрыть"><Icon name="close" size={18} /></button>
      </div>

      <div className="px-5 sm:px-6 py-4 space-y-4">
        <Field label="Название">
          <input autoFocus value={form.title} onChange={(e) => set("title", e.target.value)} placeholder="Например, Личная почта"
            className="w-full rounded-xl border border-[var(--border)] bg-[var(--surface-2)] px-3.5 h-[42px] text-sm text-[var(--text)] outline-none focus:border-[var(--accent)] transition" />
        </Field>

        <div className="grid sm:grid-cols-2 gap-4">
          <Field label="Логин / e-mail">
            <input value={form.login} onChange={(e) => set("login", e.target.value)} placeholder="логин"
              className="w-full rounded-xl border border-[var(--border)] bg-[var(--surface-2)] px-3.5 h-[42px] text-sm text-[var(--text)] outline-none focus:border-[var(--accent)] transition" />
          </Field>
          <Field label="Сайт">
            <input value={form.url} onChange={(e) => set("url", e.target.value)} placeholder="example.com"
              className="w-full rounded-xl border border-[var(--border)] bg-[var(--surface-2)] px-3.5 h-[42px] text-sm text-[var(--text)] outline-none focus:border-[var(--accent)] transition" />
          </Field>
        </div>

        <Field label="Пароль">
          <div className="flex gap-1.5">
            <div className="flex items-center gap-1.5 flex-1 rounded-xl border border-[var(--border)] bg-[var(--surface-2)] px-3 h-[42px] focus-within:border-[var(--accent)] transition">
              <input type={show ? "text" : "password"} value={form.password} onChange={(e) => set("password", e.target.value)} placeholder="пароль"
                className="mono flex-1 bg-transparent outline-none text-[14px] text-[var(--text)]" />
              <button type="button" onClick={() => setShow((s) => !s)} className="text-[var(--muted)] hover:text-[var(--accent)] transition" title={show ? "Скрыть" : "Показать"}>
                <Icon name={show ? "eyeOff" : "eye"} size={16} />
              </button>
            </div>
            <button type="button" onClick={() => setGen((g) => !g)} className={`shrink-0 inline-flex items-center gap-1.5 px-3 rounded-xl border text-[13px] font-semibold transition ${gen ? "border-[var(--accent)] text-[var(--accent)] bg-[var(--accent-weak)]" : "border-[var(--border)] text-[var(--muted)] hover:text-[var(--text)]"}`}>
              <Icon name="refresh" size={15} /> Генератор
            </button>
          </div>
          {form.password && <div className="mt-2"><StrengthBar value={form.password} /></div>}
        </Field>

        {gen && <GeneratorPanel onUse={(v) => { set("password", v); setShow(true); }} />}

        <Field label="Заметка">
          <input value={form.note} onChange={(e) => set("note", e.target.value)} placeholder="например, включена 2FA"
            className="w-full rounded-xl border border-[var(--border)] bg-[var(--surface-2)] px-3.5 h-[42px] text-sm text-[var(--text)] outline-none focus:border-[var(--accent)] transition" />
        </Field>

        <button type="button" onClick={() => set("favorite", !form.favorite)} className="flex items-center gap-2.5">
          <span className={`nb-toggle ${form.favorite ? "on" : ""}`} />
          <span className="text-[13px] text-[var(--text)]">В избранном</span>
        </button>
      </div>

      <div className="sticky bottom-0 flex items-center gap-2 px-5 sm:px-6 py-3.5 bg-[var(--surface)]/95 backdrop-blur border-t border-[var(--border)]">
        {isEdit && (!confirmDel ? (
          <Button variant="danger" onClick={() => setConfirmDel(true)} disabled={busy}><Icon name="trash" size={16} /> Удалить</Button>
        ) : (
          <div className="flex items-center gap-2">
            <Button variant="danger" onClick={del} disabled={busy}>Да, удалить</Button>
            <Button variant="ghost" onClick={() => setConfirmDel(false)}>Отмена</Button>
          </div>
        ))}
        <div className="ml-auto flex items-center gap-2">
          <Button variant="ghost" onClick={onClose} disabled={busy}>Отмена</Button>
          <Button variant="primary" onClick={save} disabled={busy || !form.title.trim()}>
            {busy ? <Spinner /> : <Icon name="check" size={16} />} Сохранить
          </Button>
        </div>
      </div>
    </Modal>
  );
}

/* ----------------------------------------------------------- замок (PIN, zero-knowledge) */
const PIN_LEN = 4;
function VaultGate({ onUnlocked }) {
  const [phase, setPhase] = React.useState("checking"); // checking | unset | locked
  const [stage, setStage] = React.useState("enter");    // для unset: enter | confirm
  const [pin, setPin] = React.useState("");
  const [firstPin, setFirstPin] = React.useState("");
  const [busy, setBusy] = React.useState(false);
  const [err, setErr] = React.useState("");

  React.useEffect(() => {
    window.vault.status().then(setPhase).catch(() => setPhase("locked"));
  }, []);

  const finish = async (code) => {
    setBusy(true); setErr("");
    try {
      if (phase === "unset") await window.vault.setup(code);
      else await window.vault.unlock(code);
      onUnlocked();
    } catch (e) {
      setErr(phase === "unset" ? "Не удалось сохранить PIN." : "Неверный PIN");
      setPin(""); setBusy(false);
    }
  };

  const press = (d) => {
    if (busy) return;
    setErr("");
    setPin((prev) => {
      if (prev.length >= PIN_LEN) return prev;
      const v = prev + d;
      if (v.length === PIN_LEN) {
        if (phase === "unset") {
          if (stage === "enter") {
            setFirstPin(v); setStage("confirm");
            setTimeout(() => setPin(""), 150);
          } else if (v === firstPin) {
            finish(v);
          } else {
            setErr("PIN не совпал, начни заново"); setStage("enter"); setFirstPin("");
            setTimeout(() => setPin(""), 350);
          }
        } else {
          finish(v);
        }
      }
      return v;
    });
  };

  const doReset = async () => {
    if (!window.confirm("Сбросить PIN? Все сохранённые пароли будут удалены безвозвратно.")) return;
    setBusy(true);
    try {
      await api.resetKeyInfo();
      window.vault.lock();
      setPhase("unset"); setStage("enter"); setFirstPin(""); setPin(""); setErr("");
    } catch (e) { setErr("Не удалось сбросить."); }
    finally { setBusy(false); }
  };

  if (phase === "checking") {
    return <div className="grid place-items-center py-24 text-[var(--muted)]"><Spinner size={24} /></div>;
  }

  const title = phase === "locked" ? "Введи PIN" : stage === "confirm" ? "Повтори PIN" : "Придумай PIN";
  const sub = phase === "locked"
    ? "Короткий код для доступа к паролям на этом устройстве."
    : "4 цифры. Ими шифруются пароли прямо в браузере — сервер видит только шифр. Восстановить нельзя.";

  return (
    <div className="max-w-[300px] mx-auto py-10 text-center">
      <div className="mx-auto mb-4 grid place-items-center w-14 h-14 rounded-2xl bg-[var(--accent-weak)] text-[var(--accent)]">
        <Icon name="lock" size={26} />
      </div>
      <h3 className="text-xl font-extrabold text-[var(--text)]">{title}</h3>
      <p className="mt-1.5 text-[13px] leading-relaxed text-[var(--muted)]">{sub}</p>

      <div className={`flex justify-center gap-3 mt-6 ${err ? "shake" : ""}`}>
        {Array.from({ length: PIN_LEN }).map((_, i) => (
          <span key={i} className={`w-3.5 h-3.5 rounded-full border-2 ${i < pin.length ? "bg-[var(--accent)] border-[var(--accent)]" : "border-[var(--border-strong)]"}`} />
        ))}
      </div>
      {err && <p className="mt-2 text-[12px] text-[var(--danger)] font-semibold">{err}</p>}

      <div className="grid grid-cols-3 gap-2.5 mt-6">
        {[1, 2, 3, 4, 5, 6, 7, 8, 9].map((n) => (
          <button key={n} onClick={() => press(String(n))} disabled={busy}
            className="h-14 rounded-xl bg-[var(--surface)] border border-[var(--border)] text-[20px] font-bold text-[var(--text)] hover:border-[var(--border-strong)] active:scale-95 transition mono">{n}</button>
        ))}
        <span />
        <button onClick={() => press("0")} disabled={busy}
          className="h-14 rounded-xl bg-[var(--surface)] border border-[var(--border)] text-[20px] font-bold text-[var(--text)] hover:border-[var(--border-strong)] active:scale-95 transition mono">0</button>
        <button onClick={() => setPin((p) => p.slice(0, -1))} disabled={busy}
          className="h-14 rounded-xl text-[var(--muted)] grid place-items-center hover:bg-[var(--surface-2)] transition" aria-label="Стереть">
          <Icon name="close" size={18} />
        </button>
      </div>

      {phase === "locked" && (
        <button onClick={doReset} disabled={busy} className="mt-5 text-[12px] text-[var(--muted)] hover:text-[var(--danger)] transition">
          Забыл PIN — сбросить (удалит пароли)
        </button>
      )}
    </div>
  );
}

/* ----------------------------------------------------------- баннер здоровья */
function VaultHealth({ health, active, onToggle }) {
  if (!health) return null;
  const issues = new Set([...health.weak, ...health.reused, ...health.old]).size;
  const tone = health.score >= 80 ? "green" : health.score >= 50 ? "amber" : "red";
  return (
    <button onClick={onToggle} className="w-full text-left mb-4 rounded-2xl border border-[var(--border)] bg-[var(--surface)] p-3.5 hover:border-[var(--border-strong)] transition">
      <div className="flex items-center gap-3">
        <div className="relative grid place-items-center w-12 h-12 shrink-0">
          <svg width="48" height="48" viewBox="0 0 48 48" className="-rotate-90">
            <circle cx="24" cy="24" r="20" fill="none" stroke="var(--surface-2)" strokeWidth="5" />
            <circle cx="24" cy="24" r="20" fill="none" strokeWidth="5" strokeLinecap="round"
              strokeDasharray={`${(health.score / 100) * 125.6} 125.6`} className={`str-stroke-${tone}`} />
          </svg>
          <span className="absolute text-[13px] font-extrabold text-[var(--text)] mono">{health.score}</span>
        </div>
        <div className="min-w-0 flex-1">
          <div className="text-[14px] font-bold text-[var(--text)]">Здоровье хранилища</div>
          <div className="text-[12px] text-[var(--muted)]">
            {issues === 0 ? "Все пароли в порядке 🎉" : `${issues} ${pluralRu(issues, "пароль требует", "пароля требуют", "паролей требуют")} внимания`}
          </div>
        </div>
        <span className={`text-[12px] font-semibold ${active ? "text-[var(--accent)]" : "text-[var(--muted)]"} shrink-0`}>{active ? "скрыть" : "показать"}</span>
      </div>
    </button>
  );
}

/* ----------------------------------------------------------- экран «Пароли» */
function PasswordsScreen({ createSignal }) {
  const [unlocked, setUnlocked] = React.useState(() => (window.vault ? window.vault.isUnlocked() : true));
  const [items, setItems] = React.useState([]);
  const [loading, setLoading] = React.useState(true);
  const [q, setQ] = React.useState("");
  const [editing, setEditing] = React.useState(null);
  const [modalOpen, setModalOpen] = React.useState(false);
  const [health, setHealth] = React.useState(null);
  const [showHealth, setShowHealth] = React.useState(false);
  const [blurred, setBlurred] = React.useState(false);

  // блюр при сворачивании приложения (безопасность)
  React.useEffect(() => {
    const onVis = () => setBlurred(document.hidden);
    document.addEventListener("visibilitychange", onVis);
    return () => document.removeEventListener("visibilitychange", onVis);
  }, []);

  const load = React.useCallback(async () => {
    setLoading(true);
    const data = await api.getPasswords({ q: q || undefined });
    setItems(data);
    setLoading(false);
    api.getVaultHealth().then(setHealth);
  }, [q]);
  React.useEffect(() => { if (unlocked) { const t = setTimeout(load, 200); return () => clearTimeout(t); } }, [q, unlocked]);

  const firstSignal = React.useRef(createSignal);
  React.useEffect(() => {
    if (createSignal !== firstSignal.current) { setEditing(null); setModalOpen(true); }
  }, [createSignal]);

  const openNew = () => { setEditing(null); setModalOpen(true); };
  const openEdit = (item) => { setEditing(item); setModalOpen(true); };
  const toggleFav = async (item) => { await api.updatePassword(item.id, { favorite: !item.favorite }); load(); };

  const flagsFor = (id) => {
    if (!health || !showHealth) return [];
    const f = [];
    if (health.weak.includes(id)) f.push("weak");
    if (health.reused.includes(id)) f.push("reused");
    if (health.old.includes(id)) f.push("old");
    return f;
  };

  if (!unlocked) {
    return (
      <div>
        <ScreenHead title="Пароли" sub="Личное хранилище с генератором надёжных паролей" />
        <VaultGate onUnlocked={() => setUnlocked(true)} />
      </div>
    );
  }

  return (
    <div className={blurred ? "vault-blur" : ""}>
      <ScreenHead title="Пароли" sub="Личное хранилище с генератором надёжных паролей">
        <Button onClick={openNew} className="hidden sm:inline-flex"><Icon name="plus" size={17} /> Добавить</Button>
      </ScreenHead>

      <VaultHealth health={health} active={showHealth} onToggle={() => setShowHealth((s) => !s)} />

      <div className="relative mb-4">
        <Icon name="search" size={18} className="absolute left-3.5 top-1/2 -translate-y-1/2 text-[var(--muted)]" />
        <input value={q} onChange={(e) => setQ(e.target.value)} placeholder="Поиск по названию или логину…"
          className="w-full h-11 rounded-xl border border-[var(--border)] bg-[var(--surface)] pl-10 pr-3 text-sm text-[var(--text)] outline-none focus:border-[var(--accent)] transition placeholder:text-[var(--muted)]" />
      </div>

      {loading ? (
        <div className="grid gap-3">{[0, 1, 2].map((i) => <div key={i} className="sk h-28 rounded-2xl" />)}</div>
      ) : items.length === 0 ? (
        <EmptyState icon="lock" title={q ? "Ничего не нашлось" : "Хранилище пустое"} sub={q ? "Измени запрос." : "Добавь первый пароль — или сгенерируй надёжный прямо сейчас."}
          action={!q && <Button onClick={openNew}><Icon name="plus" size={17} /> Добавить пароль</Button>} />
      ) : (
        <div className="grid gap-3">
          {items.map((p, i) => <PasswordCard key={p.id} item={p} index={i} flags={flagsFor(p.id)} onEdit={openEdit} onToggleFav={toggleFav} />)}
        </div>
      )}

      <PasswordModal item={editing} open={modalOpen} onClose={() => setModalOpen(false)} onSaved={load} onDeleted={load} />
    </div>
  );
}

Object.assign(window, { PasswordsScreen, PasswordModal, PasswordCard, GeneratorPanel, StrengthBar });
