// Aria console — schermata dell'organizzazione ATTIVA: stato del dominio
// (polling durante il provisioning, retry, porta-online), membri e ruoli,
// trasferimento ownership, eliminazione (= sospensione del dominio).
// L'interfaccia si adatta al ruolo dell'utente (view.role): le azioni che il
// backend rifiuterebbe non vengono proprio mostrate.
const { Card, Badge, Banner, Button, IconButton, Icon, Select, Dialog, Avatar, TextField } = window.AriaDesignSystem_af77ab;

const ORG_ROLE_RANK = { viewer: 1, editor: 2, manager: 3, admin: 4, owner: 5 };
const orgRoleAtLeast = (role, min) => (ORG_ROLE_RANK[role] || 0) >= ORG_ROLE_RANK[min];
const ORG_ROLE_OPTIONS = [
  { value: "viewer", label: "Viewer" },
  { value: "editor", label: "Editor" },
  { value: "manager", label: "Manager" },
  { value: "admin", label: "Admin" },
];

// Ruoli proponibili in un invito: i manager solo sotto il proprio, admin/owner
// tutto tranne owner (stessa regola canAssignRole del backend, qui solo cosmesi).
const inviteRoleOptions = (myRole) =>
  ORG_ROLE_OPTIONS.filter((o) => (myRole === "manager" ? ORG_ROLE_RANK[o.value] < ORG_ROLE_RANK.manager : true));
const ORG_ROLE_LABEL = { viewer: "Viewer", editor: "Editor", manager: "Manager", admin: "Admin", owner: "Owner" };

// Stato del dominio in linguaggio utente (il badge grezzo sta in AppShell).
const DOMAIN_STATUS_TEXT = {
  offline: "Offline: l'organizzazione vive solo in Aria, nessun dominio richiesto.",
  provisioning: "Provisioning in corso: il dominio è in creazione…",
  active: "Dominio attivo e conversante.",
  failed: "Il provisioning del dominio è fallito.",
  suspended: "Dominio sospeso: i nuovi accessi sono negati.",
  pending_verification: "In attesa della verifica email.",
};

function SectionCard({ title, subtitle, actions, children }) {
  return (
    <Card>
      <div style={{ padding: "16px 18px", display: "flex", flexDirection: "column", gap: 14 }}>
        <div style={{ display: "flex", alignItems: "center", gap: 10 }}>
          <div style={{ display: "flex", flexDirection: "column", gap: 2, flex: 1, minWidth: 0 }}>
            <span style={{ font: "var(--fw-semibold) 15px/1.3 var(--font-sans)", color: "var(--text-strong)" }}>{title}</span>
            {subtitle && <span style={{ fontSize: 12, color: "var(--text-muted)" }}>{subtitle}</span>}
          </div>
          <div style={{ display: "flex", gap: 8 }}>{actions}</div>
        </div>
        {children}
      </div>
    </Card>
  );
}

// Sezione inviti (manager e superiori): crea l'invito e consegna SEMPRE il
// link copiabile (il token si vede solo qui, alla creazione); l'email parte
// in più quando il backend ha un transport SMTP configurato.
function InvitationsSection({ myRole, notify }) {
  const [invites, setInvites] = React.useState(null); // null = caricamento
  const [email, setEmail] = React.useState("");
  const [role, setRole] = React.useState("viewer");
  const [busy, setBusy] = React.useState(false);
  const [created, setCreated] = React.useState(null); // { link, email, emailSent }
  const [reloadKey, setReloadKey] = React.useState(0);

  React.useEffect(() => {
    let alive = true;
    window.AriaData.listInvites().then(
      (list) => { if (alive) setInvites(list); },
      () => { if (alive) setInvites([]); }
    );
    return () => { alive = false; };
  }, [reloadKey]);

  async function invite(e) {
    e.preventDefault();
    setBusy(true);
    try {
      const res = await window.AriaData.createInvite(email.trim(), role);
      if (res.ok) {
        setCreated({ link: window.location.origin + res.invitePath, email: res.email, emailSent: res.emailSent });
        setEmail("");
        setReloadKey((k) => k + 1);
      } else {
        notify({ tone: "danger", title: "Invito non creato", body: res.error });
      }
    } finally { setBusy(false); }
  }

  async function revoke(inv) {
    const res = await window.AriaData.revokeInvite(inv.id);
    if (res.ok) notify({ tone: "success", title: "Invito revocato", body: inv.email });
    else notify({ tone: "danger", title: "Revoca non riuscita", body: res.error });
    setReloadKey((k) => k + 1);
  }

  async function copyLink() {
    try {
      await navigator.clipboard.writeText(created.link);
      notify({ tone: "success", title: "Link copiato", body: "Invialo alla persona invitata." });
    } catch (_e) { /* clipboard negata: il link resta selezionabile a mano */ }
  }

  return (
    <SectionCard
      title={`Inviti${invites != null ? ` (${invites.length} in attesa)` : ""}`}
      subtitle="La registrazione è solo a invito: il link è la porta d'ingresso."
    >
      <form onSubmit={invite} style={{ display: "flex", gap: 10, alignItems: "flex-end" }}>
        <span style={{ flex: 1 }}>
          <TextField label="Email" required value={email} placeholder="persona@azienda.it" onChange={(e) => setEmail(e.target.value)} />
        </span>
        <span style={{ width: 130 }}>
          <Select label="Ruolo" value={role} options={inviteRoleOptions(myRole)} onChange={(e) => setRole(e.target.value)} />
        </span>
        <Button variant="primary" type="submit" disabled={busy || email.trim() === ""}
          iconLeft={busy ? <Icon name="loader" size={15} color="#fff" /> : <Icon name="mail-plus" size={15} color="#fff" />}>
          Invita
        </Button>
      </form>

      {created && (
        <Banner tone="success" title={created.emailSent ? `Invito inviato a ${created.email}` : `Invito creato per ${created.email}`} icon="mail-check">
          <div style={{ display: "flex", flexDirection: "column", gap: 8 }}>
            {!created.emailSent && <span>L'email non è configurata: consegna tu il link.</span>}
            <div style={{ display: "flex", gap: 8, alignItems: "center" }}>
              <code style={{ fontSize: 12, background: "var(--surface-app)", padding: "6px 8px", borderRadius: 6, overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap", flex: 1 }}>{created.link}</code>
              <Button variant="secondary" size="sm" iconLeft={<Icon name="copy" size={14} />} onClick={copyLink}>Copia</Button>
            </div>
          </div>
        </Banner>
      )}

      {invites != null && invites.length > 0 && (
        <div style={{ display: "flex", flexDirection: "column" }}>
          {invites.map((inv) => (
            <div key={inv.id} style={{ display: "flex", alignItems: "center", gap: 12, padding: "9px 2px", borderBottom: "1px solid var(--border-subtle)" }}>
              <Icon name="mail" size={16} color="var(--text-subtle)" />
              <span style={{ flex: 1, minWidth: 0, display: "flex", flexDirection: "column", lineHeight: 1.25 }}>
                <span style={{ fontSize: 13.5, color: "var(--text-strong)", overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap" }}>{inv.email}</span>
                <span style={{ fontSize: 12, color: "var(--text-subtle)" }}>
                  invitato da {inv.invitedByUsername} · scade il {new Date(inv.expiresAt).toLocaleDateString("it-IT")}
                </span>
              </span>
              {inv.expired ? <Badge tone="danger">scaduto</Badge> : <Badge tone="neutral">{ORG_ROLE_LABEL[inv.role] || inv.role}</Badge>}
              <IconButton label="Revoca invito" onClick={() => revoke(inv)}><Icon name="trash-2" size={15} /></IconButton>
            </div>
          ))}
        </div>
      )}
    </SectionCard>
  );
}

function OrganizationPanel({ onChanged, notify }) {
  const { user, applyTokens } = window.AriaAuth.useAuth();
  const [view, setView] = React.useState(null);       // { organization, role, members } | null
  const [loadError, setLoadError] = React.useState(null);
  const [domainInfo, setDomainInfo] = React.useState(null); // { organization, domain?, provisionerUnreachable? }
  const [reloadKey, setReloadKey] = React.useState(0);
  const [busy, setBusy] = React.useState(false);
  const [confirm, setConfirm] = React.useState(null); // { kind: 'remove'|'leave'|'delete', member? }
  const [transferTo, setTransferTo] = React.useState(null); // userId | null (dialog aperto)
  const [goOnline, setGoOnline] = React.useState(false);

  const reload = () => setReloadKey((k) => k + 1);

  // Caricamento: vista membri (GET /org) + stato dominio (GET /org/domain, che
  // riconcilia la cache col provisioner — o degrada se irraggiungibile).
  React.useEffect(() => {
    let alive = true;
    setLoadError(null);
    window.AriaData.getOrg().then(
      (v) => { if (alive) setView(v); },
      (err) => { if (alive) setLoadError(err); }
    );
    window.AriaData.getDomainStatus().then(
      (info) => { if (alive) setDomainInfo(info); },
      () => { /* lo stato del dominio è accessorio: la pagina vive con la cache */ }
    );
    return () => { alive = false; };
  }, [reloadKey]);

  const organization = (domainInfo && domainInfo.organization) || (view && view.organization) || null;
  const status = organization ? organization.status : null;
  const myRole = view ? view.role : null;
  const canAdmin = myRole != null && orgRoleAtLeast(myRole, "admin");
  const isOwner = myRole === "owner";

  // Polling: finché il provisioning è in corso la pagina si aggiorna da sola.
  React.useEffect(() => {
    if (status !== "provisioning") return undefined;
    const t = setInterval(async () => {
      try {
        const info = await window.AriaData.getDomainStatus();
        setDomainInfo(info);
        if (info.organization.status !== "provisioning") {
          onChanged && onChanged(); // il badge nella sidebar deve convergere
          if (info.organization.status === "active") notify({ tone: "success", title: "Dominio attivo", body: "Il provisioning è andato a buon fine." });
          if (info.organization.status === "failed") notify({ tone: "danger", title: "Provisioning fallito", body: "Puoi ritentare gli step falliti." });
        }
      } catch (_e) { /* il prossimo giro riprova */ }
    }, 4000);
    return () => clearInterval(t);
  }, [status]);

  async function refreshStatus() {
    try {
      setDomainInfo(await window.AriaData.getDomainStatus());
      onChanged && onChanged();
    } catch (err) {
      notify({ tone: "danger", title: "Aggiornamento non riuscito", body: err.message || "Riprova." });
    }
  }

  async function retry() {
    setBusy(true);
    try {
      const res = await window.AriaData.retryDomain();
      if (res.ok) { setDomainInfo({ organization: res.organization }); onChanged && onChanged(); }
      else notify({ tone: "danger", title: "Retry non riuscito", body: res.error });
    } finally { setBusy(false); }
  }

  async function changeRole(member, role) {
    const res = await window.AriaData.setMemberRole(member.userId, role);
    if (res.ok) {
      notify({ tone: "success", title: "Ruolo aggiornato", body: `${member.username} → ${ORG_ROLE_LABEL[role]}` });
      reload();
    } else {
      notify({ tone: "danger", title: "Cambio ruolo non riuscito", body: res.error });
    }
  }

  async function confirmAction() {
    if (!confirm) return;
    setBusy(true);
    try {
      if (confirm.kind === "delete") {
        const res = await window.AriaData.deleteOrg();
        if (res.ok) {
          notify({ tone: "danger", title: "Organizzazione eliminata", body: "Dominio sospeso e assistenti disattivati." });
          onChanged && onChanged();
          reload();
        } else {
          notify({ tone: "danger", title: "Eliminazione non riuscita", body: res.error });
        }
      } else {
        // remove | leave: stessa API; per l'uscita servono token nuovi (l'org
        // attiva del token non esiste più per l'utente).
        const res = await window.AriaData.removeMember(confirm.member.userId);
        if (res.ok) {
          if (confirm.kind === "leave") {
            await window.AriaAuth.refresh(); // token riemessi sulla membership di default
            notify({ tone: "success", title: "Sei uscito dall'organizzazione", body: "" });
          } else {
            notify({ tone: "success", title: "Membro rimosso", body: confirm.member.username });
          }
          onChanged && onChanged();
          reload();
        } else {
          notify({ tone: "danger", title: "Operazione non riuscita", body: res.error });
        }
      }
      setConfirm(null);
    } finally { setBusy(false); }
  }

  async function doTransfer() {
    if (!transferTo) return;
    setBusy(true);
    try {
      const res = await window.AriaData.transferOwnership(transferTo);
      if (res.ok) {
        if (res.tokens) await applyTokens(res.tokens); // il vecchio owner è ora admin
        notify({ tone: "success", title: "Ownership trasferita", body: "" });
        setTransferTo(null);
        onChanged && onChanged();
        reload();
      } else {
        notify({ tone: "danger", title: "Trasferimento non riuscito", body: res.error });
      }
    } finally { setBusy(false); }
  }

  if (loadError) {
    return (
      <div style={{ padding: 28 }}>
        <Banner tone="danger" title="Impossibile caricare l'organizzazione" icon="alert-circle">
          <span>{loadError.message || "Errore inatteso."} </span>
          <Button variant="ghost" size="sm" onClick={reload}>Riprova</Button>
        </Banner>
      </div>
    );
  }
  if (view === null) {
    return (
      <div style={{ flex: 1, display: "flex", alignItems: "center", justifyContent: "center", gap: 10, color: "var(--text-muted)", padding: 40 }}>
        <Icon name="loader" size={22} color="var(--text-subtle)" />
        <span style={{ fontSize: 14 }}>Caricamento organizzazione…</span>
      </div>
    );
  }

  const me = view.members.find((m) => user && m.userId === user.id) || null;
  const others = view.members.filter((m) => !me || m.userId !== me.userId);
  const saga = domainInfo && domainInfo.domain && Array.isArray(domainInfo.domain.steps) ? domainInfo.domain.steps : null;
  // Dominio fuori dalla gestione del provisioner (es. organizzazione migrata,
  // dominio creato prima del provisioner): retry/sospensione verrebbero
  // rifiutati dal backend → non li offriamo proprio.
  const unmanaged = !!(domainInfo && domainInfo.unmanaged);

  return (
    <div style={{ padding: 24, display: "flex", flexDirection: "column", gap: 18, maxWidth: 860 }}>
      {/* --- Dominio ------------------------------------------------------- */}
      <SectionCard
        title={<span style={{ display: "inline-flex", alignItems: "center", gap: 8 }}>Dominio «{organization.domain}» {React.createElement(window.OrgStatusBadge, { status })}</span>}
        subtitle={DOMAIN_STATUS_TEXT[status] || status}
        actions={
          <React.Fragment>
            {status === "offline" && canAdmin && (
              <Button variant="primary" size="sm" iconLeft={<Icon name="cloud-upload" size={15} color="#fff" />} onClick={() => setGoOnline(true)}>Porta online</Button>
            )}
            {status === "failed" && canAdmin && !unmanaged && (
              <Button variant="primary" size="sm" disabled={busy} iconLeft={<Icon name="refresh-cw" size={15} color="#fff" />} onClick={retry}>Riprova provisioning</Button>
            )}
            <IconButton label="Aggiorna stato" onClick={refreshStatus}><Icon name="refresh-cw" size={15} /></IconButton>
          </React.Fragment>
        }
      >
        {domainInfo && domainInfo.provisionerUnreachable && (
          <Banner tone="warning" title="Provisioning non raggiungibile" icon="cloud-off">
            Lo stato mostrato è quello in cache; il servizio di provisioning non risponde.
          </Banner>
        )}
        {unmanaged && (
          <Banner tone="info" title="Dominio non gestito dal provisioner" icon="info">
            Il dominio esiste fuori dal ciclo di provisioning (es. organizzazione migrata): le operazioni sul suo ciclo di vita si fanno dalla dashboard del provisioner.
          </Banner>
        )}
        {saga && saga.length > 0 && (
          <div style={{ display: "flex", flexDirection: "column", gap: 6 }}>
            {saga.map((s) => (
              <div key={s.name} style={{ display: "flex", alignItems: "center", gap: 8, fontSize: 13, color: "var(--text-muted)" }}>
                <Icon name={s.status === "done" || s.status === "completed" ? "check-circle-2" : s.status === "failed" ? "x-circle" : "circle-dashed"} size={15}
                  color={s.status === "failed" ? "var(--danger)" : s.status === "done" || s.status === "completed" ? "var(--primary)" : "var(--text-subtle)"} />
                <span style={{ fontFamily: "var(--font-mono, monospace)", fontSize: 12 }}>{s.name}</span>
                <span style={{ color: "var(--text-subtle)" }}>{s.status}</span>
                {s.error && <span style={{ color: "var(--danger)", fontSize: 12 }}>{s.error}</span>}
              </div>
            ))}
          </div>
        )}
      </SectionCard>

      {/* --- Membri -------------------------------------------------------- */}
      <SectionCard
        title={`Membri (${view.members.length})`}
        subtitle="I nuovi membri entrano tramite invito (sezione qui sotto)."
        actions={isOwner && others.length > 0 && (
          <Button variant="secondary" size="sm" iconLeft={<Icon name="crown" size={15} />} onClick={() => setTransferTo(others[0].userId)}>Trasferisci ownership</Button>
        )}
      >
        <div style={{ display: "flex", flexDirection: "column" }}>
          {view.members.map((m) => {
            const self = me && m.userId === me.userId;
            return (
              <div key={m.userId} style={{ display: "flex", alignItems: "center", gap: 12, padding: "10px 2px", borderBottom: "1px solid var(--border-subtle)" }}>
                <Avatar name={m.displayName || m.username} tone={self ? "sky" : "sage"} />
                <span style={{ display: "flex", flexDirection: "column", lineHeight: 1.25, flex: 1, minWidth: 0 }}>
                  <span style={{ fontSize: 13.5, fontWeight: 500, color: "var(--text-strong)" }}>
                    {m.displayName || m.username} {self && <span style={{ color: "var(--text-subtle)", fontWeight: 400 }}>(tu)</span>}
                  </span>
                  <span style={{ fontSize: 12, color: "var(--text-subtle)" }}>{m.username}</span>
                </span>
                {m.role === "owner" ? (
                  <Badge tone="accent">Owner</Badge>
                ) : canAdmin ? (
                  <span style={{ width: 130 }}>
                    <Select value={m.role} options={ORG_ROLE_OPTIONS} onChange={(e) => changeRole(m, e.target.value)} />
                  </span>
                ) : (
                  <Badge tone="neutral">{ORG_ROLE_LABEL[m.role] || m.role}</Badge>
                )}
                {self && m.role !== "owner" && (
                  <IconButton label="Esci dall'organizzazione" onClick={() => setConfirm({ kind: "leave", member: m })}><Icon name="log-out" size={15} /></IconButton>
                )}
                {!self && canAdmin && m.role !== "owner" && (
                  <IconButton label="Rimuovi" onClick={() => setConfirm({ kind: "remove", member: m })}><Icon name="trash-2" size={15} /></IconButton>
                )}
              </div>
            );
          })}
        </div>
      </SectionCard>

      {/* --- Inviti (manager e superiori) ------------------------------------ */}
      {orgRoleAtLeast(myRole, "manager") && <InvitationsSection myRole={myRole} notify={notify} />}

      {/* --- Zona pericolosa (solo owner; non per domini fuori gestione) ----- */}
      {isOwner && !unmanaged && (
        <SectionCard
          title="Elimina organizzazione"
          subtitle="Il dominio viene SOSPESO (nessuna nuova connessione) e gli assistenti disattivati. Il deprovisioning vero resta un'operazione manuale."
          actions={<Button variant="danger" size="sm" disabled={status === "suspended"} onClick={() => setConfirm({ kind: "delete" })}>Elimina</Button>}
        />
      )}

      {/* --- Dialogs -------------------------------------------------------- */}
      <Dialog open={!!confirm} onClose={() => (busy ? null : setConfirm(null))}
        title={confirm && confirm.kind === "delete" ? "Elimina organizzazione" : confirm && confirm.kind === "leave" ? "Esci dall'organizzazione" : "Rimuovi membro"}
        footer={<React.Fragment>
          <Button variant="secondary" disabled={busy} onClick={() => setConfirm(null)}>Annulla</Button>
          <Button variant="danger" disabled={busy} iconLeft={busy ? <Icon name="loader" size={16} /> : undefined} onClick={confirmAction}>Conferma</Button>
        </React.Fragment>}>
        {confirm && confirm.kind === "delete" && (
          <span>L'organizzazione «<b>{organization.name}</b>» verrà eliminata: il dominio <b>{organization.domain}</b> sarà sospeso e gli assistenti disattivati.</span>
        )}
        {confirm && confirm.kind === "leave" && <span>Uscirai dall'organizzazione «<b>{organization.name}</b>». Un admin potrà invitarti di nuovo.</span>}
        {confirm && confirm.kind === "remove" && <span>«<b>{confirm.member.username}</b>» verrà rimosso dall'organizzazione.</span>}
      </Dialog>

      <Dialog open={transferTo != null} onClose={() => (busy ? null : setTransferTo(null))} title="Trasferisci ownership"
        footer={<React.Fragment>
          <Button variant="secondary" disabled={busy} onClick={() => setTransferTo(null)}>Annulla</Button>
          <Button variant="primary" disabled={busy} iconLeft={busy ? <Icon name="loader" size={16} /> : undefined} onClick={doTransfer}>Trasferisci</Button>
        </React.Fragment>}>
        <div style={{ display: "flex", flexDirection: "column", gap: 12 }}>
          <span>Il nuovo owner avrà il controllo completo; tu diventerai <b>Admin</b>.</span>
          {transferTo != null && (
            <Select label="Nuovo owner" value={transferTo}
              options={others.map((m) => ({ value: m.userId, label: `${m.displayName || m.username} (${m.username})` }))}
              onChange={(e) => setTransferTo(e.target.value)} />
          )}
        </div>
      </Dialog>

      {goOnline && React.createElement(window.GoOnlineDialog, {
        organization,
        onClose: () => setGoOnline(false),
        onDone: (org) => {
          setGoOnline(false);
          setDomainInfo({ organization: org });
          onChanged && onChanged();
          notify({ tone: "success", title: "Provisioning avviato", body: `Il dominio «${org.domain}» è in creazione.` });
        },
        notify,
      })}
    </div>
  );
}

Object.assign(window, { OrganizationPanel });
