/**
 * Lojas — os sítios onde a marca existe.
 *
 * Era um placeholder desde a Fase 0, com a tabela criada na migração 007 e
 * sozinha desde então. É a peça mais pequena que faltava e é a que destranca as
 * campanhas: uma campanha escolhe lojas, e sem lojas o briefing não tem
 * terceiro passo.
 *
 * ## O limite do plano diz-se antes, não depois
 *
 * O botão de acrescentar desliga-se quando o plano está no tecto, com a razão
 * escrita ao lado. A alternativa — deixar preencher o formulário todo e dar
 * 409 no fim — é a forma mais irritante de dar a mesma informação.
 *
 * ## Painéis e lojas
 *
 * Cada loja diz quantos painéis tem, e uma loja com painéis instalados não se
 * apaga. O painel é um objecto físico numa parede: deixá-lo a apontar para uma
 * loja apagada dava um inventário a dizer que o equipamento está algures e
 * ninguém sabe onde. O ecrã não esconde o botão — explica.
 */

function LojaLinha({ loja, podeMexer, ocupado, onEditar, onApagar }) {
  const morada = [loja.address, loja.postal_code, loja.city].filter(Boolean).join(', ');

  return (
    // Um cartão por loja (28 Set). A grelha de células dentro de um Painel
    // deixava uma loja sozinha num canto escuro e o resto do cartão vazio.
    <li className="flex flex-col justify-between gap-4 border border-border bg-card p-5">
      <div className="flex min-w-0 gap-3">
        <IconLojas size={18} className="mt-0.5 shrink-0 text-primary" />
        <div className="min-w-0">
          <p className="truncate text-sm font-medium text-foreground">{loja.name}</p>
          {morada && <p className="mt-0.5 text-xs text-muted-foreground">{morada}</p>}
          <p className="mt-2 text-xs">
            <span className={loja.paineis > 0 ? 'text-foreground' : 'text-muted-foreground'}>
              {loja.paineis > 0
                ? `${loja.paineis} ${loja.paineis === 1 ? 'painel instalado' : 'painéis instalados'}`
                : 'sem painéis'}
            </span>
            <span className="text-muted-foreground">
              {loja.geo_lat !== null && loja.geo_lat !== undefined ? ' · no mapa' : ' · sem coordenadas'}
            </span>
          </p>
        </div>
      </div>

      {podeMexer && (
        <div className="flex flex-wrap gap-2">
          <button
            type="button"
            disabled={ocupado}
            onClick={() => onEditar(loja)}
            className="border border-border px-3 py-1.5 text-xs disabled:opacity-50"
          >
            Editar
          </button>
          <button
            type="button"
            disabled={ocupado}
            onClick={() => onApagar(loja)}
            className="ns-btn ns-btn-sm ns-btn-fantasma text-xs hover:!text-[hsl(0_80%_70%)]"
          >
            Apagar
          </button>
        </div>
      )}
    </li>
  );
}

/**
 * O formulário, num modal.
 *
 * As coordenadas são opcionais e estão juntas de propósito — a API recusa meia
 * coordenada, e um formulário que as separasse convidava ao erro.
 */
function ModalLoja({ loja, aberto, ocupado, onFechar, onGuardar }) {
  const comoNumero = (v) => (Number.isFinite(Number(String(v).replace(',', '.'))) ? Number(String(v).replace(',', '.')) : String(v));
  const vazia = { name: '', address: '', postal_code: '', city: '', geo_lat: '', geo_lng: '', notes: '' };
  const [campos, setCampos] = React.useState(vazia);

  React.useEffect(() => {
    if (!aberto) return;
    setCampos(
      loja
        ? {
          name: loja.name || '',
          address: loja.address || '',
          postal_code: loja.postal_code || '',
          city: loja.city || '',
          geo_lat: loja.geo_lat ?? '',
          geo_lng: loja.geo_lng ?? '',
          notes: loja.notes || '',
        }
        : vazia
    );
  }, [aberto, loja]);

  const mudar = (chave) => (e) => setCampos((c) => ({ ...c, [chave]: e.target.value }));

  const submeter = (e) => {
    e.preventDefault();
    if (!campos.name.trim()) return;
    onGuardar(loja, {
      ...campos,
      // Um valor que não é número segue como está, e o servidor recusa-o: o Number() dava NaN,
      // que o JSON manda como null, e a loja ficava «sem coordenadas» em silêncio (cliente simulado, 6 Out).
      geo_lat: campos.geo_lat === '' ? null : comoNumero(campos.geo_lat),
      geo_lng: campos.geo_lng === '' ? null : comoNumero(campos.geo_lng),
    });
  };

  const campo = (chave, rotulo, extra = {}) => (
    <div>
      <label htmlFor={`loja-${chave}`} className="label-eyebrow">
        {rotulo}
      </label>
      <input
        id={`loja-${chave}`}
        value={campos[chave]}
        onChange={mudar(chave)}
        {...extra}
        className="mt-1 w-full border border-border bg-background px-3 py-2 text-sm text-foreground outline-none placeholder:text-muted-foreground focus-visible:border-primary"
      />
    </div>
  );

  return (
    <Modal
      aberto={aberto}
      onFechar={onFechar}
      titulo={loja ? 'Editar loja' : 'Nova loja'}
      acoes={
        <>
          <button
            type="button"
            onClick={onFechar}
            className="border border-border px-4 py-2 text-sm uppercase tracking-wider text-muted-foreground outline-none hover:text-foreground focus-visible:ring-1 focus-visible:ring-accent"
          >
            Cancelar
          </button>
          <button
            type="submit"
            form="form-loja"
            disabled={ocupado || !campos.name.trim()}
            className="bg-primary px-4 py-2 text-sm uppercase tracking-wider text-primary-foreground outline-none hover:bg-primary/90 focus-visible:ring-1 focus-visible:ring-accent disabled:bg-secondary disabled:text-muted-foreground"
          >
            Guardar
          </button>
        </>
      }
    >
      <form id="form-loja" onSubmit={submeter} className="space-y-3">
        {campo('name', 'Nome (obrigatório)', { placeholder: 'Loja do Centro', maxLength: 255, autoFocus: true })}
        {campo('address', 'Morada', { placeholder: 'Rua de Exemplo 1' })}
        <div className="grid grid-cols-2 gap-3">
          {campo('postal_code', 'Código postal', { placeholder: '4000-000', maxLength: 16 })}
          {campo('city', 'Cidade', { placeholder: 'Porto', maxLength: 128 })}
        </div>

        <div>
          <p className="label-eyebrow">Coordenadas</p>
          <p className="mt-1 text-xs text-muted-foreground">
            Opcionais, mas vêm as duas ou nenhuma. Servem para a loja aparecer no mapa da rede.
          </p>
          <div className="mt-1 grid grid-cols-2 gap-3">
            <input
              aria-label="Latitude"
              value={campos.geo_lat}
              onChange={mudar('geo_lat')}
              placeholder="41.1496"
              inputMode="decimal"
              className="w-full border border-border bg-background px-3 py-2 text-sm text-foreground outline-none placeholder:text-muted-foreground focus-visible:border-primary"
            />
            <input
              aria-label="Longitude"
              value={campos.geo_lng}
              onChange={mudar('geo_lng')}
              placeholder="-8.6109"
              inputMode="decimal"
              className="w-full border border-border bg-background px-3 py-2 text-sm text-foreground outline-none placeholder:text-muted-foreground focus-visible:border-primary"
            />
          </div>
        </div>

        <div>
          <label htmlFor="loja-notes" className="label-eyebrow">
            Notas
          </label>
          <textarea
            id="loja-notes"
            rows={3}
            value={campos.notes}
            onChange={mudar('notes')}
            className="mt-1 w-full border border-border bg-background px-3 py-2 text-sm text-foreground outline-none focus-visible:border-primary"
          />
        </div>
      </form>
    </Modal>
  );
}

/**
 * "Lojas e painéis" é uma entrada só no menu (28 Set, de 7 para 5 entradas):
 * as Lojas e os Painéis e assistente ficam a um clique, nestes separadores no
 * topo dos dois ecrãs. São ligações entre páginas (cada uma tem o seu URL), e
 * por isso `nav` com aria-current, e não role=tab.
 */
function SeparadoresRede({ slug, activo, onNavegar }) {
  const itens = [['lojas', 'Lojas'], ['paineis-pdv', 'Painéis e assistente']];
  return (
    <nav aria-label="Lojas e painéis" className="flex flex-wrap gap-x-6 border-b border-border">
      {itens.map(([chave, rotulo]) => (
        <a
          key={chave}
          href={`/${slug}/${chave}`}
          aria-current={activo === chave ? 'page' : undefined}
          onClick={(e) => { if (onNavegar) { e.preventDefault(); onNavegar(`/${slug}/${chave}`); } }}
          className={`-mb-px border-b-2 py-3 text-sm outline-none ${
            activo === chave ? 'border-primary font-medium text-foreground' : 'border-transparent text-muted-foreground hover:text-foreground'
          }`}
        >
          {rotulo}
        </a>
      ))}
    </nav>
  );
}

function ScreenLojas({ slug, onNavegar }) {
  const [dados, setDados] = React.useState(null);
  const [erro, setErro] = React.useState(null);
  const [ocupado, setOcupado] = React.useState(false);
  const [aEditar, setAEditar] = React.useState(undefined); // undefined = fechado
  const [toast, setToast] = React.useState(null);
  const fecharToast = React.useCallback(() => setToast(null), []);

  const carregar = React.useCallback(
    () =>
      api
        .get(`/api/${slug}/lojas`)
        .then(setDados)
        .catch((e) => setErro(e.message || 'Não foi possível ler as lojas.')),
    [slug]
  );

  React.useEffect(() => {
    setDados(null);
    setErro(null);
    carregar();
  }, [carregar]);

  const comAviso = async (accao, mensagem) => {
    setOcupado(true);
    try {
      await accao();
      await carregar();
      if (mensagem) setToast({ id: Date.now(), mensagem });
      return true;
    } catch (e) {
      setToast({ id: Date.now(), mensagem: e.message, erro: true });
      return false;
    } finally {
      setOcupado(false);
    }
  };

  const guardar = async (loja, campos) => {
    const ok = await comAviso(
      () =>
        loja
          ? api.patch(`/api/${slug}/lojas/${loja.id}`, campos)
          : api.post(`/api/${slug}/lojas`, campos),
      loja ? 'Loja actualizada.' : 'Loja criada.'
    );
    if (ok) setAEditar(undefined);
  };

  const cabecalho = (
    <header className="space-y-4">
      <h1 className="font-display text-4xl uppercase leading-none tracking-wide">Lojas e painéis</h1>
      <SeparadoresRede slug={slug} activo="lojas" onNavegar={onNavegar} />
    </header>
  );

  if (erro) {
    return (
      <div className="space-y-6">
        {cabecalho}
        <div className="border border-border bg-card px-6 py-12 text-center">
          <p className="font-display text-xl tracking-wide">Não deu para ler as lojas</p>
          <p className="mt-2 text-sm text-muted-foreground">{erro}</p>
        </div>
      </div>
    );
  }

  if (!dados) {
    return (
      <div className="space-y-6">
        {cabecalho}
        <SkeletonTabela linhas={3} />
      </div>
    );
  }

  const noTecto = dados.limite !== null && dados.lojas.length >= dados.limite;

  return (
    <div className="space-y-9">
      {cabecalho}

      <section>
        <div className="flex flex-wrap items-start justify-between gap-4">
          <div className="min-w-0">
            <p className="text-sm text-muted-foreground">
              {dados.lojas.length}{' '}
              {dados.lojas.length === 1 ? 'loja' : 'lojas'}
              {dados.limite === null
                ? '. O teu plano não tem limite.'
                : ` de ${dados.limite} ${dados.limite === 1 ? 'que o plano dá' : 'que o plano dá'}.`}
              {noTecto && (
                <>
                  {' '}
                  <span className="text-accent">Não há mais lugares</span> — fala com a NetScreen
                  para mudar de plano.
                </>
              )}
            </p>
          </div>
          {!dados.podes_gerir && <SoQuemPode className="max-w-xs" accao="acrescentar ou mudar lojas" />}
          {dados.podes_gerir && (
            <button
              type="button"
              disabled={noTecto}
              onClick={() => setAEditar(null)}
              title={noTecto ? 'O plano não dá mais lojas' : undefined}
              className="shrink-0 bg-primary px-4 py-2 text-sm text-primary-foreground outline-none hover:bg-primary/90 disabled:cursor-not-allowed"
            >
              Nova loja
            </button>
          )}
        </div>

        {dados.lojas.length === 0 ? (
          <div className="mt-3 border border-dashed border-border bg-card px-6 py-10 text-center">
            <p className="text-sm text-foreground">Ainda não há lojas.</p>
            <p className="mx-auto mt-2 max-w-prose text-xs leading-relaxed text-muted-foreground">
              As campanhas escolhem em que lojas ficam activas, e os painéis são instalados numa.
              Começa por acrescentar a primeira.
            </p>
          </div>
        ) : (
          <ul className="mt-5 grid grid-cols-1 gap-4 md:grid-cols-2 lg:grid-cols-3">
            {dados.lojas.map((l) => (
              <LojaLinha
                key={l.id}
                loja={l}
                podeMexer={dados.podes_gerir}
                ocupado={ocupado}
                onEditar={setAEditar}
                onApagar={(loja) =>
                  comAviso(() => api.del(`/api/${slug}/lojas/${loja.id}`), 'Loja apagada.')
                }
              />
            ))}
          </ul>
        )}

        {dados.limite !== null && (
          <div className="mt-6 max-w-sm">
            <BarraUso rotulo="Lojas que o plano dá" usado={dados.lojas.length} limite={dados.limite} />
          </div>
        )}
      </section>

      <ModalLoja
        aberto={aEditar !== undefined}
        loja={aEditar || null}
        ocupado={ocupado}
        onFechar={() => setAEditar(undefined)}
        onGuardar={guardar}
      />
      <Toast toast={toast} onFechar={fecharToast} />
    </div>
  );
}
