/**
 * Base de dados — o que alimenta a lista: todos os itens (também os fechados),
 * clientes, equipamentos, cabines, pessoas e as listas de valores. Veio do Excel da Ana
 * (scripts/importar-excel.js) e o Bruno completa e corrige aqui.
 *
 * Todos consultam; só o Bruno (perfil admin) cria, edita e apaga.
 * Clientes e equipamentos editam-se num modal (dois ou três campos); pessoas
 * numa página (mais campos) — docs/padroes-interface.md do NetScreen AI.
 */

const SECCOES_BASE = [
  { chave: 'itens', rotulo: 'Itens' },
  { chave: 'clientes', rotulo: 'Clientes' },
  { chave: 'equipamentos', rotulo: 'Equipamentos' },
  { chave: 'cabines', rotulo: 'Cabines' },
  { chave: 'pessoas', rotulo: 'Pessoas' },
  { chave: 'listas', rotulo: 'Listas' },
];
const LIMITE_LINHAS = 100;

/**
 * Tabela simples da base. Com `selecionados` (um Set de chaves), ganha uma
 * coluna de caixas para escolher linhas — é assim que se juntam repetidos.
 */
function TabelaBase({ colunas, linhas, aoAbrir, vazio, selecionados, chaveLinha, aoSelecionar }) {
  const comSelecao = !!selecionados;
  return (
    <div className="relative overflow-x-auto border bg-card">
      <table className="w-full text-left text-sm">
        <thead>
          <tr className="border-b border-border text-xs text-muted-foreground">
            {comSelecao && <th scope="col" className="w-10 px-4 py-2.5"><span className="sr-only">Escolher</span></th>}
            {colunas.map((c) => <th key={c.rotulo} scope="col" className={`whitespace-nowrap px-4 py-2.5 font-medium ${c.classe || ''}`}>{c.rotulo}</th>)}
          </tr>
        </thead>
        <tbody className="divide-y divide-[var(--border)]">
          {linhas.length === 0 && (
            <tr><td colSpan={colunas.length + (comSelecao ? 1 : 0)} className="px-4 py-6 text-muted-foreground">{vazio}</td></tr>
          )}
          {linhas.map((l, i) => {
            const chave = comSelecao ? chaveLinha(l) : i;
            const marcado = comSelecao && selecionados.has(chave);
            return (
              <tr
                key={chave}
                className={`${aoAbrir ? 'linha-item cursor-pointer' : ''} ${marcado ? 'bg-secondary/60' : ''}`}
                onClick={aoAbrir ? () => aoAbrir(l) : undefined}
                onKeyDown={aoAbrir ? (e) => { if (e.key === 'Enter') aoAbrir(l); } : undefined}
                tabIndex={aoAbrir ? 0 : undefined}
              >
                {comSelecao && (
                  <td className="px-4 py-2.5" onClick={(e) => e.stopPropagation()}>
                    <input type="checkbox" checked={marcado} onChange={() => aoSelecionar(chave)} aria-label="Escolher para juntar" />
                  </td>
                )}
                {colunas.map((c) => <td key={c.rotulo} className={`px-4 py-2.5 ${c.classe || ''}`}>{c.valor(l)}</td>)}
              </tr>
            );
          })}
        </tbody>
      </table>
    </div>
  );
}

/** Um Set em estado React, com alternar e limpar. */
function useSelecao() {
  const [sel, setSel] = React.useState(() => new Set());
  const alternar = (k) => setSel((s) => { const n = new Set(s); if (n.has(k)) n.delete(k); else n.add(k); return n; });
  const limpar = () => setSel(new Set());
  return [sel, alternar, limpar];
}

function BarraFiltro({ procura, setProcura, rotulo, children }) {
  return (
    <div className="mb-4 flex flex-wrap items-center gap-3">
      <label className="relative min-w-0 flex-1 sm:max-w-xs">
        <span className="sr-only">{rotulo}</span>
        <IconProcurar size={16} className="pointer-events-none absolute left-3 top-1/2 -translate-y-1/2 text-muted-foreground" />
        <input type="search" className="campo !pl-9" placeholder={rotulo} value={procura} onChange={(e) => setProcura(e.target.value)} />
      </label>
      {children}
    </div>
  );
}

const normalizar = (s) => String(s || '').toLowerCase().normalize('NFD').replace(/[̀-ͯ]/g, '');

// Chaves para encontrar repetidos. Conservadoras de propósito: só juntam o que
// difere em acentos, pontuação, "Lda"/"Unipessoal"/"Farmácia", ou "×"/"mm".
// Variantes como "Auchan Alfragide" e "Auchan Almada" podem ser lojas
// diferentes — essas juntam-se à mão.
const chaveCliente = (c) => `${c.numero == null ? '' : c.numero}|${c.nome}`;
const chaveRepetidoCliente = (nome) => normalizar(nome)
  .replace(/[^a-z0-9 ]/g, ' ')
  .replace(/\b(lda|ltda|unipessoal|unip|sa|farmacia|farm)\b/g, ' ')
  .replace(/\s+/g, ' ')
  .trim();
const chaveRepetidoEquipamento = (d) => normalizar(d).replace(/×/g, 'x').replace(/mm/g, '').replace(/[^a-z0-9]/g, '');

function gruposRepetidos(lista, chave) {
  const g = {};
  lista.forEach((x) => { const k = chave(x); if (k) (g[k] = g[k] || []).push(x); });
  return Object.values(g).filter((v) => v.length > 1);
}

function ModalJuntarClientes({ clientes, onFechar }) {
  const { dados, acoes } = useLista();
  const usos = (c) => dados.itens.filter((i) => mesmoNome(i.cliente, c.nome)).length;
  const nomes = Array.from(new Set(clientes.map((c) => c.nome)));
  const numeros = Array.from(new Set(clientes.map((c) => c.numero).filter((n) => n != null)));
  // Por omissão fica o nome do que tem número (é o do sistema de faturação) e, entre esses, o mais usado
  const preferido = clientes.slice().sort((a, b) => (b.numero != null) - (a.numero != null) || usos(b) - usos(a))[0];
  const [nome, setNome] = React.useState(preferido.nome);
  const [numero, setNumero] = React.useState(numeros.length ? String(preferido.numero ?? numeros[0]) : '');
  const afetados = dados.itens.filter((i) => clientes.some((c) => mesmoNome(c.nome, i.cliente))).length;

  async function juntar() {
    if (await acoes.juntarClientes(clientes, { nome: nome.trim(), numero: numero === '' ? null : Number(numero) })) onFechar();
  }

  return (
    <Modal
      aberto
      onFechar={onFechar}
      titulo={`Juntar ${clientes.length} clientes`}
      acoes={
        <>
          <button type="button" className={BOTAO_SECUNDARIO} onClick={onFechar} data-foco-inicial>Cancelar</button>
          <button type="button" className={BOTAO_PRIMARIO} onClick={juntar} disabled={!nome.trim()}>Juntar num só</button>
        </>
      }
    >
      <fieldset>
        <legend className="mb-2 text-foreground">Nome que fica</legend>
        <div className="space-y-1.5">
          {nomes.map((n) => (
            <label key={n} className="flex items-center gap-2.5">
              <input type="radio" name="nome-juntar" checked={nome === n} onChange={() => setNome(n)} />
              <span className="text-foreground">{n}</span>
            </label>
          ))}
        </div>
        <input className="campo mt-2" value={nome} onChange={(e) => setNome(e.target.value)} aria-label="Ou escreve outro nome" />
      </fieldset>
      <fieldset className="mt-4">
        <legend className="mb-2 text-foreground">Nº de cliente que fica</legend>
        <div className="flex flex-wrap gap-x-5 gap-y-1.5">
          {numeros.map((n) => (
            <label key={n} className="flex items-center gap-2.5">
              <input type="radio" name="numero-juntar" checked={numero === String(n)} onChange={() => setNumero(String(n))} />
              <span className="tabular-nums text-foreground">{n}</span>
            </label>
          ))}
          <label className="flex items-center gap-2.5">
            <input type="radio" name="numero-juntar" checked={numero === ''} onChange={() => setNumero('')} /> Sem número
          </label>
        </div>
        {numeros.length > 1 && (
          <p className="mt-2 text-accent">Têm números diferentes ({numeros.join(', ')}). Confirma qual é o do cliente antes de juntar.</p>
        )}
      </fieldset>
      <p className="mt-4">
        {afetados ? `${plural(afetados, 'item passa', 'itens passam')} a apontar para este cliente e fica registado no histórico deles.` : 'Nenhum item usa estes clientes.'}
      </p>
    </Modal>
  );
}

function ModalJuntarEquipamentos({ equipamentos, onFechar }) {
  const { dados, acoes } = useLista();
  const [descricao, setDescricao] = React.useState(equipamentos[0].descricao);
  const artigos = Array.from(new Set(equipamentos.map((e) => e.artigo).filter(Boolean)));
  const [artigo, setArtigo] = React.useState(artigos[0] || '');
  const chaves = new Set(equipamentos.map((e) => normalizar(e.descricao)));
  const afetados = dados.itens.filter((i) => i.equipamentos.some((q) => chaves.has(normalizar(q.descricao)))).length;

  async function juntar() {
    if (await acoes.juntarEquipamentos(equipamentos, { descricao: descricao.trim(), artigo: artigo.trim() || null })) onFechar();
  }

  return (
    <Modal
      aberto
      onFechar={onFechar}
      titulo={`Juntar ${equipamentos.length} equipamentos`}
      acoes={
        <>
          <button type="button" className={BOTAO_SECUNDARIO} onClick={onFechar} data-foco-inicial>Cancelar</button>
          <button type="button" className={BOTAO_PRIMARIO} onClick={juntar} disabled={!descricao.trim()}>Juntar num só</button>
        </>
      }
    >
      <fieldset>
        <legend className="mb-2 text-foreground">Descrição que fica</legend>
        <div className="space-y-1.5">
          {equipamentos.map((e) => (
            <label key={e.descricao} className="flex items-center gap-2.5">
              <input type="radio" name="desc-juntar" checked={descricao === e.descricao} onChange={() => setDescricao(e.descricao)} />
              <span className="text-foreground">{e.descricao}</span>
            </label>
          ))}
        </div>
        <input className="campo mt-2" value={descricao} onChange={(e) => setDescricao(e.target.value)} aria-label="Ou escreve outra descrição" />
      </fieldset>
      <CampoFormulario rotulo="Código de artigo" ajuda="(opcional)" className="mt-4 block">
        <input className="campo tabular-nums" value={artigo} onChange={(e) => setArtigo(e.target.value)} />
      </CampoFormulario>
      <p className="mt-4">
        {afetados ? `A descrição muda também em ${plural(afetados, 'item', 'itens')}, com registo no histórico.` : 'Nenhum item usa estas descrições.'}
      </p>
    </Modal>
  );
}

/** A barra que aparece quando há linhas escolhidas. */
function BarraJuntar({ n, nome, onJuntar, onLimpar }) {
  if (n === 0) return null;
  return (
    <div className="sticky top-28 z-10 mb-3 flex flex-wrap items-center gap-3 rounded-lg bg-secondary px-4 py-2.5 text-sm">
      <span>{plural(n, `${nome} escolhido`, `${nome}s escolhidos`)}</span>
      <button type="button" className={`${BOTAO_PRIMARIO} ml-auto`} onClick={onJuntar} disabled={n < 2}>Juntar {n > 1 ? n : ''}</button>
      <button type="button" className={BOTAO_DISCRETO} onClick={onLimpar}>Limpar escolha</button>
    </div>
  );
}

/** Os grupos de possíveis repetidos, cada um com o seu botão. */
function ListaRepetidos({ grupos, descrever, onJuntar, vazio }) {
  if (!grupos.length) return <p className="border bg-card px-5 py-6 text-sm text-muted-foreground">{vazio}</p>;
  return (
    <ul className="space-y-2">
      {grupos.map((g, i) => (
        <li key={i} className="flex flex-wrap items-center gap-3 border bg-card px-4 py-3 text-sm">
          <div className="min-w-0 flex-1 space-y-0.5">
            {g.map((x, j) => <p key={j} className="truncate">{descrever(x)}</p>)}
          </div>
          <button type="button" className={BOTAO_SECUNDARIO} onClick={() => onJuntar(g)}>Juntar</button>
        </li>
      ))}
    </ul>
  );
}

// ─── Itens ─────────────────────────────────────────────────────────────────

const FILTROS_ITENS = [
  { chave: 'abertos', rotulo: 'Em aberto', teste: (a) => a.aberto },
  { chave: 'validar', rotulo: 'Por validar', teste: (a) => a.porValidar && a.aberto },
  { chave: 'concluidos', rotulo: 'Concluídos', teste: (a) => a.concluido },
  { chave: 'perdidos', rotulo: 'Perdidos', teste: (a) => a.perdido },
  { chave: 'todos', rotulo: 'Todos', teste: () => true },
];

function BaseItens() {
  const { itens } = useLista();
  const [filtro, setFiltro] = React.useState('abertos');
  const [limite, setLimite] = React.useState(40);
  const f = FILTROS_ITENS.find((x) => x.chave === filtro);
  const lista = itens.filter(f.teste).sort((a, b) => b.numero - a.numero);
  return (
    <>
      <div className="mb-4 flex flex-wrap gap-2" role="group" aria-label="Filtrar itens">
        {FILTROS_ITENS.map((x) => (
          <button
            key={x.chave}
            type="button"
            aria-pressed={filtro === x.chave}
            onClick={() => { setFiltro(x.chave); setLimite(40); }}
            className={`rounded-md px-3 py-1.5 text-sm ${filtro === x.chave ? 'bg-secondary text-foreground' : 'text-muted-foreground hover:text-foreground'}`}
          >
            {x.rotulo} <span className="tabular-nums text-muted-foreground">{itens.filter(x.teste).length}</span>
          </button>
        ))}
      </div>
      <ListaItens itens={lista.slice(0, limite)} vazio="Nenhum item neste filtro." />
      {lista.length > limite && (
        <button type="button" className={`${BOTAO_SECUNDARIO} mt-4`} onClick={() => setLimite((l) => l + 60)}>
          Mostrar mais ({lista.length - limite} por mostrar)
        </button>
      )}
    </>
  );
}

// ─── Clientes ──────────────────────────────────────────────────────────────

function ModalCliente({ cliente, onFechar }) {
  const { dados, acoes } = useLista();
  const [numero, setNumero] = React.useState(cliente && cliente.numero != null ? String(cliente.numero) : '');
  const [nome, setNome] = React.useState(cliente ? cliente.nome : '');
  const [erro, setErro] = React.useState('');
  const emUso = cliente ? dados.itens.filter((i) => mesmoNome(i.cliente, cliente.nome)).length : 0;

  async function guardar() {
    if (!nome.trim()) { setErro('Indica o nome do cliente.'); return; }
    const n = numero.trim() === '' ? null : Number(numero);
    if (numero.trim() !== '' && !Number.isInteger(n)) { setErro('O nº de cliente é um número inteiro.'); return; }
    const repetido = dados.clientes.find((c) => c !== cliente && n != null && c.numero === n);
    if (repetido) { setErro(`O nº ${n} já é do cliente ${repetido.nome}.`); return; }
    if (await acoes.guardarCliente(cliente, { numero: n, nome: nome.trim() })) onFechar();
  }

  return (
    <Modal
      aberto
      onFechar={onFechar}
      titulo={cliente ? 'Editar cliente' : 'Novo cliente'}
      acoes={
        <>
          {cliente && emUso === 0 && (
            <button type="button" className={`${BOTAO_DISCRETO} mr-auto`} onClick={async () => { if (await acoes.apagarCliente(cliente)) onFechar(); }}>Apagar</button>
          )}
          <button type="button" className={BOTAO_SECUNDARIO} onClick={onFechar}>Cancelar</button>
          <button type="button" className={BOTAO_PRIMARIO} onClick={guardar}>Guardar</button>
        </>
      }
    >
      <div className="grid gap-3 sm:grid-cols-[120px_1fr]">
        <CampoFormulario rotulo="Nº cliente">
          <input className="campo tabular-nums" inputMode="numeric" value={numero} onChange={(e) => setNumero(e.target.value)} data-foco-inicial />
        </CampoFormulario>
        <CampoFormulario rotulo="Nome">
          <input className="campo" value={nome} onChange={(e) => setNome(e.target.value)} />
        </CampoFormulario>
      </div>
      {cliente && emUso > 0 && <p className="mt-3">Usado em {plural(emUso, 'item', 'itens')}: mudar o nome muda-o também nesses itens.</p>}
      {erro && <p role="alert" className="mt-3 text-[hsl(var(--offline))]">{erro}</p>}
    </Modal>
  );
}

function BaseClientes({ admin }) {
  const { dados } = useLista();
  const [procura, setProcura] = React.useState('');
  const [limite, setLimite] = React.useState(LIMITE_LINHAS);
  const [aEditar, setAEditar] = React.useState(undefined); // undefined = fechado, null = novo
  const [aJuntar, setAJuntar] = React.useState(null);      // lista de clientes a juntar
  const [soRepetidos, setSoRepetidos] = React.useState(false);
  const [selecao, alternar, limparSelecao] = useSelecao();
  const contagem = React.useMemo(() => {
    const m = {};
    dados.itens.forEach((i) => { const k = chaveNome(i.cliente); m[k] = (m[k] || 0) + 1; });
    return m;
  }, [dados.itens]);
  const repetidos = React.useMemo(() => gruposRepetidos(dados.clientes, (c) => chaveRepetidoCliente(c.nome)), [dados.clientes]);
  const q = normalizar(procura);
  const lista = dados.clientes.filter((c) => !q || normalizar(c.nome).includes(q) || String(c.numero || '').includes(q));
  const escolhidos = dados.clientes.filter((c) => selecao.has(chaveCliente(c)));
  const descrever = (c) => (
    <>
      <span className="tabular-nums text-muted-foreground">{c.numero != null ? `nº ${c.numero}` : 'sem nº'}</span> — {c.nome}
      <span className="text-muted-foreground"> ({plural(contagem[chaveNome(c.nome)] || 0, 'item', 'itens')})</span>
    </>
  );

  return (
    <>
      <BarraFiltro procura={procura} setProcura={setProcura} rotulo="Procurar cliente ou nº">
        <span className="text-sm text-muted-foreground">{plural(lista.length, 'cliente', 'clientes')}</span>
        {admin && (
          <button type="button" aria-pressed={soRepetidos} className={soRepetidos ? BOTAO_PRIMARIO : BOTAO_SECUNDARIO} onClick={() => setSoRepetidos((v) => !v)}>
            Possíveis repetidos <span className="tabular-nums">{repetidos.length}</span>
          </button>
        )}
        {admin && <button type="button" className={`${BOTAO_PRIMARIO} ml-auto`} onClick={() => setAEditar(null)}><IconMais size={14} /> Novo cliente</button>}
      </BarraFiltro>

      {soRepetidos ? (
        <>
          <p className="mb-3 text-xs text-muted-foreground">
            Nomes que só diferem em acentos, pontuação ou "Lda", "Unipessoal", "Farmácia" — quase sempre o mesmo cliente, um com nº e outro sem.
            Variantes como "Auchan Alfragide" e "Auchan Almada" podem ser lojas diferentes: essas escolhem-se na lista, com as caixas.
          </p>
          <ListaRepetidos grupos={repetidos} descrever={descrever} onJuntar={setAJuntar} vazio="Não há repetidos óbvios." />
        </>
      ) : (
        <>
          <p className="mb-3 text-xs text-muted-foreground">
            Importados dos itens e das assistências do Excel. {admin ? 'Para juntar clientes repetidos, escolhe-os com as caixas.' : ''}
          </p>
          {admin && <BarraJuntar n={escolhidos.length} nome="cliente" onJuntar={() => setAJuntar(escolhidos)} onLimpar={limparSelecao} />}
          <TabelaBase
            colunas={[
              { rotulo: 'Nº', valor: (c) => (c.numero != null ? c.numero : <span className="text-muted-foreground">—</span>), classe: 'w-20 tabular-nums' },
              { rotulo: 'Nome', valor: (c) => c.nome },
              { rotulo: 'Itens', valor: (c) => contagem[chaveNome(c.nome)] || <span className="text-muted-foreground">0</span>, classe: 'w-20 text-right tabular-nums' },
            ]}
            linhas={lista.slice(0, limite)}
            aoAbrir={admin ? (c) => setAEditar(c) : null}
            vazio="Nenhum cliente com esse nome."
            selecionados={admin ? selecao : null}
            chaveLinha={chaveCliente}
            aoSelecionar={alternar}
          />
          {lista.length > limite && (
            <button type="button" className={`${BOTAO_SECUNDARIO} mt-4`} onClick={() => setLimite((l) => l + LIMITE_LINHAS)}>
              Mostrar mais ({lista.length - limite} por mostrar)
            </button>
          )}
        </>
      )}
      {aEditar !== undefined && <ModalCliente cliente={aEditar} onFechar={() => setAEditar(undefined)} />}
      {aJuntar && <ModalJuntarClientes clientes={aJuntar} onFechar={() => { setAJuntar(null); limparSelecao(); }} />}
    </>
  );
}

// ─── Equipamentos ──────────────────────────────────────────────────────────

function ModalEquipamento({ equipamento, onFechar }) {
  const { acoes } = useLista();
  const [descricao, setDescricao] = React.useState(equipamento ? equipamento.descricao : '');
  const [artigo, setArtigo] = React.useState(equipamento && equipamento.artigo ? equipamento.artigo : '');
  const [cabine, setCabine] = React.useState(equipamento && equipamento.cabine ? equipamento.cabine : '');
  const [erro, setErro] = React.useState('');

  async function guardar() {
    if (!descricao.trim()) { setErro('Descreve o equipamento.'); return; }
    const novo = { descricao: descricao.trim(), artigo: artigo.trim() || null, cabine: medidaCabine(cabine) || cabine.trim() || null };
    if (await acoes.guardarEquipamento(equipamento, novo)) onFechar();
  }

  return (
    <Modal
      aberto
      onFechar={onFechar}
      titulo={equipamento ? 'Editar equipamento' : 'Novo equipamento'}
      acoes={
        <>
          {equipamento && (
            <button type="button" className={`${BOTAO_DISCRETO} mr-auto`} onClick={async () => { if (await acoes.apagarEquipamento(equipamento)) onFechar(); }}>Apagar</button>
          )}
          <button type="button" className={BOTAO_SECUNDARIO} onClick={onFechar}>Cancelar</button>
          <button type="button" className={BOTAO_PRIMARIO} onClick={guardar}>Guardar</button>
        </>
      }
    >
      <CampoFormulario rotulo="Descrição">
        <input className="campo" value={descricao} onChange={(e) => setDescricao(e.target.value)} placeholder="Led Billboard 3.840 × 2.880mm PH6.67 HB" data-foco-inicial />
      </CampoFormulario>
      <CampoFormulario rotulo="Código de artigo" ajuda="(opcional)" className="mt-3 block">
        <input className="campo tabular-nums" value={artigo} onChange={(e) => setArtigo(e.target.value)} placeholder="110Z9130.03.02.00" />
      </CampoFormulario>
      <CampoFormulario rotulo="Cabine habitual" ajuda="(opcional: vem preenchida ao escolher este equipamento num item)" className="mt-3 block">
        <input className="campo" list="lista-cabines-base" value={cabine} onChange={(e) => setCabine(e.target.value)} placeholder="960 × 960 mm" />
      </CampoFormulario>
      <p className="mt-3">Os itens guardam a sua própria descrição: apagar ou mudar aqui não altera itens que já existem.</p>
      {erro && <p role="alert" className="mt-3 text-[hsl(var(--offline))]">{erro}</p>}
    </Modal>
  );
}

function BaseEquipamentos({ admin }) {
  const { dados } = useLista();
  const [procura, setProcura] = React.useState('');
  const [aEditar, setAEditar] = React.useState(undefined);
  const [aJuntar, setAJuntar] = React.useState(null);
  const [soRepetidos, setSoRepetidos] = React.useState(false);
  const [selecao, alternar, limparSelecao] = useSelecao();
  const repetidos = React.useMemo(() => gruposRepetidos(dados.equipamentos, (e) => chaveRepetidoEquipamento(e.descricao)), [dados.equipamentos]);
  const usos = React.useMemo(() => {
    const m = {};
    dados.itens.forEach((i) => i.equipamentos.forEach((q) => { const k = normalizar(q.descricao); m[k] = (m[k] || 0) + 1; }));
    return m;
  }, [dados.itens]);
  const q = normalizar(procura);
  const lista = dados.equipamentos
    .map((e) => Object.assign({}, e, { itens: usos[normalizar(e.descricao)] || 0 }))
    .filter((e) => !q || normalizar(e.descricao).includes(q) || normalizar(e.artigo).includes(q));
  return (
    <>
      <BarraFiltro procura={procura} setProcura={setProcura} rotulo="Procurar equipamento ou artigo">
        <span className="text-sm text-muted-foreground">{plural(lista.length, 'equipamento', 'equipamentos')}</span>
        {admin && (
          <button type="button" aria-pressed={soRepetidos} className={soRepetidos ? BOTAO_PRIMARIO : BOTAO_SECUNDARIO} onClick={() => setSoRepetidos((v) => !v)}>
            Possíveis repetidos <span className="tabular-nums">{repetidos.length}</span>
          </button>
        )}
        {admin && <button type="button" className={`${BOTAO_PRIMARIO} ml-auto`} onClick={() => setAEditar(null)}><IconMais size={14} /> Novo equipamento</button>}
      </BarraFiltro>
      {soRepetidos ? (
        <>
          <p className="mb-3 text-xs text-muted-foreground">Descrições iguais a menos de maiúsculas, "×"/"x", "mm" e pontuação.</p>
          <ListaRepetidos
            grupos={repetidos}
            descrever={(e) => <>{e.descricao}{e.artigo ? <span className="text-muted-foreground"> — artigo {e.artigo}</span> : ''}</>}
            onJuntar={setAJuntar}
            vazio="Não há repetidos óbvios."
          />
        </>
      ) : (
        <>
          <p className="mb-3 text-xs text-muted-foreground">
            Cada descrição distinta que aparece nos itens do Excel e da lista. No Excel o equipamento está em texto livre: há descrições a juntar e algumas que não são equipamento.
          </p>
          {admin && <BarraJuntar n={selecao.size} nome="equipamento" onJuntar={() => setAJuntar(dados.equipamentos.filter((e) => selecao.has(e.descricao)))} onLimpar={limparSelecao} />}
          <TabelaBase
            colunas={[
              { rotulo: 'Descrição', valor: (e) => e.descricao },
              { rotulo: 'Artigo', valor: (e) => e.artigo || <span className="text-muted-foreground">—</span>, classe: 'tabular-nums' },
              { rotulo: 'Cabine habitual', valor: (e) => e.cabine || <span className="text-muted-foreground">—</span>, classe: 'tabular-nums' },
              { rotulo: 'Itens', valor: (e) => e.itens || 0, classe: 'w-20 text-right tabular-nums' },
            ]}
            linhas={lista}
            aoAbrir={admin ? (e) => setAEditar(dados.equipamentos.find((x) => x.descricao === e.descricao)) : null}
            vazio="Nenhum equipamento com essa descrição."
            selecionados={admin ? selecao : null}
            chaveLinha={(e) => e.descricao}
            aoSelecionar={alternar}
          />
        </>
      )}
      {aEditar !== undefined && <ModalEquipamento equipamento={aEditar} onFechar={() => setAEditar(undefined)} />}
      {aJuntar && <ModalJuntarEquipamentos equipamentos={aJuntar} onFechar={() => { setAJuntar(null); limparSelecao(); }} />}
    </>
  );
}

// ─── Cabines ───────────────────────────────────────────────────────────────

function ModalCabine({ cabine, onFechar }) {
  const { acoes } = useLista();
  const [descricao, setDescricao] = React.useState(cabine ? cabine.descricao : '');
  const medida = medidaCabine(descricao);

  async function guardar() {
    if (!descricao.trim()) return;
    if (await acoes.guardarCabine(cabine, { descricao: descricao.trim() })) onFechar();
  }

  return (
    <Modal
      aberto
      onFechar={onFechar}
      titulo={cabine ? 'Editar cabine' : 'Nova cabine'}
      acoes={
        <>
          {cabine && (
            <button type="button" className={`${BOTAO_DISCRETO} mr-auto`} onClick={async () => { if (await acoes.apagarCabine(cabine)) onFechar(); }}>Apagar</button>
          )}
          <button type="button" className={BOTAO_SECUNDARIO} onClick={onFechar}>Cancelar</button>
          <button type="button" className={BOTAO_PRIMARIO} onClick={guardar} disabled={!descricao.trim()}>Guardar</button>
        </>
      }
    >
      <CampoFormulario rotulo="Medida" ajuda="(largura × altura; PH opcional)">
        <input className="campo" value={descricao} onChange={(e) => setDescricao(e.target.value)} placeholder="960 × 960 mm" data-foco-inicial />
      </CampoFormulario>
      {medida && medida !== descricao.trim() && <p className="mt-2">Fica escrita assim: <span className="text-foreground">{medida}</span></p>}
      <p className="mt-3">É a lista que aparece ao escolher a cabine num item. Os itens guardam o seu próprio texto: mudar ou apagar aqui não os altera.</p>
    </Modal>
  );
}

function BaseCabines({ admin }) {
  const { dados } = useLista();
  const [aEditar, setAEditar] = React.useState(undefined);
  const usos = React.useMemo(() => {
    const m = {};
    dados.itens.forEach((i) => i.equipamentos.forEach((q) => { const k = medidaCabine(q.cabines); if (k) m[k] = (m[k] || 0) + 1; }));
    return m;
  }, [dados.itens]);
  const habituais = React.useMemo(() => {
    const m = {};
    dados.equipamentos.forEach((e) => { const k = medidaCabine(e.cabine); if (k) m[k] = (m[k] || 0) + 1; });
    return m;
  }, [dados.equipamentos]);
  const lista = dados.cabines.map((c) => {
    const k = medidaCabine(c.descricao) || c.descricao;
    return Object.assign({}, c, { itens: usos[k] || 0, equipamentos: habituais[k] || 0 });
  });
  return (
    <>
      <div className="mb-4 flex flex-wrap items-center gap-3">
        <span className="text-sm text-muted-foreground">
          As medidas de cabine para escolher em cada equipamento de um item. Escritas sempre da mesma forma (960 × 960 mm).
        </span>
        {admin && <button type="button" className={`${BOTAO_PRIMARIO} ml-auto`} onClick={() => setAEditar(null)}><IconMais size={14} /> Nova cabine</button>}
      </div>
      <TabelaBase
        colunas={[
          { rotulo: 'Cabine', valor: (c) => <span className="tabular-nums">{c.descricao}</span> },
          { rotulo: 'Equipamentos', valor: (c) => c.equipamentos || '', classe: 'w-32 text-right tabular-nums' },
          { rotulo: 'Itens', valor: (c) => c.itens || 0, classe: 'w-20 text-right tabular-nums' },
        ]}
        linhas={lista}
        aoAbrir={admin ? (c) => setAEditar(dados.cabines.find((x) => x.id === c.id)) : null}
        vazio="Ainda não há cabines na base."
      />
      {aEditar !== undefined && <ModalCabine cabine={aEditar} onFechar={() => setAEditar(undefined)} />}
    </>
  );
}

// ─── Pessoas ───────────────────────────────────────────────────────────────

function BasePessoas({ admin }) {
  const { dados, irPara } = useLista();
  return (
    <>
      <div className="mb-4 flex flex-wrap items-center gap-3">
        <span className="text-sm text-muted-foreground">
          Quem recebe a lista e quem pode atualizá-la. Só o administrador cria itens e mexe na base.
        </span>
        {admin && <a href="#/pessoa" className={`${BOTAO_PRIMARIO} ml-auto`}><IconMais size={14} /> Nova pessoa</a>}
      </div>
      <TabelaBase
        colunas={[
          { rotulo: 'Nome', valor: (p) => <span className="font-medium">{p.nome}</span> },
          { rotulo: 'Função', valor: (p) => p.funcao },
          { rotulo: 'Perfil', valor: (p) => <Badge variante={p.perfil === 'admin' ? 'primario' : p.perfil === 'editor' ? 'neutro' : 'contorno'}>{ROTULO_PERFIL[p.perfil]}</Badge> },
          { rotulo: 'Comercial', valor: (p) => (p.comercial ? 'Sim' : ''), classe: 'w-24' },
          { rotulo: 'Notificações', valor: (p) => (p.notificar ? 'Sim' : 'Não'), classe: 'w-28' },
        ]}
        linhas={dados.pessoas}
        aoAbrir={admin ? (p) => irPara('pessoa', null, { id: p.id }) : null}
        vazio="Sem pessoas."
      />
    </>
  );
}

// ─── Listas ────────────────────────────────────────────────────────────────

const LISTAS_BASE = [
  { chave: 'situacao', rotulo: 'Situação do negócio', ajuda: 'A coluna "P. Situação" do Excel.' },
  { chave: 'tipoVenda', rotulo: 'Tipo de venda', ajuda: 'A coluna "Tipo Venda" do Excel.' },
  { chave: 'departamentos', rotulo: 'Departamentos', ajuda: 'A coluna "Departamento" do Excel.' },
  { chave: 'funcoes', rotulo: 'Funções', ajuda: 'A função de cada pessoa.' },
];

function ListaEditavel({ lista, admin }) {
  const { dados, acoes } = useLista();
  const [novo, setNovo] = React.useState('');
  const valores = dados.listas[lista.chave] || [];
  function juntar(e) {
    e.preventDefault();
    if (!novo.trim()) return;
    acoes.adicionarNaLista(lista.chave, novo.trim());
    setNovo('');
  }
  return (
    <section className="border bg-card p-5">
      <h3 className="text-sm font-semibold">{lista.rotulo}</h3>
      <p className="mb-3 mt-0.5 text-xs text-muted-foreground">{lista.ajuda}</p>
      <div className="flex flex-wrap gap-2">
        {valores.map((v) => (
          <span key={v} className="inline-flex items-center gap-1.5 rounded-md bg-secondary px-2.5 py-1 text-sm">
            {v}
            {admin && (
              <button type="button" onClick={() => acoes.removerDaLista(lista.chave, v)} className="text-muted-foreground hover:text-foreground" aria-label={`Tirar ${v}`}>
                <IconFechar size={12} />
              </button>
            )}
          </span>
        ))}
      </div>
      {admin && (
        <form onSubmit={juntar} className="mt-3 flex gap-2">
          <input className="campo" value={novo} onChange={(e) => setNovo(e.target.value)} placeholder="Novo valor" aria-label={`Novo valor em ${lista.rotulo}`} />
          <button type="submit" className={BOTAO_SECUNDARIO}>Juntar</button>
        </form>
      )}
    </section>
  );
}

// ─── Ecrã ──────────────────────────────────────────────────────────────────

function ScreenBase({ seccao }) {
  const { dados, utilizador, irPara } = useLista();
  const admin = utilizador.perfil === 'admin';
  const activa = SECCOES_BASE.some((s) => s.chave === seccao) ? seccao : 'itens';
  const contagens = { itens: dados.itens.length, clientes: dados.clientes.length, equipamentos: dados.equipamentos.length, cabines: dados.cabines.length, pessoas: dados.pessoas.length };

  return (
    <>
      <CabecalhoPagina titulo="Base de dados">
        Importada do Excel da Ana a {fmtLongo(parseData(dados.excelDe))} e da lista de {fmtLongo(parseData(dados.listaDe))}.
        {admin ? ' Podes acrescentar e corrigir tudo aqui.' : ' Clientes, equipamentos, cabines, pessoas e listas: só o Bruno os altera. Os itens editam-se no painel de cada um.'}
      </CabecalhoPagina>
      <datalist id="lista-cabines-base">{dados.cabines.map((c) => <option key={c.id} value={c.descricao} />)}</datalist>
      <Separadores
        rotulo="Secções da base de dados"
        separadores={SECCOES_BASE.map((s) => ({ chave: s.chave, rotulo: contagens[s.chave] != null ? `${s.rotulo} ${contagens[s.chave]}` : s.rotulo }))}
        activo={activa}
        aoMudar={(chave) => irPara('base', null, { sec: chave })}
      />
      <PainelSeparador chave="itens" activo={activa}><BaseItens /></PainelSeparador>
      <PainelSeparador chave="clientes" activo={activa}><BaseClientes admin={admin} /></PainelSeparador>
      <PainelSeparador chave="equipamentos" activo={activa}><BaseEquipamentos admin={admin} /></PainelSeparador>
      <PainelSeparador chave="cabines" activo={activa}><BaseCabines admin={admin} /></PainelSeparador>
      <PainelSeparador chave="pessoas" activo={activa}><BasePessoas admin={admin} /></PainelSeparador>
      <PainelSeparador chave="listas" activo={activa}>
        <div className="grid gap-4 md:grid-cols-2">
          {LISTAS_BASE.map((l) => <ListaEditavel key={l.chave} lista={l} admin={admin} />)}
        </div>
      </PainelSeparador>
    </>
  );
}
