/* Settings.jsx — Налаштування карти, live API. */

const { useState: useStateSt, useEffect: useEffectSt } = React;

const PROVIDERS = [
  { id: "maptiler", name: "MapTiler",   desc: "Рекомендовано · GDPR-compliant · Україна є" },
  { id: "mapbox",   name: "Mapbox",     desc: "Преміум якість · платний понад 50k req/місяць" },
  { id: "osm",      name: "OpenStreetMap (tile.openstreetmap.org)", desc: "Безкоштовно · обмеження rate-limit" },
];

const FALLBACKS = [
  { id: "auto",   label: "Авто",             desc: "При недоступності провайдера — перемкнутись на OSM автоматично" },
  { id: "manual", label: "Ручне перемикання", desc: "Адмін отримує алерт і вирішує вручну" },
  { id: "coords", label: "Координатний режим", desc: "Карта прихована, всі дії — через lat/lon поля" },
];

function Settings() {
  const [loaded, setLoaded] = useStateSt(false);
  const [error, setError] = useStateSt(null);
  const [provider, setProvider] = useStateSt("maptiler");
  const [apiKey, setApiKey] = useStateSt(""); // raw input — pristine empty if not changed
  const [hasKey, setHasKey] = useStateSt(false); // backend reports {set: true}
  const [keyPreview, setKeyPreview] = useStateSt("");
  const [showKey, setShowKey] = useStateSt(false);
  const [fallback, setFallback] = useStateSt("auto");
  const [saving, setSaving] = useStateSt(false);
  const [saved, setSaved] = useStateSt(false);

  const reload = async () => {
    try {
      const res = await window.passengerApi.settings.get();
      const it = res.items || {};
      setProvider(it["map.provider"] || "maptiler");
      setFallback(it["map.fallback_policy"] || "auto");
      const keyMeta = it["map.api_key"] || { set: false, preview: "" };
      setHasKey(!!keyMeta.set);
      setKeyPreview(keyMeta.preview || "");
      setApiKey(""); // raw never returned
      setError(null);
      setLoaded(true);
    } catch (e) {
      setError(e);
      window.showToast && window.showToast("Не вдалося завантажити: " + (e.message || ""), "bad");
    }
  };

  useEffectSt(() => { reload(); }, []);

  const handleSave = async () => {
    setSaving(true);
    setSaved(false);
    try {
      const items = {
        "map.provider": provider,
        "map.fallback_policy": fallback,
      };
      const rotatesSecret = !!apiKey.trim();
      if (rotatesSecret) items["map.api_key"] = apiKey.trim();

      let confirm_password = null;
      if (rotatesSecret && window.confirmPassword) {
        confirm_password = await window.confirmPassword(
          "Ротація API-ключа карти потребує підтвердження. Введіть свій пароль."
        );
        if (confirm_password === null) { setSaving(false); return; }
      }

      await window.passengerApi.settings.save(items, confirm_password);
      setSaved(true);
      setApiKey("");
      window.showToast && window.showToast("Налаштування збережено", "ok");
      await reload();
      setTimeout(() => setSaved(false), 3000);
    } catch (e) {
      const msg = (e && e.errors && e.errors.confirm_password) || (e && e.message) || "";
      window.showToast && window.showToast("Помилка збереження: " + msg, "bad");
    } finally {
      setSaving(false);
    }
  };

  const handleReset = async () => {
    setProvider("maptiler");
    setFallback("auto");
    setApiKey("");
    window.showToast && window.showToast("Поля скинуто до дефолтів (натисніть «Зберегти»)", "info");
  };

  if (!loaded) {
    return (
      <>
        <Topbar title="Налаштування" subtitle="Завантаження…" />
        <div className="page" style={{ padding: 60, textAlign: "center", color: "var(--text-3)" }}>
          <span style={{ display: "inline-block", animation: "spin 1s linear infinite", marginRight: 6 }}>⟳</span>
          Завантаження…
        </div>
      </>
    );
  }

  return (
    <>
      <Topbar title="Налаштування" subtitle="Конфігурація карти і системи" />
      <div className="page" style={{ maxWidth: 720, animation: "fadeIn 0.2s ease" }}>

        {error && (
          <div className="alert-banner bad">
            <span>Помилка завантаження.</span>
            <button className="btn btn-sm btn-secondary" onClick={reload}>Спробувати знову</button>
          </div>
        )}

        {/* Provider */}
        <div className="card" style={{ marginBottom: 16 }}>
          <div className="card-header"><span className="card-title">Tile-провайдер карти</span></div>
          <div className="card-body" style={{ display: "flex", flexDirection: "column", gap: 10 }}>
            {PROVIDERS.map(p => (
              <label key={p.id} style={{
                display: "flex", alignItems: "flex-start", gap: 12,
                padding: "12px 14px", borderRadius: "var(--radius-sm)",
                border: `1px solid ${provider === p.id ? "var(--accent)" : "var(--border)"}`,
                background: provider === p.id ? "var(--accent-soft)" : "var(--surface)",
                cursor: "pointer", transition: "all 0.12s",
              }}>
                <input type="radio" name="provider" value={p.id}
                  checked={provider === p.id}
                  onChange={() => setProvider(p.id)}
                  style={{ marginTop: 2 }} />
                <div>
                  <div style={{ fontWeight: 600, fontSize: 14 }}>{p.name}</div>
                  <div style={{ fontSize: 12.5, color: "var(--text-3)", marginTop: 2 }}>{p.desc}</div>
                </div>
              </label>
            ))}
          </div>
        </div>

        {/* API Key */}
        <div className="card" style={{ marginBottom: 16 }}>
          <div className="card-header">
            <span className="card-title">API-ключ</span>
            <span className="badge badge-warn">Конфіденційно</span>
          </div>
          <div className="card-body">
            {hasKey && !apiKey && (
              <div style={{ fontSize: 13, color: "var(--text-2)", marginBottom: 8 }}>
                Поточний ключ: <span className="mono" style={{ color: "var(--text-3)" }}>{keyPreview || "(встановлено)"}</span>
                <span style={{ color: "var(--text-3)", fontSize: 12, marginLeft: 8 }}>· введіть нове значення для ротації</span>
              </div>
            )}
            <div style={{ position: "relative" }}>
              <input
                className="input mono"
                type={showKey ? "text" : "password"}
                value={apiKey}
                onChange={e => setApiKey(e.target.value)}
                placeholder={hasKey ? "Введіть нове значення для зміни" : "Введіть API-ключ"}
                style={{ paddingRight: 80 }}
              />
              <button onClick={() => setShowKey(s => !s)} style={{
                position: "absolute", right: 8, top: "50%", transform: "translateY(-50%)",
                border: "none", background: "none", cursor: "pointer",
                color: "var(--text-3)", fontSize: 12.5, fontFamily: "inherit",
              }}>
                {showKey ? "Сховати" : "Показати"}
              </button>
            </div>
            <div style={{ fontSize: 12, color: "var(--text-3)", marginTop: 6 }}>
              Зберігається у БД на сервері. Сирое значення ніколи не повертається через API.
            </div>
          </div>
        </div>

        {/* Fallback */}
        <div className="card" style={{ marginBottom: 24 }}>
          <div className="card-header"><span className="card-title">Fallback-режим</span></div>
          <div className="card-body" style={{ display: "flex", flexDirection: "column", gap: 10 }}>
            {FALLBACKS.map(f => (
              <label key={f.id} style={{
                display: "flex", alignItems: "flex-start", gap: 12,
                padding: "10px 14px", borderRadius: "var(--radius-sm)",
                border: `1px solid ${fallback === f.id ? "var(--accent)" : "var(--border)"}`,
                background: fallback === f.id ? "var(--accent-soft)" : "var(--surface)",
                cursor: "pointer", transition: "all 0.12s",
              }}>
                <input type="radio" name="fallback" value={f.id}
                  checked={fallback === f.id} onChange={() => setFallback(f.id)}
                  style={{ marginTop: 2 }} />
                <div>
                  <div style={{ fontWeight: 600, fontSize: 13.5 }}>{f.label}</div>
                  <div style={{ fontSize: 12.5, color: "var(--text-3)", marginTop: 1 }}>{f.desc}</div>
                </div>
              </label>
            ))}
          </div>
        </div>

        <div style={{ display: "flex", gap: 10 }}>
          <button className="btn btn-primary" onClick={handleSave} disabled={saving || saved}
            style={{ opacity: saving ? 0.7 : 1 }}>
            {saving
              ? <><span style={{ display: "inline-block", animation: "spin 1s linear infinite" }}>⟳</span> Зберігаю…</>
              : saved ? "✓ Збережено" : "Зберегти налаштування"}
          </button>
          <button className="btn btn-secondary" onClick={handleReset}>Скинути поля</button>
        </div>

        <div style={{ marginTop: 20, padding: "12px 16px", background: "var(--surface-2)", border: "1px solid var(--border)", borderRadius: "var(--radius)", fontSize: 13, color: "var(--text-3)" }}>
          💡 Зміни набувають чинності після збереження. Карта поки не рендериться у Stops/Routes — провайдер фіксується для майбутніх паків.
        </div>

        <div style={{ marginTop: 32 }}>
          <UsersBlock />
        </div>

      </div>
    </>
  );
}

const ROLE_OPTIONS = [
  { id: "dispatcher", label: "Диспетчер" },
  { id: "engineer",   label: "Інженер" },
  { id: "admin",      label: "Адміністратор" },
];

function UsersBlock() {
  const [items, setItems] = useStateSt([]);
  const [loading, setLoading] = useStateSt(true);
  const [adding, setAdding] = useStateSt(false);
  const [form, setForm] = useStateSt({ email: "", role: "engineer", name: "", password: "" });
  const [errors, setErrors] = useStateSt({});
  const [editing, setEditing] = useStateSt(null); // email being edited
  const [editForm, setEditForm] = useStateSt({});

  const reload = async () => {
    setLoading(true);
    try {
      const res = await window.passengerApi.users.list();
      setItems(res.items || []);
    } catch (e) {
      window.showToast && window.showToast("Не вдалося завантажити: " + (e.message || ""), "bad");
    } finally { setLoading(false); }
  };

  useEffectSt(() => { reload(); }, []);

  const handleCreate = async () => {
    setErrors({});
    try {
      await window.passengerApi.users.create({
        email: form.email.trim(),
        role: form.role,
        name: form.name.trim() || null,
        password: form.password,
      });
      window.showToast && window.showToast(`Користувача ${form.email} створено`, "ok");
      setForm({ email: "", role: "engineer", name: "", password: "" });
      setAdding(false);
      await reload();
    } catch (e) {
      if (e.errors) setErrors(e.errors);
      else window.showToast && window.showToast("Помилка: " + (e.message || ""), "bad");
    }
  };

  const handleSave = async (email) => {
    try {
      const orig = items.find(u => u.email === email) || {};
      const roleChanging = editForm.role && editForm.role !== orig.role;
      const pwdRotating = !!editForm.password;

      let confirm_password = null;
      if ((roleChanging || pwdRotating) && window.confirmPassword) {
        const msg = pwdRotating
          ? `Ротація пароля для ${email} потребує підтвердження. Введіть свій пароль.`
          : `Зміна ролі для ${email} потребує підтвердження. Введіть свій пароль.`;
        confirm_password = await window.confirmPassword(msg);
        if (confirm_password === null) return;
      }

      await window.passengerApi.users.update(email, {
        role: editForm.role,
        name: editForm.name,
        password: editForm.password || undefined,
        confirm_password,
      });
      window.showToast && window.showToast(
        `${email} оновлено` + (pwdRotating ? " (пароль ротовано)" : ""), "ok"
      );
      setEditing(null);
      setEditForm({});
      await reload();
    } catch (e) {
      if (e.errors) {
        const msg = Object.values(e.errors).join(", ");
        window.showToast && window.showToast("Помилка: " + msg, "bad");
      } else if (e.status === 409) {
        window.showToast && window.showToast(e.data?.detail?.errors?.role || "Conflict", "bad");
      } else {
        window.showToast && window.showToast("Помилка: " + (e.message || ""), "bad");
      }
    }
  };

  const handleDelete = async (email) => {
    if (!window.confirmPassword) return;
    const confirm_password = await window.confirmPassword(
      `Видалення користувача ${email} потребує підтвердження. Введіть свій пароль.`
    );
    if (confirm_password === null) return;
    try {
      await window.passengerApi.users.remove(email, confirm_password);
      window.showToast && window.showToast(`${email} видалено`, "warn");
      await reload();
    } catch (e) {
      const msg = (e && e.errors && e.errors.confirm_password) || (e && e.message) ||
        (e && e.status === 409 ? "Cannot delete self" : "");
      window.showToast && window.showToast("Помилка: " + msg, "bad");
    }
  };

  return (
    <div className="card">
      <div className="card-header">
        <span className="card-title">Користувачі панелі</span>
        {!adding && (
          <button className="btn btn-primary btn-sm" onClick={() => setAdding(true)}>+ Додати</button>
        )}
      </div>

      {adding && (
        <div className="card-body" style={{ borderBottom: "1px solid var(--border)" }}>
          <div style={{ display: "grid", gridTemplateColumns: "1fr 1fr", gap: 10 }}>
            <div>
              <label className="field-label">Email *</label>
              <input className={"input" + (errors.email ? " error" : "")}
                value={form.email}
                onChange={e => { setForm(f => ({ ...f, email: e.target.value })); setErrors(er => ({ ...er, email: "" })); }}
                placeholder="user@passenger.app" />
              {errors.email && <div className="field-error">{errors.email}</div>}
            </div>
            <div>
              <label className="field-label">Роль</label>
              <select className="input" value={form.role}
                onChange={e => setForm(f => ({ ...f, role: e.target.value }))}>
                {ROLE_OPTIONS.map(r => <option key={r.id} value={r.id}>{r.label}</option>)}
              </select>
            </div>
            <div>
              <label className="field-label">Ім'я (опціонально)</label>
              <input className="input" value={form.name}
                onChange={e => setForm(f => ({ ...f, name: e.target.value }))}
                placeholder="Іван Петрович" />
            </div>
            <div>
              <label className="field-label">Пароль * (мін. 8)</label>
              <input className={"input" + (errors.password ? " error" : "")}
                type="password"
                value={form.password}
                onChange={e => { setForm(f => ({ ...f, password: e.target.value })); setErrors(er => ({ ...er, password: "" })); }}
                placeholder="••••••••" />
              {errors.password && <div className="field-error">{errors.password}</div>}
            </div>
          </div>
          <div style={{ display: "flex", gap: 8, marginTop: 14, justifyContent: "flex-end" }}>
            <button className="btn btn-secondary" onClick={() => { setAdding(false); setErrors({}); }}>Скасувати</button>
            <button className="btn btn-primary" onClick={handleCreate}>Створити</button>
          </div>
        </div>
      )}

      <table className="table">
        <thead>
          <tr><th>Email</th><th>Роль</th><th>Ім'я</th><th>Останній логін</th><th></th></tr>
        </thead>
        <tbody>
          {loading ? (
            <tr><td colSpan={5} style={{ textAlign: "center", color: "var(--text-3)", padding: 20 }}>
              <span style={{ display: "inline-block", animation: "spin 1s linear infinite", marginRight: 6 }}>⟳</span>
              Завантаження…
            </td></tr>
          ) : items.length === 0 ? (
            <tr><td colSpan={5} style={{ textAlign: "center", color: "var(--text-3)", padding: 20 }}>Немає користувачів</td></tr>
          ) : items.map(u => {
            const isEdit = editing === u.email;
            return (
              <tr key={u.email}>
                <td style={{ fontWeight: 500 }}>{u.email}</td>
                <td>
                  {isEdit ? (
                    <select className="input" style={{ width: "auto", padding: "3px 8px" }}
                      value={editForm.role || u.role}
                      onChange={e => setEditForm(f => ({ ...f, role: e.target.value }))}>
                      {ROLE_OPTIONS.map(r => <option key={r.id} value={r.id}>{r.label}</option>)}
                    </select>
                  ) : (
                    <span className={"badge " + (u.role === "admin" ? "badge-bad" : u.role === "engineer" ? "badge-warn" : "badge-neutral")}>
                      {ROLE_OPTIONS.find(r => r.id === u.role)?.label || u.role}
                    </span>
                  )}
                </td>
                <td>
                  {isEdit ? (
                    <input className="input" style={{ padding: "3px 8px" }}
                      value={editForm.name ?? (u.name || "")}
                      onChange={e => setEditForm(f => ({ ...f, name: e.target.value }))}
                      placeholder="Ім'я" />
                  ) : (u.name || <span style={{ color: "var(--text-3)" }}>—</span>)}
                </td>
                <td className="mono" style={{ fontSize: 11, color: "var(--text-3)" }}>
                  {u.last_login_at ? new Date(u.last_login_at).toLocaleString("uk-UA") : "—"}
                </td>
                <td style={{ width: 240 }}>
                  {isEdit ? (
                    <>
                      <input className="input" type="password" style={{ padding: "3px 8px", marginBottom: 4 }}
                        value={editForm.password || ""}
                        onChange={e => setEditForm(f => ({ ...f, password: e.target.value }))}
                        placeholder="новий пароль (опц.)" />
                      <div style={{ display: "flex", gap: 4 }}>
                        <button className="btn btn-primary btn-xs" onClick={() => handleSave(u.email)}>Зберегти</button>
                        <button className="btn btn-ghost btn-xs" onClick={() => { setEditing(null); setEditForm({}); }}>Скасувати</button>
                      </div>
                    </>
                  ) : (
                    <div style={{ display: "flex", gap: 4 }}>
                      <button className="btn btn-secondary btn-xs" onClick={() => { setEditing(u.email); setEditForm({ role: u.role, name: u.name || "" }); }}>Змінити</button>
                      <button className="btn btn-ghost btn-xs" style={{ color: "var(--bad)" }}
                        onClick={() => handleDelete(u.email)}>Видалити</button>
                    </div>
                  )}
                </td>
              </tr>
            );
          })}
        </tbody>
      </table>
    </div>
  );
}

Object.assign(window, { Settings });
