// Organização ativa, dados da organização e painel de equipe (compartilhado entre a área do cliente e a Administração).
// Tudo lê e grava pelo banco (RLS); a tela só mostra o que a pessoa pode fazer e confirma o que o banco confirmou.
// Limite do backend hoje: administrador de cliente edita dados da organização e suspende/reativa membros; atribuir
// papéis exige roles.manage, que só a equipe Vértice tem. Convites exigem uma Edge Function com credencial de servidor
// (ainda inexistente), por isso o botão aparece como "Em breve" e não promete nada.

// Organização ativa (id, nome, tipo) e seus ambientes, vindos do contexto do servidor. Recarrega quando o contexto muda.
function useActiveOrg() {
  const [st, setSt] = React.useState({ loading: true, org: null, envs: [] });
  React.useEffect(() => {
    let alive = true;
    const load = () => window.VxAuthorization.getContext().then(ctx => {
      if (!alive) return;
      const active = ctx && ctx.active_context;
      const m = ((ctx && ctx.memberships) || []).find(x => x.organization && active && x.organization.id === active.organization_id);
      setSt({ loading: false, org: m ? { id: m.organization.id, name: m.organization.name, kind: m.organization.kind } : null, envs: m ? m.environments || [] : [] });
    }, () => alive && setSt({ loading: false, org: null, envs: [] }));
    load();
    window.addEventListener('vx-context-changed', load);
    return () => { alive = false; window.removeEventListener('vx-context-changed', load); };
  }, []);
  return st;
}

const vxDate = v => v ? new Date(v).toLocaleDateString('pt-BR') : '—';
const vxDateTime = v => v ? new Date(v).toLocaleString('pt-BR', { dateStyle: 'short', timeStyle: 'short' }) : '—';
const VX_ORG_KIND = { VERTICE: 'Vértice', CLIENT: 'Cliente', PARTNER: 'Parceiro', SERVICE_PROVIDER: 'Prestador de serviço', AUDITOR: 'Auditoria', OTHER: 'Outro' };
const VX_ORG_STATUS = { ACTIVE: 'Ativa', INVITED: 'Convidada', SUSPENDED: 'Suspensa', DISABLED: 'Desativada' };
const VX_MEMBER_STATUS = { ACTIVE: ['Ativo', 'success'], INVITED: ['Convidado', 'info'], SUSPENDED: ['Suspenso', 'warning'], REVOKED: ['Revogado', 'danger'] };

// Estado de carregamento/erro de uma leitura real.
function useRemote(fn, deps) {
  const [st, setSt] = React.useState({ loading: true, error: '', data: null });
  const [n, setN] = React.useState(0);
  React.useEffect(() => {
    let alive = true;
    setSt(s => ({ ...s, loading: true, error: '' }));
    Promise.resolve().then(fn).then(data => alive && setSt({ loading: false, error: '', data }), e => alive && setSt({ loading: false, error: (e && e.message) || 'Não foi possível carregar.', data: null }));
    return () => { alive = false; };
  }, [...(deps || []), n]);
  return [st, () => setN(x => x + 1)];
}

function OrgDetails({ org, onSaved }) {
  const { Card, Input, Badge, Button, Alert } = window.VRticeDesignSystem_d763eb;
  const { toast } = useShell();
  const [d, setD] = React.useState({ name: org.name || '', legal_name: org.legal_name || '', document: org.document || '' });
  const [busy, setBusy] = React.useState(false), [err, setErr] = React.useState('');
  const dirty = d.name !== (org.name || '') || d.legal_name !== (org.legal_name || '') || d.document !== (org.document || '');
  const save = async () => {
    setBusy(true); setErr('');
    try { const saved = await window.VxAccessAdmin.saveOrganization(window.VxAuth.db(), org.id, d); toast('Dados da organização salvos', 'ph-check-circle'); onSaved && onSaved(saved); }
    catch (e) { setErr(e.message); } finally { setBusy(false); }
  };
  return (
    <Card variant="flat" padding="28px 32px" gap={20}>
      <div style={{ display: 'flex', gap: 10, flexWrap: 'wrap', alignItems: 'center' }}>
        <Badge variant="meta" tone="info">{VX_ORG_KIND[org.kind] || org.kind}</Badge>
        <Badge variant="meta" tone={org.status === 'ACTIVE' ? 'success' : 'warning'}>{VX_ORG_STATUS[org.status] || org.status}</Badge>
        <span style={{ fontSize: 12, color: 'var(--text-muted)' }}>Tipo e situação só a plataforma altera.</span>
      </div>
      <div style={{ display: 'grid', gridTemplateColumns: 'repeat(auto-fit, minmax(260px, 1fr))', gap: 18 }}>
        <Input label="Nome" value={d.name} onChange={e => setD(s => ({ ...s, name: e.target.value }))} />
        <Input label="Razão social" value={d.legal_name} onChange={e => setD(s => ({ ...s, legal_name: e.target.value }))} />
        <Input label="CNPJ ou CPF (somente números)" mono value={d.document} onChange={e => setD(s => ({ ...s, document: e.target.value }))} />
      </div>
      {err && <Alert tone="danger" title="Não foi possível salvar">{err}</Alert>}
      <div><PBtn perm="organizations.manage" icon="ph-floppy-disk" onClick={save} disabled={busy || !dirty}>{busy ? 'Salvando…' : 'Salvar'}</PBtn></div>
    </Card>
  );
}

function EnvList({ envs }) {
  const { Card, Badge, EmptyState } = window.VRticeDesignSystem_d763eb;
  return (
    <Card variant="flat" padding="24px 32px" gap={12}>
      <h3 style={{ margin: 0, fontSize: 16, fontWeight: 600 }}>Ambientes</h3>
      {envs.length ? envs.map(e => (
        <div key={e.id} style={{ display: 'flex', gap: 12, alignItems: 'center', padding: '10px 0', borderTop: '1px solid var(--border-subtle)' }}>
          <strong style={{ fontWeight: 600 }}>{e.name}</strong>
          <span style={{ fontFamily: 'var(--font-mono)', fontSize: 12, color: 'var(--text-muted)' }}>{e.key}</span>
          <Badge variant="meta" tone="neutral">{e.kind}</Badge>
          {e.status && e.status !== 'ACTIVE' && <Badge variant="meta" tone="warning">{VX_ORG_STATUS[e.status] || e.status}</Badge>}
        </div>
      )) : <EmptyState variant="inline" icon="ph-stack" title="Nenhum ambiente ativo">Esta organização não tem ambientes ativos.</EmptyState>}
    </Card>
  );
}

// Tela do administrador do cliente (e de qualquer organização ativa): dados e ambientes da própria organização.
function OrganizationScreen() {
  const { PageHeader, Alert, Skeleton } = window.VRticeDesignSystem_d763eb;
  const active = useActiveOrg();
  const [st, reload] = useRemote(() => active.org ? window.VxAccessAdmin.loadOrganization(window.VxAuth.db(), active.org.id) : null, [active.org && active.org.id]);
  return (
    <>
      <PageHeader eyebrow="MINHA ORGANIZAÇÃO" title="Dados da organização" description="Cadastro e ambientes da organização em que você está atuando." />
      <Alert tone="info" title="O que você pode administrar aqui">Dados cadastrais e a equipe desta organização. Módulos internos da plataforma, configurações globais e dados de outras organizações não aparecem nesta área.</Alert>
      {active.loading || st.loading ? <Skeleton height={220} radius={20} />
        : !active.org ? <Alert tone="warning" title="Sem organização ativa">Não há uma organização ativa na sua sessão. Escolha uma no seletor do menu lateral.</Alert>
        : st.error ? <Alert tone="danger" title="Não foi possível carregar">{st.error}</Alert>
        : st.data && <><OrgDetails key={st.data.org.id + (st.data.org.name || '')} org={st.data.org} onSaved={reload} /><EnvList envs={st.data.environments} /></>}
    </>
  );
}

// Equipe de uma organização. Atribuição de papéis só aparece para quem tem roles.manage (o banco revalida).
function TeamPanel({ orgId, orgKind, envs }) {
  const { Card, Badge, Button, Modal, Select, Input, Alert, EmptyState, Skeleton, Tag, IconButton } = window.VRticeDesignSystem_d763eb;
  const { toast } = useShell();
  const { can } = useAccess();
  const canPlatformRoles = can('roles.manage');
  const canTenantRoles = orgKind === 'CLIENT' && can('users.manage');   // administrador do cliente: papéis de cliente abaixo do próprio nível (o banco decide)
  const canRoles = canPlatformRoles || canTenantRoles;
  const [st, reload] = useRemote(() => window.VxAccessAdmin.listMembers(window.VxAuth.db(), orgId, { withRoles: canRoles }), [orgId, canRoles]);
  const [catalog] = useRemote(() => canRoles ? window.VxAccessAdmin.listRoles(window.VxAuth.db()) : [], [canRoles]);
  const [tenantKeys] = useRemote(() => canTenantRoles ? window.VxAccessAdmin.listAssignableClientRoles(window.VxAuth.db(), orgId) : [], [orgId, canTenantRoles]);
  const tenantSet = new Set(tenantKeys.data || []);
  const [assign, setAssign] = React.useState(null), [revoke, setRevoke] = React.useState(null), [busy, setBusy] = React.useState(false), [err, setErr] = React.useState('');
  const [pick, setPick] = React.useState({ role: '', env: '' });
  const [inv, setInv] = React.useState(null);   // modal de convite: { email, name, role, env }
  const assignable = window.VxAccessAdmin.assignableRoles(catalog.data || [], orgKind).filter(r => canPlatformRoles || tenantSet.has(r.key));
  const canRevoke = r => canPlatformRoles || tenantSet.has(r.role && r.role.key);
  const chosen = assignable.find(r => r.key === pick.role);
  const envOptions = [{ value: '', label: 'Selecione…' }, ...(envs || []).map(e => ({ value: e.id, label: e.name }))];
  const run = async (fn, okMsg) => {
    setBusy(true); setErr('');
    try { await fn(); toast(okMsg, 'ph-check-circle'); setAssign(null); setRevoke(null); reload(); }
    catch (e) { setErr(e.message); } finally { setBusy(false); }
  };
  const setStatus = (m, status) => run(() => window.VxAccessAdmin.setMembershipStatus(window.VxAuth.db(), m.id, status), status === 'SUSPENDED' ? 'Membro suspenso' : 'Membro reativado');
  const doAssign = () => {
    if (!chosen) return setErr('Escolha um papel.');
    if (chosen.scope === 'ENVIRONMENT' && !pick.env) return setErr('Escolha o ambiente deste papel.');
    run(() => window.VxAccessAdmin.assignRole(window.VxAuth.db(), { membershipId: assign.id, roleId: chosen.id, environmentId: chosen.scope === 'ENVIRONMENT' ? pick.env : null }), 'Papel atribuído');
  };
  const inviteRoles = assignable.filter(r => tenantSet.has(r.key));
  const invChosen = inv && inviteRoles.find(r => r.key === inv.role);
  const doInvite = () => {
    if (!inv.email.trim()) return setErr('Informe o e-mail da pessoa.');
    if (!invChosen) return setErr('Escolha um papel.');
    if (invChosen.scope === 'ENVIRONMENT' && !inv.env) return setErr('Escolha o ambiente deste papel.');
    run(async () => { await window.VxAccessAdmin.inviteMember(window.VxAuth.db(), { organizationId: orgId, email: inv.email, roleKey: invChosen.key, environmentId: invChosen.scope === 'ENVIRONMENT' ? inv.env : null, displayName: inv.name, redirectTo: window.VxAuth && window.VxAuth.redirectTo }); setInv(null); }, 'Convite enviado: a pessoa define a senha pelo e-mail');
  };
  return (
    <Card variant="flat" padding="24px 32px" gap={16}>
      <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', gap: 12, flexWrap: 'wrap' }}>
        <h3 style={{ margin: 0, fontSize: 16, fontWeight: 600 }}>Equipe</h3>
        {canTenantRoles ? <PBtn perm="users.manage" icon="ph-user-plus" variant="secondary" onClick={() => { setErr(''); setInv({ email: '', name: '', role: '', env: '' }); }}>Convidar pessoa</PBtn>
          : <SoonBtn icon="ph-user-plus" variant="secondary">Convidar pessoa</SoonBtn>}
      </div>
      {!canRoles && <Alert tone="info" title="Papéis">Atribuir ou revogar papéis é feito pelo administrador da organização ou pela equipe Vértice. Aqui você acompanha os membros.</Alert>}
      {canTenantRoles && !canPlatformRoles && <Alert tone="info" title="Seu nível">Você atribui e revoga apenas papéis abaixo do seu nível. O sistema recusa o resto.</Alert>}
      {st.loading ? <Skeleton height={120} radius={16} />
        : st.error ? <Alert tone="danger" title="Não foi possível carregar a equipe">{st.error}</Alert>
        : !st.data.length ? <EmptyState variant="inline" icon="ph-users" title="Nenhum membro visível">Você não tem acesso à lista de membros desta organização ou ela está vazia.</EmptyState>
        : st.data.map(m => {
          const [label, tone] = VX_MEMBER_STATUS[m.status] || [m.status, 'neutral'];
          return (
            <div key={m.id} style={{ display: 'flex', flexDirection: 'column', gap: 10, padding: '14px 0', borderTop: '1px solid var(--border-subtle)' }}>
              <div style={{ display: 'flex', gap: 12, alignItems: 'center', flexWrap: 'wrap' }}>
                <strong style={{ fontWeight: 600, overflowWrap: 'anywhere' }}>{m.name}</strong>
                {m.job_title && <span style={{ fontSize: 13, color: 'var(--text-muted)' }}>{m.job_title}</span>}
                <Badge variant="meta" tone={tone}>{label}</Badge>
                <span style={{ fontSize: 12, color: 'var(--text-subtle)' }}>desde {vxDate(m.created_at)}</span>
                <span style={{ marginLeft: 'auto', display: 'flex', gap: 8 }}>
                  {canRoles && assignable.length > 0 && <PBtn perm={canPlatformRoles ? 'roles.manage' : 'users.manage'} size="sm" variant="secondary" icon="ph-key" onClick={() => { setErr(''); setPick({ role: '', env: '' }); setAssign(m); }}>Atribuir papel</PBtn>}
                  {m.status === 'ACTIVE' && <PBtn perm="users.manage" size="sm" variant="danger" onClick={() => setStatus(m, 'SUSPENDED')} disabled={busy}>Suspender</PBtn>}
                  {m.status === 'SUSPENDED' && <PBtn perm="users.manage" size="sm" variant="secondary" onClick={() => setStatus(m, 'ACTIVE')} disabled={busy}>Reativar</PBtn>}
                </span>
              </div>
              {canRoles && <div style={{ display: 'flex', gap: 8, flexWrap: 'wrap' }}>
                {m.roles.length ? m.roles.map(r => <span key={r.id} style={{ display: 'inline-flex', alignItems: 'center', gap: 2 }}><Tag>{(r.role && r.role.name) || (r.role && r.role.key)}</Tag>{canRevoke(r) && <IconButton size="sm" icon="ph-x" label={'Revogar ' + ((r.role && r.role.name) || (r.role && r.role.key))} onClick={() => { setErr(''); setRevoke({ m, r }); }} />}</span>) : <span style={{ fontSize: 13, color: 'var(--text-muted)' }}>Sem papel: nenhum acesso concedido.</span>}
              </div>}
            </div>
          );
        })}
      {err && !assign && !revoke && !inv && <Alert tone="danger" title="Não foi possível concluir">{err}</Alert>}
      {assign && <Modal kicker="Equipe" title={'Atribuir papel a ' + assign.name} onClose={() => setAssign(null)} footer={<><Button block onClick={doAssign} disabled={busy}>{busy ? 'Atribuindo…' : 'Atribuir'}</Button><Button variant="ghost" onClick={() => setAssign(null)}>Cancelar</Button></>}>
        <div style={{ display: 'flex', flexDirection: 'column', gap: 16 }}>
          <Select label="Papel" options={[{ value: '', label: 'Selecione…' }, ...assignable.map(r => ({ value: r.key, label: r.name || r.key }))]} value={pick.role} onChange={e => setPick(s => ({ ...s, role: e.target.value }))} />
          {chosen && chosen.description && <span style={{ fontSize: 13, color: 'var(--text-muted)' }}>{chosen.description}</span>}
          {chosen && chosen.scope === 'ENVIRONMENT' && <Select label="Ambiente" options={envOptions} value={pick.env} onChange={e => setPick(s => ({ ...s, env: e.target.value }))} />}
          {err && <Alert tone="danger" title="Não foi possível atribuir">{err}</Alert>}
        </div>
      </Modal>}
      {inv && <Modal kicker="Equipe" title="Convidar pessoa" onClose={() => setInv(null)} footer={<><Button block onClick={doInvite} disabled={busy}>{busy ? 'Enviando…' : 'Enviar convite'}</Button><Button variant="ghost" onClick={() => setInv(null)}>Cancelar</Button></>}>
        <div style={{ display: 'flex', flexDirection: 'column', gap: 16 }}>
          <Input label="E-mail" value={inv.email} onChange={e => setInv(s => ({ ...s, email: e.target.value }))} />
          <Input label="Nome (opcional)" value={inv.name} onChange={e => setInv(s => ({ ...s, name: e.target.value }))} />
          <Select label="Papel" options={[{ value: '', label: 'Selecione…' }, ...inviteRoles.map(r => ({ value: r.key, label: r.name || r.key }))]} value={inv.role} onChange={e => setInv(s => ({ ...s, role: e.target.value }))} />
          {invChosen && invChosen.scope === 'ENVIRONMENT' && <Select label="Ambiente" options={envOptions} value={inv.env} onChange={e => setInv(s => ({ ...s, env: e.target.value }))} />}
          <span style={{ fontSize: 13, color: 'var(--text-muted)' }}>A pessoa recebe um e-mail para definir a própria senha. Você não vê nem recebe a senha. Só aparecem os papéis abaixo do seu nível.</span>
          {err && <Alert tone="danger" title="Não foi possível convidar">{err}</Alert>}
        </div>
      </Modal>}
      {revoke && <Modal kicker="Equipe" title="Revogar papel" onClose={() => setRevoke(null)} footer={<><Button variant="danger" block onClick={() => run(() => window.VxAccessAdmin.revokeRole(window.VxAuth.db(), revoke.r.id), 'Papel revogado')} disabled={busy}>{busy ? 'Revogando…' : 'Revogar'}</Button><Button variant="ghost" onClick={() => setRevoke(null)}>Cancelar</Button></>}>
        <div style={{ display: 'flex', flexDirection: 'column', gap: 12 }}>
          <span>Revogar <strong>{(revoke.r.role && revoke.r.role.name) || (revoke.r.role && revoke.r.role.key)}</strong> de <strong>{revoke.m.name}</strong>? A pessoa perde, na hora, todo acesso que esse papel concedia.</span>
          {err && <Alert tone="danger" title="Não foi possível revogar">{err}</Alert>}
        </div>
      </Modal>}
    </Card>
  );
}

// Equipe da organização ativa (área do cliente).
function TeamScreen() {
  const { PageHeader, Alert, Skeleton } = window.VRticeDesignSystem_d763eb;
  const active = useActiveOrg();
  return (
    <>
      <PageHeader eyebrow="MINHA ORGANIZAÇÃO" title="Equipe" description="Pessoas com acesso à sua organização e a situação de cada uma." />
      {active.loading ? <Skeleton height={180} radius={20} />
        : !active.org ? <Alert tone="warning" title="Sem organização ativa">Escolha uma organização no seletor do menu lateral.</Alert>
        : <TeamPanel orgId={active.org.id} orgKind={active.org.kind} envs={active.envs} />}
    </>
  );
}

Object.assign(window, { useActiveOrg, useRemote, vxDate, vxDateTime, VX_ORG_KIND, VX_ORG_STATUS, OrgDetails, EnvList, TeamPanel, OrganizationScreen, TeamScreen });
