/* Stops.jsx — екран Зупинок: live API через window.passengerApi. */

const { useState: useStateS, useEffect: useEffectS, useRef: useRefS } = React;

function slugifyCode(name) {
  // Простий transliteration UA/RU → ASCII + slug + 4-цифровий suffix.
  const map = {
    "а":"a","б":"b","в":"v","г":"g","ґ":"g","д":"d","е":"e","є":"ie","ё":"e",
    "ж":"zh","з":"z","и":"y","і":"i","ї":"yi","й":"y","к":"k","л":"l","м":"m",
    "н":"n","о":"o","п":"p","р":"r","с":"s","т":"t","у":"u","ф":"f","х":"kh",
    "ц":"ts","ч":"ch","ш":"sh","щ":"shch","ъ":"","ы":"y","ь":"","э":"e","ю":"iu","я":"ia",
  };
  const lower = (name || "").toLowerCase();
  let out = "";
  for (const ch of lower) out += (map[ch] !== undefined) ? map[ch] : ch;
  out = out.replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "");
  if (!out) out = "stop";
  const suffix = String(Math.floor(1000 + Math.random() * 9000));
  return out.slice(0, 40) + "-" + suffix;
}

/* ── Drawer ────────────────────────────────────────────────── */
function Drawer({ open, onClose, title, width = 440, children, footer }) {
  const [anim, setAnim] = useStateS(false);

  useEffectS(() => {
    if (open) requestAnimationFrame(() => setAnim(true));
    else setAnim(false);
  }, [open]);

  if (!open && !anim) return null;

  return (
    <>
      <div onClick={onClose} style={{
        position: "fixed", inset: 0, background: "rgba(0,0,0,0.25)", zIndex: 40,
        opacity: anim ? 1 : 0, transition: "opacity 200ms",
      }} />
      <div style={{
        position: "fixed", top: 0, right: 0, height: "100vh",
        width, background: "var(--surface)", zIndex: 41,
        display: "flex", flexDirection: "column",
        borderLeft: "1px solid var(--border)",
        boxShadow: "-4px 0 24px rgba(0,0,0,0.08)",
        transform: anim ? "translateX(0)" : "translateX(100%)",
        transition: "transform 220ms cubic-bezier(0.4,0,0.2,1)",
      }}>
        <div style={{ padding: "16px 20px", borderBottom: "1px solid var(--border)", display: "flex", justifyContent: "space-between", alignItems: "center" }}>
          <span style={{ fontSize: 15, fontWeight: 700 }}>{title}</span>
          <button onClick={onClose} style={{ border: "none", background: "none", cursor: "pointer", fontSize: 20, color: "var(--text-3)", lineHeight: 1, padding: 4 }}>×</button>
        </div>
        <div style={{ flex: 1, overflow: "auto", padding: "20px" }}>
          {children}
        </div>
        {footer && (
          <div style={{ padding: "14px 20px", borderTop: "1px solid var(--border)", background: "var(--surface-2)", display: "flex", gap: 8, justifyContent: "flex-end" }}>
            {footer}
          </div>
        )}
      </div>
    </>
  );
}

/* ── Create Stop Form (controlled через ref-handle) ─────────── */
const CreateStopForm = React.forwardRef(function CreateStopForm({ saving }, ref) {
  const [form, setForm] = useStateS({ name: "", lat: "", lon: "", radius: 60 });
  const [errors, setErrors] = useStateS({});

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

  React.useImperativeHandle(ref, () => ({
    getFormData() {
      const code = slugifyCode(form.name);
      return {
        code,
        name: (form.name || "").trim(),
        lat: parseFloat(form.lat),
        lon: parseFloat(form.lon),
        radius: parseInt(form.radius, 10) || 60,
      };
    },
    setFieldErrors(errs) { setErrors(errs || {}); },
    reset() { setForm({ name: "", lat: "", lon: "", radius: 60 }); setErrors({}); },
  }));

  return (
    <div style={{ display: "flex", flexDirection: "column", gap: 18 }}>
      <div>
        <label className="field-label">Назва зупинки *</label>
        <input className={"input" + (errors.name ? " error" : "")}
          value={form.name} onChange={e => set("name", e.target.value)}
          placeholder="напр. Хрещатик А" autoFocus />
        {errors.name && <div className="field-error">{errors.name}</div>}
        {errors.code && <div className="field-error">{errors.code}</div>}
      </div>

      <div className="map-stub" style={{ height: 140, display: "flex", alignItems: "center", justifyContent: "center" }}>
        <div style={{ textAlign: "center", color: "var(--text-3)", position: "relative", zIndex: 1 }}>
          <div style={{ fontSize: 24, marginBottom: 4 }}>🗺</div>
          <div style={{ fontSize: 12 }}>Карта · вкажіть координати нижче</div>
        </div>
      </div>

      <div style={{ display: "grid", gridTemplateColumns: "1fr 1fr", gap: 12 }}>
        <div>
          <label className="field-label">Широта *</label>
          <input className={"input mono" + (errors.lat ? " error" : "")}
            value={form.lat} onChange={e => set("lat", e.target.value)} placeholder="50.4501" />
          {errors.lat && <div className="field-error">{errors.lat}</div>}
        </div>
        <div>
          <label className="field-label">Довгота *</label>
          <input className={"input mono" + (errors.lon ? " error" : "")}
            value={form.lon} onChange={e => set("lon", e.target.value)} placeholder="30.5234" />
          {errors.lon && <div className="field-error">{errors.lon}</div>}
        </div>
      </div>

      <div>
        <label className="field-label">Радіус зупинки</label>
        <div style={{ display: "flex", gap: 6, flexWrap: "wrap", marginTop: 6 }}>
          {[40, 60, 75, 100, 150].map(r => (
            <button key={r} onClick={() => set("radius", r)} style={{
              padding: "5px 14px", borderRadius: 999,
              border: `1px solid ${form.radius === r ? "var(--accent)" : "var(--border)"}`,
              background: form.radius === r ? "var(--accent-soft)" : "var(--surface)",
              color: form.radius === r ? "var(--accent)" : "var(--text-2)",
              fontFamily: "inherit", fontSize: 13, fontWeight: 500, cursor: "pointer",
              transition: "all 0.12s",
            }}>{r} м</button>
          ))}
        </div>
        <div style={{ fontSize: 12, color: "var(--text-3)", marginTop: 6 }}>
          Зона зарахування пасажира до зупинки
        </div>
      </div>

      {saving && (
        <div style={{ textAlign: "center", color: "var(--text-3)", fontSize: 13 }}>
          <span style={{ display: "inline-block", animation: "spin 1s linear infinite", marginRight: 6 }}>⟳</span>
          Зберігаю…
        </div>
      )}
    </div>
  );
});

/* ── Main Screen ───────────────────────────────────────────── */
function Stops({ onNav }) {
  const [stops, setStops] = useStateS([]);
  const [counts, setCounts] = useStateS({ all: 0, draft: 0, published: 0, archived: 0 });
  const [loading, setLoading] = useStateS(true);
  const [error, setError] = useStateS(null);
  const [search, setSearch] = useStateS("");
  const [filter, setFilter] = useStateS("all");
  const [drawerOpen, setDrawerOpen] = useStateS(false);
  const [saving, setSaving] = useStateS(false);
  const [selected, setSelected] = useStateS(new Set());
  const formRef = useRefS();

  const reload = async (opts = {}) => {
    setLoading(true);
    try {
      const res = await window.passengerApi.stops.list({
        search: opts.search ?? search,
        status: opts.filter ?? filter,
      });
      setStops(res.items || []);
      setCounts(res.counts || { all: 0, draft: 0, published: 0, archived: 0 });
      setError(null);
    } catch (e) {
      setError(e);
      window.showToast && window.showToast("Не вдалося завантажити зупинки: " + (e.message || ""), "bad");
    } finally {
      setLoading(false);
    }
  };

  useEffectS(() => { reload({ search, filter }); /* eslint-disable-next-line */ }, [search, filter]);
  window.passengerApi.usePolling(() => reload({ search, filter }), 30000, [search, filter]);

  const toggleSelect = (id) => {
    setSelected(prev => {
      const next = new Set(prev);
      next.has(id) ? next.delete(id) : next.add(id);
      return next;
    });
  };

  const handleDelete = async (stop) => {
    try {
      await window.passengerApi.stops.remove(stop.id);
      window.showToast && window.showToast(
        `Зупинку «${stop.name}» видалено`, "warn",
        async () => {
          try {
            await window.passengerApi.stops.restore(stop.id);
            await reload();
            window.showToast && window.showToast(`«${stop.name}» відновлено`, "ok");
          } catch (e) {
            window.showToast && window.showToast("Не вдалося відновити: " + (e.message || ""), "bad");
          }
        }
      );
      await reload();
    } catch (e) {
      window.showToast && window.showToast("Помилка видалення: " + (e.message || ""), "bad");
    }
  };

  const handlePublish = async (stop) => {
    try {
      await window.passengerApi.stops.publish(stop.id);
      window.showToast && window.showToast(`«${stop.name}» опубліковано`, "ok");
      await reload();
    } catch (e) {
      window.showToast && window.showToast("Помилка публікації: " + (e.message || ""), "bad");
    }
  };

  const handleBulkDelete = async () => {
    const ids = [...selected];
    if (!ids.length) return;
    try {
      const res = await window.passengerApi.stops.bulkDelete(ids);
      setSelected(new Set());
      window.showToast && window.showToast(`Видалено ${res.deleted || 0} зупинок`, "warn");
      await reload();
    } catch (e) {
      window.showToast && window.showToast("Помилка bulk-delete: " + (e.message || ""), "bad");
    }
  };

  const handleSave = async (status) => {
    if (!formRef.current) return;
    const data = { ...formRef.current.getFormData(), status };
    setSaving(true);
    try {
      await window.passengerApi.stops.create(data);
      window.showToast && window.showToast(
        status === "published"
          ? `«${data.name}» опубліковано`
          : `Чернетку «${data.name}» збережено`,
        status === "published" ? "ok" : "info"
      );
      formRef.current.reset();
      setDrawerOpen(false);
      await reload();
    } catch (e) {
      if (e.errors) {
        formRef.current.setFieldErrors(e.errors);
      } else {
        window.showToast && window.showToast("Помилка збереження: " + (e.message || ""), "bad");
      }
    } finally {
      setSaving(false);
    }
  };

  return (
    <>
      <Topbar
        title="Зупинки"
        subtitle={loading ? "Завантаження…" : `${counts.all} зупинок`}
        actions={
          <button className="btn btn-primary btn-sm" onClick={() => setDrawerOpen(true)}>
            + Нова зупинка
          </button>
        }
      />

      <div className="page" style={{ animation: "fadeIn 0.2s ease" }}>

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

        {/* Toolbar */}
        <div style={{ display: "flex", gap: 10, marginBottom: 16, alignItems: "center", flexWrap: "wrap" }}>
          <div style={{ position: "relative", flex: 1, maxWidth: 320 }}>
            <span style={{ position: "absolute", left: 10, top: "50%", transform: "translateY(-50%)", color: "var(--text-3)", fontSize: 14 }}>🔍</span>
            <input className="input" value={search} onChange={e => setSearch(e.target.value)}
              placeholder="Пошук за назвою або кодом…"
              style={{ paddingLeft: 32 }} />
          </div>

          <div className="segmented">
            {[
              { id: "all",       label: `Усі ${counts.all}` },
              { id: "published", label: `Опубліковані ${counts.published}` },
              { id: "draft",     label: `Чернетки ${counts.draft}` },
            ].map(f => (
              <button key={f.id} className={filter === f.id ? "active" : ""} onClick={() => setFilter(f.id)}>
                {f.label}
              </button>
            ))}
          </div>

          {selected.size > 0 && (
            <div style={{ display: "flex", gap: 6, alignItems: "center", padding: "4px 12px", background: "var(--accent-soft)", border: "1px solid var(--accent)", borderRadius: "var(--radius-sm)" }}>
              <span style={{ fontSize: 13, color: "var(--accent)", fontWeight: 600 }}>{selected.size} обрано</span>
              <button className="btn btn-ghost btn-xs" onClick={() => setSelected(new Set())}>Зняти</button>
              <button className="btn btn-danger btn-xs" onClick={handleBulkDelete}>Видалити</button>
            </div>
          )}
        </div>

        {/* Table */}
        <div className="card" style={{ padding: 0, overflow: "hidden" }}>
          {loading ? (
            <div style={{ padding: 60, textAlign: "center", color: "var(--text-3)" }}>
              <span style={{ display: "inline-block", animation: "spin 1s linear infinite", marginRight: 6 }}>⟳</span>
              Завантаження…
            </div>
          ) : stops.length === 0 ? (
            <div style={{ padding: 60, textAlign: "center", color: "var(--text-3)" }}>
              <div style={{ fontSize: 32, marginBottom: 12 }}>📍</div>
              <div style={{ fontSize: 15, fontWeight: 600, color: "var(--text-2)", marginBottom: 6 }}>
                {search ? `Нічого не знайдено за «${search}»` : "Зупинок ще немає"}
              </div>
              <div style={{ fontSize: 13, marginBottom: 20 }}>
                {search ? "Спробуйте інший запит або скиньте фільтри" : "Додайте першу зупинку"}
              </div>
              <div style={{ display: "flex", gap: 8, justifyContent: "center" }}>
                {search
                  ? <button className="btn btn-secondary btn-sm" onClick={() => { setSearch(""); setFilter("all"); }}>Скинути фільтри</button>
                  : <button className="btn btn-primary btn-sm" onClick={() => setDrawerOpen(true)}>+ Нова зупинка</button>
                }
              </div>
            </div>
          ) : (
            <table className="table">
              <thead>
                <tr>
                  <th style={{ width: 40 }}>
                    <input type="checkbox"
                      checked={selected.size === stops.length && stops.length > 0}
                      onChange={e => setSelected(e.target.checked ? new Set(stops.map(s => s.id)) : new Set())}
                    />
                  </th>
                  <th>Назва</th>
                  <th>Код</th>
                  <th>Статус</th>
                  <th>Радіус</th>
                  <th>Координати</th>
                  <th></th>
                </tr>
              </thead>
              <tbody>
                {stops.map(stop => (
                  <StopRow key={stop.id} stop={stop}
                    selected={selected.has(stop.id)}
                    onToggle={() => toggleSelect(stop.id)}
                    onDelete={() => handleDelete(stop)}
                    onPublish={() => handlePublish(stop)}
                  />
                ))}
              </tbody>
            </table>
          )}
        </div>
      </div>

      <Drawer
        open={drawerOpen}
        onClose={() => { if (!saving) setDrawerOpen(false); }}
        title="Нова зупинка"
        footer={<>
          <button className="btn btn-secondary" disabled={saving} onClick={() => setDrawerOpen(false)}>Скасувати</button>
          <button className="btn btn-secondary" disabled={saving} onClick={() => handleSave("draft")}>Зберегти чернетку</button>
          <button className="btn btn-primary" disabled={saving} onClick={() => handleSave("published")}>Опублікувати</button>
        </>}
      >
        <CreateStopForm ref={formRef} saving={saving} />
      </Drawer>
    </>
  );
}

function StopRow({ stop, selected, onToggle, onDelete, onPublish }) {
  const [hovered, setHovered] = useStateS(false);
  const statusBadge = stop.status === "published"
    ? <span className="badge badge-ok">● Опубліковано</span>
    : stop.status === "archived"
      ? <span className="badge badge-neutral">▼ Архівна</span>
      : <span className="badge badge-neutral">○ Чернетка</span>;

  return (
    <tr style={{ background: selected ? "var(--accent-soft)" : hovered ? "var(--surface-2)" : undefined }}
      onMouseEnter={() => setHovered(true)} onMouseLeave={() => setHovered(false)}>
      <td><input type="checkbox" checked={selected} onChange={onToggle} /></td>
      <td style={{ fontWeight: 500 }}>{stop.name}</td>
      <td><span className="mono" style={{ color: "var(--text-3)" }}>{stop.code}</span></td>
      <td>{statusBadge}</td>
      <td style={{ color: "var(--text-2)" }}>{stop.radius} м</td>
      <td><span className="mono" style={{ fontSize: 11, color: "var(--text-3)" }}>{Number(stop.lat).toFixed(4)}, {Number(stop.lon).toFixed(4)}</span></td>
      <td>
        {hovered && (
          <div style={{ display: "flex", gap: 4 }}>
            {stop.status === "draft" && (
              <button className="btn btn-secondary btn-xs" onClick={onPublish}>Опублікувати</button>
            )}
            <button className="btn btn-ghost btn-xs" onClick={() => window.showToast && window.showToast(`Редагування «${stop.name}» — буде в pack-04.1`, "info")}>
              Редагувати
            </button>
            <button className="btn btn-ghost btn-xs"
              style={{ color: "var(--bad)" }}
              onClick={onDelete}>
              Видалити
            </button>
          </div>
        )}
      </td>
    </tr>
  );
}

Object.assign(window, { Stops, Drawer });
