/* Teclado numérico gigante — variantes: pin | qtd | venda */

function NumPad({ value, onChange, maxLen = 6, disabled }) {
  // ref espelho: garante que toques em sequência rápida não usem valor obsoleto
  const valRef = React.useRef(value);
  valRef.current = value;
  function tap(d) {
    if (disabled) return;
    const cur = valRef.current;
    const next = d === '⌫' ? cur.slice(0, -1) : (cur.length < maxLen ? cur + d : cur);
    if (next !== cur) { valRef.current = next; onChange(next); }
  }
  const keys = ['1', '2', '3', '4', '5', '6', '7', '8', '9', '', '0', '⌫'];
  return (
    <div className={'numpad' + (disabled ? ' disabled' : '')}>
      {keys.map((k, i) =>
        k === '' ? (
          <span key={i}></span>
        ) : (
          <button key={i} className={'np-key' + (k === '⌫' ? ' back' : '')} disabled={disabled} onClick={() => tap(k)}>
            {k === '⌫' ? <EIcon name="backspace" size={30} /> : k}
          </button>
        )
      )}
    </div>
  );
}

const PAPEL_NOME = { gestor: 'Gestor', escritorio: 'Escritório', vendedor: 'Vendedor', motorista: 'Motorista', estoquista: 'Estoquista' };

/* PIN: identifica a PESSOA. Não exige "PIN de superior".
   Se a pessoa identificada não tiver permissão para a ação (permite=op=>bool),
   mostra "Seu perfil (X) não permite <acaoLabel>" — nunca "peça ao gestor". */
function PinPad({ onValidado, permite, acaoLabel }) {
  const { useState, useEffect, useRef } = React;
  const [pin, setPin] = useState('');
  const [erro, setErro] = useState(null);
  const [shakeK, setShakeK] = useState(0);
  const [erros, setErros] = useState(0);
  const [bloqueio, setBloqueio] = useState(0);
  const [bloqueadoServidor, setBloqueadoServidor] = useState(false);
  const [verificando, setVerificando] = useState(false);
  const timer = useRef(null);

  useEffect(() => {
    if (bloqueio <= 0) return;
    timer.current = setTimeout(() => setBloqueio(bloqueio - 1), 1000);
    return () => clearTimeout(timer.current);
  }, [bloqueio]);

  function falha(msg, contaErro) {
    const n = contaErro ? erros + 1 : erros;
    if (contaErro) setErros(n);
    setErro(msg);
    setShakeK(Date.now());
    setPin('');
    if (contaErro && n >= 3) { setBloqueio(30); setErros(0); }
  }

  function change(v) {
    setPin(v);
    setErro(null);
    if (v.length === 4) {
      setVerificando(true);
      ESTQ.verificarPin(v).then((op) => {
        setVerificando(false);
        setBloqueadoServidor(false);
        // PIN válido: identifica a pessoa. Permissão é decidida pelo PAPEL dela.
        if (permite && !permite(op)) {
          return falha('Seu perfil (' + (PAPEL_NOME[op.papel] || op.papel) + ') não permite ' + (acaoLabel || 'esta ação'), false);
        }
        onValidado(op, v);
      }).catch((e) => {
        setVerificando(false);
        setPin('');
        // Bloqueio do servidor (5 falhas seguidas em qualquer PIN): não é um
        // simples "PIN incorreto" — o teclado continua ativo de propósito,
        // é assim que um gestor consegue liberar entrando com o PIN dele.
        if (e && /bloqueado/i.test(e.message || '')) {
          setBloqueadoServidor(true);
          setErro(e.message);
          setShakeK(Date.now());
          return;
        }
        setBloqueadoServidor(false);
        falha('PIN incorreto', true);
      });
    }
  }

  const bloqueado = bloqueio > 0;
  return (
    <div className="pinpad">
      <div className="pin-dots" key={shakeK} data-shake={shakeK ? '1' : undefined}>
        {[0, 1, 2, 3].map((i) => (
          <span key={i} className={'pin-dot' + (i < pin.length ? ' on' : '')}></span>
        ))}
      </div>
      {verificando && <div className="np-erro" style={{ color: 'var(--gray-500)' }}>Verificando…</div>}
      {bloqueadoServidor && <div className="np-erro">{erro}</div>}
      {erro && !bloqueadoServidor && !bloqueado && !verificando && <div className="np-erro">{erro}</div>}
      {bloqueado && !bloqueadoServidor && <div className="np-erro">Muitas tentativas — aguarde {bloqueio}s</div>}
      <NumPad value={pin} onChange={change} maxLen={4} disabled={(bloqueado && !bloqueadoServidor) || verificando} />
    </div>
  );
}

/* Quantidade: número grande + conversão m² ao vivo + [Todas as caixas] */
function QtdPad({ value, onChange, max, m2cx, unidade }) {
  const n = parseInt(value || '0', 10);
  const excede = n > max;
  const isMat = !m2cx;
  const noun = isMat ? (unidade || 'un') : (n === 1 ? 'caixa' : 'caixas');
  return (
    <div className="qtdpad">
      <div className={'qtd-display' + (excede ? ' excede' : '')}>
        <span className="num">{value || '0'}</span>
        <span className="unid">{noun}</span>
      </div>
      <div className={'qtd-m2' + (excede ? ' excede' : '')}>
        {excede
          ? 'Só há ' + max + (isMat ? ' ' + (unidade || 'un') : ' caixas') + ' neste pallet'
          : (!isMat && n > 0) ? '= ' + ESTQ.fmtNum(n * m2cx) + ' m²' : ' '}
      </div>
      {max <= 999 && max > 0 && max !== 999 && (
        <button className={'btn-todas' + (n === max ? ' on' : '')} onClick={() => onChange(String(max))}>
          <EIcon name="layers" size={20} /> {isMat ? 'Todos (' + max + ')' : 'Todas as caixas (' + max + ')'}
        </button>
      )}
      <NumPad value={value} onChange={(v) => onChange(v.replace(/^0+(?=\d)/, ''))} maxLen={3} />
    </div>
  );
}

/* Nº de venda: campo livre numérico */
function VendaPad({ value, onChange }) {
  return (
    <div className="qtdpad">
      <div className="qtd-display">
        <span className={'num' + (value ? '' : ' vazio')}>{value || '— — — —'}</span>
      </div>
      <div className="qtd-m2 hint-venda">Número da notinha</div>
      <NumPad value={value} onChange={onChange} maxLen={8} />
    </div>
  );
}

Object.assign(window, { NumPad, PinPad, QtdPad, VendaPad });
