"use client";

import { FormEvent, useEffect, useMemo, useState } from "react";

type PlanTone = "locked" | "trial" | "ok" | "soon" | "urgent" | "grace" | "basic";

type Member = {
  id: string;
  email: string;
  role: "owner" | "manager" | "staff" | "queue";
  roleLabel: string;
  name: string;
  fullName: string;
  displayName: string;
  phone: string;
  mobile: string;
  hasLogin: boolean;
  isActive: boolean;
  createdAt: string;
};

type Client = {
  id: string;
  slug: string;
  name: string;
  currency: string;
  createdAt: string;
  tableCount: number;
  itemCount: number;
  ticketCount: number;
  plan: "trial" | "active" | "basic";
  tone: PlanTone;
  locked: boolean;
  lockedAt: string | null;
  lockNote: string | null;
  hasFullAccess: boolean;
  trialEndsAt: string | null;
  trialDaysLeft: number | null;
  planExpiresAt: string | null;
  planDaysLeft: number | null;
  planUnlimited: boolean;
  graceEndsAt: string | null;
  graceDaysLeft: number | null;
  planMonths: number | null;
  planActivatedAt: string | null;
  planNote: string | null;
  ownerEmail: string | null;
  contactPhone: string;
  address: string;
  city: string;
  postalCode: string;
  members: Member[];
};

type Filter = "all" | "trial" | "basic" | "ending" | "active" | "locked";

const FILTERS: { key: Filter; label: string }[] = [
  { key: "all", label: "Svi" },
  { key: "trial", label: "Probni period" },
  { key: "basic", label: "Samo basic" },
  { key: "ending", label: "Ističe uskoro" },
  { key: "active", label: "Aktivna pretplata" },
  { key: "locked", label: "Zaključani" },
];

const ROLE_OPTIONS: { value: Member["role"]; label: string }[] = [
  { value: "owner", label: "Vlasnik — sve, uključujući naloge i brisanje" },
  { value: "manager", label: "Menadžer — meni, stolovi, računi, podešavanja" },
  { value: "staff", label: "Konobar — samo „Moji stolovi” na telefonu" },
  { value: "queue", label: "Ekran — samo red zahteva, bez računa i menija" },
];

function shortDate(value: string | null) {
  if (!value) return "—";
  const raw = String(value);
  const parsed = new Date(
    raw.replace(" ", "T") + (/[zZ]|[+-]\d\d:?\d\d$/.test(raw) ? "" : "Z"),
  );
  if (Number.isNaN(parsed.getTime())) return raw;
  // sr-RS renders Cyrillic month names; the rest of the app is Latin.
  return parsed.toLocaleDateString("sr-Latn-RS", {
    day: "numeric",
    month: "short",
    year: "numeric",
  });
}

function dayWord(days: number) {
  return days === 1 ? "dan" : "dana";
}

// The badge is the whole status at a glance: purple while the trial runs, green
// through most of a paid month, yellow ten days out, orange five days out, red
// once it lapses or falls back to basic, black when the account is locked.
function badgeLabel(client: Client) {
  if (client.locked) return "Zaključan";
  if (client.plan === "trial") {
    return client.hasFullAccess
      ? `Probni · još ${client.trialDaysLeft ?? 0} ${dayWord(client.trialDaysLeft ?? 0)}`
      : "Probni istekao — basic";
  }
  if (client.plan === "basic") return "Samo basic";
  if (client.planUnlimited) return "Pretplata · bez roka";
  if (client.tone === "grace") {
    const left = Math.max(0, client.graceDaysLeft ?? 0);
    return `Istekla · gasi se za ${left} ${dayWord(left)}`;
  }
  const left = client.planDaysLeft ?? 0;
  return `Pretplata · još ${left} ${dayWord(left)}`;
}

function statusLine(client: Client) {
  if (client.locked) {
    return `Zaključan ${shortDate(client.lockedAt)}${client.lockNote ? ` — ${client.lockNote}` : ""}`;
  }
  if (client.plan === "trial") {
    return `Probni period ${client.hasFullAccess ? "ističe" : "istekao"} ${shortDate(client.trialEndsAt)}`;
  }
  if (client.plan === "basic") return "Ručno vraćen na osnovni nivo (samo poziv konobaru)";
  if (client.planUnlimited) {
    return `Otključan ${shortDate(client.planActivatedAt)}, bez datuma isteka`;
  }
  const term = client.planMonths ? ` · plaćeno ${client.planMonths} mes.` : "";
  if (client.tone === "grace") {
    return `Pretplata je istekla ${shortDate(client.planExpiresAt)} — radi još do ${shortDate(client.graceEndsAt)} (3 radna dana)${term}`;
  }
  return `Pretplata važi do ${shortDate(client.planExpiresAt)}${term}`;
}

function matchesFilter(client: Client, filter: Filter) {
  switch (filter) {
    case "trial":
      return client.plan === "trial" && client.hasFullAccess && !client.locked;
    case "basic":
      return !client.locked && !client.hasFullAccess;
    case "ending":
      return !client.locked && (client.tone === "soon" || client.tone === "urgent" || client.tone === "grace");
    case "active":
      return !client.locked && client.plan === "active" && client.hasFullAccess;
    case "locked":
      return client.locked;
    default:
      return true;
  }
}

type Sort = "urgency" | "name" | "newest";

const SORTS: { key: Sort; label: string }[] = [
  { key: "urgency", label: "Ističe najskorije" },
  { key: "name", label: "Naziv (A–Š)" },
  { key: "newest", label: "Najnoviji prvo" },
];

// How urgently this client needs attention: lower sorts first. Locked and
// lapsed accounts lead, then whoever is closest to expiry; unlimited and basic
// accounts have no clock, so they sink to the bottom.
function urgencyRank(client: Client) {
  if (client.locked) return -1;
  if (client.tone === "grace") return Math.max(0, client.graceDaysLeft ?? 0);
  if (client.plan === "trial") {
    return client.hasFullAccess ? 100 + (client.trialDaysLeft ?? 0) : 50;
  }
  if (client.plan === "basic") return 9000;
  if (client.planUnlimited) return 9500;
  return 100 + (client.planDaysLeft ?? 0);
}

// With hundreds of restaurants the list must stay light: rows render collapsed
// and only a slice is mounted until "Prikaži još" asks for more.
const PAGE_SIZE = 60;

export default function PlatformPanel() {
  const [clients, setClients] = useState<Client[] | null>(null);
  const [error, setError] = useState<string | null>(null);
  const [filter, setFilter] = useState<Filter>("all");
  const [search, setSearch] = useState("");
  const [sort, setSort] = useState<Sort>("urgency");
  const [limit, setLimit] = useState(PAGE_SIZE);

  async function load() {
    const response = await fetch("/api/platform/plans", {
      cache: "no-store",
      credentials: "same-origin",
    });
    if (response.status === 401) {
      window.location.assign("/login?next=%2Fplatforma");
      return;
    }
    const payload = await response.json().catch(() => null);
    if (!response.ok || !payload?.ok) {
      setError(payload?.error?.message ?? "Podaci nisu dostupni.");
      setClients([]);
      return;
    }
    setClients(payload.clients);
  }

  useEffect(() => {
    void load();
  }, []);

  const counts = useMemo(() => {
    const rows = clients ?? [];
    return {
      total: rows.length,
      trial: rows.filter((row) => matchesFilter(row, "trial")).length,
      basic: rows.filter((row) => matchesFilter(row, "basic")).length,
      ending: rows.filter((row) => matchesFilter(row, "ending")).length,
      active: rows.filter((row) => matchesFilter(row, "active")).length,
      locked: rows.filter((row) => row.locked).length,
    };
  }, [clients]);

  const visible = useMemo(() => {
    const needle = search.trim().toLowerCase();
    const rows = (clients ?? []).filter((client) => {
      if (!matchesFilter(client, filter)) return false;
      if (!needle) return true;
      const haystack = [
        client.name,
        client.slug,
        client.ownerEmail ?? "",
        client.city,
        client.address,
        client.contactPhone,
        ...client.members.map((member) => `${member.name} ${member.email} ${member.phone} ${member.mobile}`),
      ]
        .join(" ")
        .toLowerCase();
      return haystack.includes(needle);
    });
    if (sort === "name") {
      rows.sort((a, b) => a.name.localeCompare(b.name, "sr-Latn"));
    } else if (sort === "newest") {
      rows.sort((a, b) => String(b.createdAt).localeCompare(String(a.createdAt)));
    } else {
      rows.sort((a, b) => urgencyRank(a) - urgencyRank(b) || a.name.localeCompare(b.name, "sr-Latn"));
    }
    return rows;
  }, [clients, filter, search, sort]);

  function pickFilter(next: Filter) {
    setFilter(next);
    setLimit(PAGE_SIZE);
  }

  if (clients === null) return <p className="platform-loading">Učitavamo klijente…</p>;

  const shown = visible.slice(0, limit);

  return (
    <>
      <div className="platform-stats">
        <button type="button" className={filter === "all" ? "active" : ""} onClick={() => pickFilter("all")}><b>{counts.total}</b><span>restorana ukupno</span></button>
        <button type="button" className={`tone-trial ${filter === "trial" ? "active" : ""}`} onClick={() => pickFilter("trial")}><b>{counts.trial}</b><span>u probnom periodu</span></button>
        <button type="button" className={`tone-basic ${filter === "basic" ? "active" : ""}`} onClick={() => pickFilter("basic")}><b>{counts.basic}</b><span>samo basic</span></button>
        <button type="button" className={`tone-ok ${filter === "active" ? "active" : ""}`} onClick={() => pickFilter("active")}><b>{counts.active}</b><span>aktivnih pretplata</span></button>
        <button type="button" className={`tone-urgent ${filter === "ending" ? "active" : ""}`} onClick={() => pickFilter("ending")}><b>{counts.ending}</b><span>ističe uskoro</span></button>
        <button type="button" className={`tone-locked ${filter === "locked" ? "active" : ""}`} onClick={() => pickFilter("locked")}><b>{counts.locked}</b><span>zaključanih</span></button>
      </div>

      <div className="platform-toolbar">
        <div className="platform-filters">
          {FILTERS.map((entry) => (
            <button
              type="button"
              key={entry.key}
              className={filter === entry.key ? "active" : ""}
              onClick={() => pickFilter(entry.key)}
            >
              {entry.label}
            </button>
          ))}
        </div>
        <select
          className="platform-sort"
          value={sort}
          aria-label="Redosled"
          onChange={(event) => setSort(event.target.value as Sort)}
        >
          {SORTS.map((entry) => <option key={entry.key} value={entry.key}>{entry.label}</option>)}
        </select>
        <input
          className="platform-search"
          value={search}
          placeholder="Pretraga: naziv, email, grad, telefon, osoba…"
          onChange={(event) => { setSearch(event.target.value); setLimit(PAGE_SIZE); }}
        />
      </div>

      <p className="platform-count">
        {visible.length === clients.length
          ? `${visible.length} restorana`
          : `${visible.length} od ${clients.length} restorana`}
      </p>

      {error && <div className="auth-error" role="alert">{error}</div>}

      <div className="platform-list">
        {shown.map((client) => (
          <ClientCard key={client.id} client={client} onChanged={load} onError={setError} />
        ))}
        {!visible.length && (
          <p className="platform-loading">
            {clients.length ? "Nema restorana u ovom filteru." : "Još nema registrovanih restorana."}
          </p>
        )}
        {visible.length > shown.length && (
          <button type="button" className="platform-more" onClick={() => setLimit(limit + PAGE_SIZE)}>
            Prikaži još ({visible.length - shown.length} preostalo)
          </button>
        )}
      </div>
    </>
  );
}

async function postPlan(body: Record<string, unknown>) {
  const response = await fetch("/api/platform/plans", {
    method: "POST",
    credentials: "same-origin",
    headers: { "Content-Type": "application/json" },
    body: JSON.stringify(body),
  });
  const payload = await response.json().catch(() => null);
  if (!response.ok || !payload?.ok) {
    throw new Error(payload?.error?.message ?? "Radnja nije uspela.");
  }
  return payload;
}

async function callMembers(method: "POST" | "PATCH" | "DELETE", body: Record<string, unknown>) {
  const response = await fetch("/api/platform/members", {
    method,
    credentials: "same-origin",
    headers: { "Content-Type": "application/json" },
    body: JSON.stringify(body),
  });
  const payload = await response.json().catch(() => null);
  if (!response.ok || !payload?.ok) {
    throw new Error(payload?.error?.message ?? "Radnja nije uspela.");
  }
  return payload;
}

function ClientCard({
  client,
  onChanged,
  onError,
}: {
  client: Client;
  onChanged: () => Promise<void>;
  onError: (message: string | null) => void;
}) {
  const [expanded, setExpanded] = useState(false);
  const [open, setOpen] = useState<"none" | "people" | "details">("none");
  const [months, setMonths] = useState(String(client.planMonths ?? 1));
  const [note, setNote] = useState(client.planNote ?? "");
  const [busy, setBusy] = useState<string | null>(null);

  const managers = client.members.filter(
    (member) => member.role === "owner" || member.role === "manager",
  );

  async function run(label: string, body: Record<string, unknown>) {
    setBusy(label);
    onError(null);
    try {
      await postPlan({ slug: client.slug, note, ...body });
      await onChanged();
    } catch (problem) {
      onError(problem instanceof Error ? problem.message : "Radnja nije uspela.");
    } finally {
      setBusy(null);
    }
  }

  const monthCount = Math.min(36, Math.max(1, Number.parseInt(months, 10) || 1));

  return (
    <article className={`platform-row tone-${client.tone} ${expanded ? "expanded" : "collapsed"}`}>
      <div className="platform-row-main">
        <button
          type="button"
          className="platform-row-summary"
          aria-expanded={expanded}
          onClick={() => setExpanded(!expanded)}
        >
          <div className="platform-row-title">
            <strong>{client.name}</strong>
            <span className={`platform-badge tone-${client.tone}`}>{badgeLabel(client)}</span>
          </div>
          <small>
            /{client.slug} · {client.currency}
            {client.city ? ` · ${client.city}` : ""}
            {client.ownerEmail ? ` · ${client.ownerEmail}` : ""}
            {client.contactPhone ? ` · ${client.contactPhone}` : ""}
          </small>
          <b className="platform-status">{statusLine(client)}</b>
          <i className="platform-caret">{expanded ? "▴ Zatvori" : "▾ Detalji i naplata"}</i>
        </button>

        {expanded && <>
        <small>registrovan {shortDate(client.createdAt)}</small>
        <em>
          {client.tableCount} stolova · {client.itemCount} jela · {client.ticketCount} zahteva
        </em>

        <dl className="platform-contact">
          <div>
            <dt>Kontakt email</dt>
            <dd>{client.ownerEmail ?? "—"}</dd>
          </div>
          <div>
            <dt>Telefon restorana</dt>
            <dd>{client.contactPhone || "—"}</dd>
          </div>
          <div>
            <dt>Adresa</dt>
            <dd>{client.address || "—"}</dd>
          </div>
          <div>
            <dt>Grad i poštanski broj</dt>
            <dd>{[client.city, client.postalCode].filter(Boolean).join(" ") || "—"}</dd>
          </div>
        </dl>

        {managers.length ? (
          <ul className="platform-managers">
            {managers.map((member) => (
              <li key={member.id}>
                <strong>{member.name || member.email}</strong>
                <span>{member.roleLabel}</span>
                <span>{member.email}</span>
                {member.phone && <span>tel {member.phone}</span>}
                {member.mobile && <span>mob {member.mobile}</span>}
                {!member.isActive && <i>nalog nije aktivan</i>}
              </li>
            ))}
          </ul>
        ) : (
          <p className="platform-empty">Nema upisanog vlasnika ni menadžera.</p>
        )}

        {client.planNote && <i className="platform-note">Beleška: {client.planNote}</i>}

        <div className="platform-row-tabs">
          <button
            type="button"
            className={open === "people" ? "active" : ""}
            onClick={() => setOpen(open === "people" ? "none" : "people")}
          >
            Osoblje i nalozi ({client.members.length})
          </button>
          <button
            type="button"
            className={open === "details" ? "active" : ""}
            onClick={() => setOpen(open === "details" ? "none" : "details")}
          >
            Podaci restorana
          </button>
          <a href={`/admin?restaurant=${encodeURIComponent(client.slug)}`} target="_blank" rel="noreferrer">
            Otvori admin ↗
          </a>
        </div>

        {open === "people" && (
          <MembersEditor client={client} onChanged={onChanged} onError={onError} />
        )}
        {open === "details" && (
          <DetailsEditor client={client} onChanged={onChanged} onError={onError} />
        )}
        </>}
      </div>

      {expanded && <div className="platform-row-side">
        <label className="platform-months">
          Meseci pretplate
          <input
            inputMode="numeric"
            value={months}
            maxLength={2}
            onChange={(event) => setMonths(event.target.value.replace(/[^0-9]/g, ""))}
          />
        </label>
        <button
          className="primary-button"
          disabled={busy !== null}
          onClick={() => void run("activate", { action: "activate", months: monthCount })}
        >
          {busy === "activate"
            ? "Otključavanje…"
            : client.hasFullAccess && client.plan === "active"
              ? `Produži ${monthCount} mes.`
              : `Otključaj na ${monthCount} mes.`}
        </button>
        <input
          value={note}
          placeholder="Beleška (npr. faktura 114)"
          maxLength={200}
          onChange={(event) => setNote(event.target.value)}
          onBlur={() => {
            if ((client.planNote ?? "") !== note) void run("note", { action: "note" });
          }}
        />
        <button
          className="secondary-button"
          disabled={busy !== null || (client.plan === "basic" && !client.locked)}
          onClick={() => void run("basic", { action: "basic" })}
        >
          {busy === "basic" ? "Menjamo…" : "Vrati na basic"}
        </button>
        <button
          className="secondary-button"
          disabled={busy !== null}
          onClick={() => void run("trial", { action: "trial" })}
        >
          {busy === "trial" ? "Menjamo…" : "Probni period 30 dana"}
        </button>
        {client.locked ? (
          <button
            className="primary-button"
            disabled={busy !== null}
            onClick={() => void run("unlock", { action: "unlock" })}
          >
            {busy === "unlock" ? "Otključavamo…" : "Otključaj nalog"}
          </button>
        ) : (
          <button
            className="danger-button"
            disabled={busy !== null}
            onClick={() => {
              if (
                window.confirm(
                  `Zaključati nalog „${client.name}"? Meni, poručivanje i poziv konobaru prestaju da rade, a osoblje ne može da uđe u admin panel dok ga ne otključate.`,
                )
              ) {
                void run("lock", { action: "lock" });
              }
            }}
          >
            {busy === "lock" ? "Zaključavamo…" : "Zaključaj kompletno"}
          </button>
        )}
      </div>}
    </article>
  );
}

function MembersEditor({
  client,
  onChanged,
  onError,
}: {
  client: Client;
  onChanged: () => Promise<void>;
  onError: (message: string | null) => void;
}) {
  const [editing, setEditing] = useState<string | null>(null);
  const [draft, setDraft] = useState<Partial<Member>>({});
  const [busy, setBusy] = useState<string | null>(null);
  const [message, setMessage] = useState<string | null>(null);
  const [adding, setAdding] = useState(false);
  const [form, setForm] = useState({
    fullName: "",
    email: "",
    role: "staff" as Member["role"],
    phone: "",
    mobile: "",
    password: "",
  });

  async function act(key: string, run: () => Promise<string | null>) {
    setBusy(key);
    onError(null);
    setMessage(null);
    try {
      const note = await run();
      await onChanged();
      if (note) setMessage(note);
    } catch (problem) {
      onError(problem instanceof Error ? problem.message : "Radnja nije uspela.");
    } finally {
      setBusy(null);
    }
  }

  async function submitNew(event: FormEvent) {
    event.preventDefault();
    await act("add", async () => {
      const wasQueue = form.role === "queue";
      const payload = await callMembers("POST", { slug: client.slug, ...form });
      setForm({ fullName: "", email: "", role: "staff", phone: "", mobile: "", password: "" });
      setAdding(false);
      if (payload.hadAccount) {
        return `${form.email} je dodat — taj email već ima MeniFlow nalog, pa se prijavljuje postojećom lozinkom.`;
      }
      if (wasQueue) {
        return `Ekran nalog je dodat — bez email-a. Na ekranu se prijavljujete adresom ${form.email} i unetom lozinkom.`;
      }
      return payload.invited
        ? `Poslali smo ${form.email} email sa linkom za postavljanje lozinke.`
        : `Nalog je napravljen, ali email nije poslat. Kliknite „Pošalji reset lozinke" ili proverite SMTP podešavanja.`;
    });
  }

  return (
    <div className="platform-people">
      <table>
        <thead>
          <tr>
            <th>Ime i prezime</th>
            <th>Uloga</th>
            <th>Email</th>
            <th>Telefon</th>
            <th>Mobilni</th>
            <th>Nalog</th>
            <th />
          </tr>
        </thead>
        <tbody>
          {client.members.map((member) =>
            editing === member.id ? (
              <tr key={member.id} className="editing">
                <td>
                  <input
                    value={draft.fullName ?? member.name}
                    maxLength={100}
                    onChange={(event) => setDraft((current) => ({ ...current, fullName: event.target.value }))}
                  />
                </td>
                <td>
                  <select
                    value={draft.role ?? member.role}
                    onChange={(event) =>
                      setDraft((current) => ({ ...current, role: event.target.value as Member["role"] }))
                    }
                  >
                    {ROLE_OPTIONS.map((option) => (
                      <option key={option.value} value={option.value}>
                        {option.label}
                      </option>
                    ))}
                  </select>
                </td>
                <td>{member.email}</td>
                <td>
                  <input
                    value={draft.phone ?? member.phone}
                    maxLength={30}
                    onChange={(event) => setDraft((current) => ({ ...current, phone: event.target.value }))}
                  />
                </td>
                <td>
                  <input
                    value={draft.mobile ?? member.mobile}
                    maxLength={30}
                    onChange={(event) => setDraft((current) => ({ ...current, mobile: event.target.value }))}
                  />
                </td>
                <td>{member.hasLogin ? (member.isActive ? "aktivan" : "isključen") : "bez naloga"}</td>
                <td className="platform-people-actions">
                  <button
                    type="button"
                    className="primary-button"
                    disabled={busy !== null}
                    onClick={() =>
                      void act("save", async () => {
                        await callMembers("PATCH", {
                          slug: client.slug,
                          memberId: member.id,
                          fullName: draft.fullName ?? member.name,
                          role: draft.role ?? member.role,
                          phone: draft.phone ?? member.phone,
                          mobile: draft.mobile ?? member.mobile,
                        });
                        setEditing(null);
                        setDraft({});
                        return null;
                      })
                    }
                  >
                    Sačuvaj
                  </button>
                  <button type="button" onClick={() => { setEditing(null); setDraft({}); }}>
                    Otkaži
                  </button>
                </td>
              </tr>
            ) : (
              <tr key={member.id}>
                <td>{member.name || "—"}</td>
                <td>{member.roleLabel}</td>
                <td>{member.email}</td>
                <td>{member.phone || "—"}</td>
                <td>{member.mobile || "—"}</td>
                <td>{member.hasLogin ? (member.isActive ? "aktivan" : "isključen") : "bez naloga"}</td>
                <td className="platform-people-actions">
                  <button type="button" onClick={() => { setEditing(member.id); setDraft({}); }}>
                    Uredi
                  </button>
                  <button
                    type="button"
                    disabled={busy !== null || !member.hasLogin}
                    onClick={() =>
                      void act(`reset-${member.id}`, async () => {
                        await callMembers("POST", {
                          action: "reset",
                          slug: client.slug,
                          memberId: member.id,
                        });
                        return `Link za novu lozinku je poslat na ${member.email}. Važi 1 sat.`;
                      })
                    }
                  >
                    {busy === `reset-${member.id}` ? "Šaljemo…" : "Pošalji reset lozinke"}
                  </button>
                  <button
                    type="button"
                    className="danger-link"
                    disabled={busy !== null}
                    onClick={() => {
                      if (!window.confirm(`Ukloniti ${member.email} iz restorana ${client.name}?`)) return;
                      void act(`remove-${member.id}`, async () => {
                        await callMembers("DELETE", { slug: client.slug, memberId: member.id });
                        return null;
                      });
                    }}
                  >
                    Ukloni
                  </button>
                </td>
              </tr>
            ),
          )}
          {!client.members.length && (
            <tr>
              <td colSpan={7}>Nijedna osoba još nije upisana u ovaj restoran.</td>
            </tr>
          )}
        </tbody>
      </table>

      {message && <p className="platform-ok" role="status">{message}</p>}

      {adding ? (
        <form className="platform-add-person" onSubmit={submitNew}>
          <label>
            Ime i prezime
            <input
              value={form.fullName}
              maxLength={100}
              required
              onChange={(event) => setForm((current) => ({ ...current, fullName: event.target.value }))}
              placeholder="npr. Jelena Jovanović"
            />
          </label>
          <label>
            Email
            <input
              type="email"
              value={form.email}
              maxLength={160}
              required
              onChange={(event) => setForm((current) => ({ ...current, email: event.target.value }))}
              placeholder="jelena@restoran.rs"
            />
          </label>
          <label>
            Uloga
            <select
              value={form.role}
              onChange={(event) => setForm((current) => ({ ...current, role: event.target.value as Member["role"] }))}
            >
              {ROLE_OPTIONS.map((option) => (
                <option key={option.value} value={option.value}>
                  {option.label}
                </option>
              ))}
            </select>
          </label>
          <label>
            Telefon
            <input
              value={form.phone}
              maxLength={30}
              onChange={(event) => setForm((current) => ({ ...current, phone: event.target.value }))}
              placeholder="011 234 5678"
            />
          </label>
          <label>
            Mobilni telefon
            <input
              value={form.mobile}
              maxLength={30}
              onChange={(event) => setForm((current) => ({ ...current, mobile: event.target.value }))}
              placeholder="064 123 4567"
            />
          </label>
          {form.role === "queue" && <label>
            Lozinka ekrana
            <input
              type="password"
              value={form.password}
              required
              minLength={12}
              maxLength={200}
              onChange={(event) => setForm((current) => ({ ...current, password: event.target.value }))}
              placeholder="Najmanje 12 znakova, slovo i broj"
            />
          </label>}
          <div className="platform-add-actions">
            <button className="primary-button" type="submit" disabled={busy !== null}>
              {busy === "add" ? "Dodajemo…" : "Dodaj u restoran"}
            </button>
            <button type="button" onClick={() => setAdding(false)}>
              Otkaži
            </button>
          </div>
          <small>
            {form.role === "queue"
              ? "Ekran nalog ne dobija email — prijavljuje se lozinkom koju ovde unesete."
              : "Osoba dobija email sa linkom da sama postavi lozinku. Ako taj email već ima MeniFlow nalog, koristi svoju postojeću lozinku."}
          </small>
        </form>
      ) : (
        <button className="secondary-button" type="button" onClick={() => setAdding(true)}>
          ＋ Dodaj osobu u restoran
        </button>
      )}
    </div>
  );
}

function DetailsEditor({
  client,
  onChanged,
  onError,
}: {
  client: Client;
  onChanged: () => Promise<void>;
  onError: (message: string | null) => void;
}) {
  const [form, setForm] = useState({
    ownerEmail: client.ownerEmail ?? "",
    contactPhone: client.contactPhone,
    address: client.address,
    city: client.city,
    postalCode: client.postalCode,
  });
  const [busy, setBusy] = useState(false);
  const [saved, setSaved] = useState(false);

  async function submit(event: FormEvent) {
    event.preventDefault();
    setBusy(true);
    setSaved(false);
    onError(null);
    try {
      await postPlan({ action: "details", slug: client.slug, ...form });
      await onChanged();
      setSaved(true);
    } catch (problem) {
      onError(problem instanceof Error ? problem.message : "Podaci nisu sačuvani.");
    } finally {
      setBusy(false);
    }
  }

  return (
    <form className="platform-details" onSubmit={submit}>
      <label>
        Kontakt email
        <input
          type="email"
          value={form.ownerEmail}
          maxLength={160}
          onChange={(event) => setForm((current) => ({ ...current, ownerEmail: event.target.value }))}
        />
      </label>
      <label>
        Telefon restorana
        <input
          value={form.contactPhone}
          maxLength={30}
          onChange={(event) => setForm((current) => ({ ...current, contactPhone: event.target.value }))}
          placeholder="011 234 5678"
        />
      </label>
      <label className="wide">
        Adresa
        <input
          value={form.address}
          maxLength={160}
          onChange={(event) => setForm((current) => ({ ...current, address: event.target.value }))}
          placeholder="Cara Dušana 12"
        />
      </label>
      <label>
        Grad
        <input
          value={form.city}
          maxLength={80}
          onChange={(event) => setForm((current) => ({ ...current, city: event.target.value }))}
          placeholder="Beograd"
        />
      </label>
      <label>
        Poštanski broj
        <input
          value={form.postalCode}
          maxLength={20}
          onChange={(event) => setForm((current) => ({ ...current, postalCode: event.target.value }))}
          placeholder="11000"
        />
      </label>
      <div className="platform-add-actions">
        <button className="primary-button" type="submit" disabled={busy}>
          {busy ? "Čuvamo…" : "Sačuvaj podatke"}
        </button>
        {saved && <span className="platform-ok">Sačuvano.</span>}
      </div>
    </form>
  );
}
