/* ===== Regras de preço e negociação (14/11) =========================
   Pedido dele: o Paulo registra o preço de manhã e o sistema resolve o
   resto sozinho — inclusive a negociação — sem ele aprovar pedido por
   pedido. Só o caso raríssimo sobe para ele.

   TRÊS FAIXAS, nesta ordem de preferência:

     CHEIO       preço do dia                        aprovação automática
     NEGOCIADO   até o limite calculado aqui         aprovação automática
     EXCEÇÃO     abaixo do limite                    o Paulo autoriza no app

   ⚠️ TUDO AQUI É HIPÓTESE, para ser revisto com o Paulo. Os números
   estão todos nesta tabela de propósito: mudar a regra é mudar uma
   linha, não caçar conta espalhada pelas telas.

   De onde sai a folga de negociação, nas palavras dele:
   - "se o estoque está alto ele tem que vender para poder girar;
      se está baixo ele pode segurar" → folga de ESTOQUE
   - "cliente que compra raríssimas vezes… faz sentido? talvez não.
      cliente fiel, às vezes faz sentido melhorar o preço" → folga de CLIENTE
   - quem paga atrasado não ganha desconto → TRAVA
   ================================================================== */

const PR_HIPOTESE = {
  /* preço do dia que o sistema sugere quando o Paulo ainda não abriu o dia */
  padraoRetira: 3.70,
  padraoEntrega: 3.92,

  /* folga por cobertura de estoque, em R$/L */
  estoque: [
    {min:10, bonus:0.10, rot:'estoque alto: precisa girar'},
    {min:7,  bonus:0.06, rot:'estoque confortável'},
    {min:3,  bonus:0.02, rot:'estoque apertado'},
    {min:0,  bonus:0.00, rot:'menos de 3 dias de estoque: não dá para negociar'},
  ],

  /* folga por recorrência do cliente (compras por mês), em R$/L */
  cliente: [
    {min:20, bonus:0.06, rot:'cliente fiel'},
    {min:10, bonus:0.03, rot:'compra com regularidade'},
    {min:4,  bonus:0.01, rot:'compra de vez em quando'},
    {min:0,  bonus:0.00, rot:'compra raramente: não vale baixar o preço'},
  ],

  /* quem atrasa pagamento perde a folga */
  atrasoTrava: 10,
  /* teto duro: nenhuma negociação automática passa disto */
  tetoDesconto: 0.15,
};

const prFaixaDe = (tabela, v) => tabela.find(f => v >= f.min) || tabela[tabela.length-1];

/* Cobertura de estoque em dias. Sem estoque lançado, devolve null. */
function prEstoque(){
  if(typeof initialEstoque === 'undefined' || !initialEstoque.length) return null;
  const e = initialEstoque[0];
  if(!e || !e.vendaDia) return null;
  return {prod:e.prod, dias: e.litros / e.vendaDia};
}

/* ===== Frete de CADA cliente (14/11) ==============================
   O buraco que a rodada anterior abriu: o preço de entrega era um só
   para todo mundo, mas levar 10.000 L a 70 km custa muito mais por
   litro do que levar 45.000 L a 20 km. Cliente longe com carga pequena
   podia estar sendo vendido no prejuízo sem ninguém ver.

   Não inventei tabela de frete: uso o MESMO cálculo que a Carteira de
   clientes já faz há semanas — ida e volta, pelo custo por km da frota,
   dividido pelos litros que cabem na viagem daquele cliente. */
function prFreteCliente(cliente, bases, custoKm){
  if(!cliente) return null;
  if(typeof dist === 'undefined' || typeof CUSTO_KM === 'undefined') return null;
  const garagem = ((bases||[]).find(b=>b.garage) || {city:'Barretos'}).city;
  const km = Math.max(dist(garagem, cliente.city), 8);
  const carga = cliente.carga || 30000;
  const ck = (custoKm != null && custoKm > 0) ? custoKm : CUSTO_KM;
  return {km, carga, custoKm: ck, porL: 2*km*ck/carga};
}

/* Preço cheio do cliente: depende de ele retirar ou receber */
function prCheio(cliente, precoDia){
  if(!precoDia) return null;
  const modo = (cliente && cliente.modo) || 'entrega';
  const v = modo === 'retira' ? precoDia.retira : precoDia.entrega;
  return (v == null) ? null : v;
}

/* O cálculo inteiro para um cliente, num objeto só.
   Devolve null quando ainda não há preço do dia. */
function prNegociacao(cliente, precoDia, bases){
  const cheio = prCheio(cliente, precoDia);
  if(cheio == null) return null;
  const modo = (cliente && cliente.modo) || 'entrega';

  /* PISO DE CUSTO: entregar abaixo de (preço de retirada + frete deste
     cliente) é pagar para transportar. Vale só para quem recebe em casa:
     quem retira leva com o caminhão dele, e o custo do produto em si o
     sistema ainda não conhece. */
  const fr = modo==='entrega' ? prFreteCliente(cliente, bases, precoDia && precoDia.custoKm) : null;
  const piso = (fr && precoDia && precoDia.retira!=null) ? precoDia.retira + fr.porL : null;

  const est = prEstoque();
  const fE = est ? prFaixaDe(PR_HIPOTESE.estoque, est.dias) : {bonus:0, rot:'sem estoque lançado'};
  const fC = cliente ? prFaixaDe(PR_HIPOTESE.cliente, cliente.compras||0) : {bonus:0, rot:'cliente sem histórico'};
  const atrasado = !!cliente && (cliente.atraso||0) >= PR_HIPOTESE.atrasoTrava;

  const partes = [
    {rot: fE.rot, valor: fE.bonus, fonte:'Estoque' + (est ? ` · ${Math.floor(est.dias)} dias` : '')},
    {rot: fC.rot, valor: fC.bonus, fonte:'Cliente' + (cliente ? ` · ${cliente.compras||0} compras/mês` : '')},
  ];
  if(atrasado) partes.push({rot:`paga com ${cliente.atraso} dias de atraso: folga cancelada`, valor:null, fonte:'Pagamento'});

  let desconto = atrasado ? 0 : Math.min(fE.bonus + fC.bonus, PR_HIPOTESE.tetoDesconto);
  let limite = Math.round((cheio - desconto) * 1000) / 1000;

  /* o frete deste cliente levanta o piso e pode comer a folga inteira */
  let freteComeu = false, precoAbaixoDoCusto = false;
  if(piso != null){
    if(cheio < piso - 0.0005) precoAbaixoDoCusto = true;
    if(limite < piso){ limite = Math.round(piso*1000)/1000; freteComeu = true; }
  }
  const descontoReal = Math.round((cheio - limite)*1000)/1000;
  if(fr) partes.push({rot:`${fr.km} km ida e volta, ${fmt(fr.carga)} L por viagem, a ${brl2(fr.custoKm)}/km`,
                      valor:null, fonte:`Frete deste cliente · ${brl3(fr.porL)}/L`});

  return {
    modo, cheio, desconto: descontoReal, limite,
    podeNegociar: descontoReal > 0.0005,
    frete: fr, piso, freteComeu, precoAbaixoDoCusto,
    partes,
    teto: PR_HIPOTESE.tetoDesconto,
  };
}

/* Em que faixa cai um preço digitado */
function prClassificar(preco, neg){
  if(!neg || preco == null) return {k:'indefinido', rot:'—', pill:'p-carregando', auto:true};
  if(preco >= neg.cheio - 0.0005) return {k:'cheio', rot:'Preço cheio', pill:'p-base', auto:true,
    txt:'Fechou no preço do dia.'};
  if(preco >= neg.limite - 0.0005) return {k:'negociado', rot:'Negociado', pill:'p-rota', auto:true,
    txt:`Dentro da sua autonomia de hoje (até ${brl3(neg.limite)}/L).`};
  const prejuizo = neg.piso!=null && preco < neg.piso - 0.0005;
  return {k:'excecao', rot:'Precisa de autorização', pill:'p-manutencao', auto:false,
    txt:`Abaixo do limite de hoje (${brl3(neg.limite)}/L). O pedido vai para o Paulo autorizar no app.`
        + (prejuizo?` Atenção: abaixo de ${brl3(neg.piso)}/L a entrega até este cliente sai no prejuízo.`:'')};
}


/* ---- As duas pecas de tela que leem estas regras -----------------
   Ficam aqui, e nao em seller.jsx, por dois motivos: quem mexer na
   regra ve a tela no mesmo arquivo, e o seller.jsx fica abaixo do
   limite de tamanho que da para publicar sem errar a transcricao. */

function PrFaixa({neg, cli, modo, cls, precoL}){
  if(!neg) return <p className="rs warn np-fx-msg">O Paulo ainda não abriu o preço de hoje. Sem isso não dá para fechar pedido.</p>;
  return <div className="np-faixa">
    <div className="np-fx-topo"><b>Até onde você pode ir com {cli.name}</b>
      {cls&&precoL>0&&<span className={'pill '+cls.pill}>{cls.rot}</span>}</div>
    <div className="np-fx-escada">
      <div className="on"><span>Preço cheio</span><b>{brl3(neg.cheio)}</b><small>{modo==='retira'?'ele retira':'nós entregamos'}</small></div>
      <div className={neg.podeNegociar?'':'off'}><span>Pode fechar até</span><b>{neg.podeNegociar?brl3(neg.limite):'—'}</b><small>{neg.podeNegociar?(neg.freteComeu?'o frete deste cliente segura o piso':'sem falar com o Paulo'):(neg.freteComeu?'o frete não deixa baixar':'hoje não dá para negociar')}</small></div>
      <div className="off"><span>Abaixo disso</span><b>autorização</b><small>o Paulo decide no app</small></div>
    </div>
    <ul className="np-fx-por">{neg.partes.map((pt,i)=><li key={i}>
      <em>{pt.fonte}</em> {pt.rot} {pt.valor!=null&&pt.valor>0?<b>+{brl3(pt.valor)}</b>:null}</li>)}</ul>
    {neg.precoAbaixoDoCusto && <p className="rs bad np-fx-msg">O preço de entrega de hoje ({brl3(neg.cheio)}) não cobre o frete até este cliente ({brl3(neg.piso)} de piso). Qualquer venda aqui sai no prejuízo — fale com o Paulo.</p>}
    {cls&&precoL>0&&<p className={'rs '+(cls.k==='excecao'?'bad':cls.k==='negociado'?'warn':'good')+' np-fx-msg'}>{cls.txt}</p>}
  </div>;
}

function PrConfirmar({seller, cli, form, vol, precoL, cls, onVoltar, onConfirmar}){
  return <div className="np-modal" role="dialog" aria-modal="true" aria-label="Confirmar pedido">
    <div className="np-cx">
      <p className="np-cx-tit">Confirma?</p>
      <dl className="np-cx-campos">
        <div><dt>Vendedor</dt><dd>{seller.name}</dd></div>
        <div><dt>Cliente</dt><dd>{cli.name} · {cli.city}</dd></div>
        <div><dt>Entrega</dt><dd>{form.modo==='retira'?'O cliente retira':'Nós entregamos'}</dd></div>
        <div><dt>Volume</dt><dd>{fmt(vol)} L de {form.product}</dd></div>
        <div><dt>Preço final</dt><dd>{brl3(precoL)}/L</dd></div>
        <div><dt>Total</dt><dd>{brl(Math.round(vol*precoL))}</dd></div>
      </dl>
      <p className={'rs '+(cls.k==='excecao'?'bad':cls.k==='negociado'?'warn':'good')+' np-cx-msg'}>
        <b>{cls.rot}.</b> {cls.txt}</p>
      <div className="np-cx-acoes">
        <button className="secondary" onClick={onVoltar}>Voltar e corrigir</button>
        <button className="primary" onClick={onConfirmar}>{cls.auto?'Confirmar e enviar':'Enviar para autorização'}</button>
      </div>
    </div>
  </div>;
}
