require 'rails_helper'

RSpec.describe 'Dashboard', type: :request do
  it 'redireciona usuário não autenticado para o login' do
    get dashboard_path
    expect(response).to redirect_to(new_user_session_path)
  end

  it 'redireciona motorista para o painel exclusivo de motorista' do
    sign_in create(:motorista)
    get dashboard_path
    expect(response).to redirect_to(motorista_dashboard_path)
  end
end

# Trava a CONTABILIZAÇÃO DAS FALHAS no dashboard principal.
#
# A base financeira do dashboard é `atendidas` (concluídas + falhadas, com
# checkout) — o MESMO conjunto que a consolidação considera elegível e paga.
# Antes usava só `pagas` (concluídas) e o valor da tela ficava menor que o do
# fechamento; e as falhas eram filtradas por `planned_date`, caindo no período
# errado. Os dois casos estão fixados aqui.
#
# ⚠️ Falhada TEM checkout: o motorista foi ao local e fechou a visita com motivo
# de insucesso. É o que torna `checkout` o eixo correto também para elas.
RSpec.describe 'Dashboard — contabilização de falhas', type: :request do
  include_context 'espelho de rastreio'

  # Preço redondo para os valores esperados serem óbvios na leitura do spec.
  let(:preco)  { 10.0 }
  let(:inicio) { '2026-08-01' }
  let(:fim)    { '2026-08-14' }

  before do
    create(:configuracao, chave: 'preco_entrega', valor: preco.to_s)
    sign_in create(:gerente)
  end

  def abrir_dashboard
    get dashboard_path, params: { inicio: inicio, fim: fim }
    expect(response).to have_http_status(:ok)
    response.body
  end

  it 'soma a falhada ao valor estimado e ao total de atendidas' do
    semear([
      { driver: 'JOSE DA SILVA', vehicle: 'GADE_001', status: 'completed',
        planned_date: Time.zone.local(2026, 8, 5, 8, 0), checkout: Time.zone.local(2026, 8, 5, 10, 0) },
      { driver: 'JOSE DA SILVA', vehicle: 'GADE_001', status: 'failed',
        planned_date: Time.zone.local(2026, 8, 6, 8, 0), checkout: Time.zone.local(2026, 8, 6, 11, 0) }
    ])

    corpo = abrir_dashboard

    # 2 atendidas × R$ 10,00 — com a base antiga (`pagas`) seria 1 e R$ 10,00.
    expect(corpo).to include('2 entregas atendidas')
    expect(corpo).to include('1 concluídas · 1 falhadas')
    expect(corpo).to include('R$ 20,00')
  end

  it 'conta a falhada pela data do CHECKOUT, não pela planejada' do
    # Planejada em 31/07 (fora), entregue em 01/08 (dentro) → entra.
    semear([
      { driver: 'JOSE DA SILVA', vehicle: 'GADE_002', status: 'failed',
        planned_date: Time.zone.local(2026, 7, 31, 8, 0), checkout: Time.zone.local(2026, 8, 1, 9, 0) }
    ])

    corpo = abrir_dashboard

    expect(corpo).to include('1 entregas atendidas')
    expect(corpo).to include('0 concluídas · 1 falhadas')
  end

  it 'exclui a falhada planejada dentro do período mas com checkout fora' do
    # O espelho do caso acima: planejada em 10/08 (dentro), entregue em 01/09
    # (fora) → não entra. Com o eixo antigo (planned_date) entrava.
    semear([
      { driver: 'JOSE DA SILVA', vehicle: 'GADE_003', status: 'failed',
        planned_date: Time.zone.local(2026, 8, 10, 8, 0), checkout: Time.zone.local(2026, 9, 1, 9, 0) }
    ])

    corpo = abrir_dashboard

    expect(corpo).to include('0 entregas atendidas')
    expect(corpo).to include('0 concluídas · 0 falhadas')
  end

  it 'mantém a pendente fora do valor, contando-a só como pendente' do
    # Pendente não tem checkout: continua no eixo planned_date e não vira R$.
    semear([
      { driver: 'JOSE DA SILVA', vehicle: 'GADE_004', status: 'pending',
        planned_date: Time.zone.local(2026, 8, 7, 8, 0), checkout: nil }
    ])

    corpo = abrir_dashboard

    expect(corpo).to include('0 entregas atendidas')
    expect(corpo).to include('1 pendentes')
  end

  it 'inclui a falhada no ranking por motorista' do
    semear([
      # JOSE: 1 concluída + 1 falhada = 2 atendidas → R$ 20,00
      { driver: 'JOSE DA SILVA', vehicle: 'GADE_005', status: 'completed',
        planned_date: Time.zone.local(2026, 8, 4, 8, 0), checkout: Time.zone.local(2026, 8, 4, 10, 0) },
      { driver: 'JOSE DA SILVA', vehicle: 'GADE_005', status: 'failed',
        planned_date: Time.zone.local(2026, 8, 4, 8, 0), checkout: Time.zone.local(2026, 8, 4, 15, 0) },
      # MARIA: 1 concluída = 1 atendida → R$ 10,00
      { driver: 'MARIA SOUZA', vehicle: 'GADE_006', status: 'completed',
        planned_date: Time.zone.local(2026, 8, 5, 8, 0), checkout: Time.zone.local(2026, 8, 5, 10, 0) }
    ])

    corpo = abrir_dashboard

    expect(corpo).to include('3 entregas atendidas')
    expect(corpo).to include('JOSE DA SILVA')
    # R$ 20,00 do JOSE só existe se a falhada dele entrou na conta do ranking
    # (com a base antiga ele apareceria com R$ 10,00, igual à MARIA).
    expect(corpo).to include('R$ 20,00')
    expect(corpo).to include('R$ 30,00') # total estimado do período
  end
end

# Trava a ABA "CONSOLIDADO" do card de motoristas.
#
# O card tem duas abas sobre o mesmo ranking e elas mostram números diferentes de
# propósito: "Estimado" = atendidas × preço; "Consolidado" = o que realmente foi
# fechado (com bônus/desconto/retirada) + a quantidade de entregas do fechamento.
# Confundir as duas é justamente o que este spec impede.
RSpec.describe 'Dashboard — aba Consolidado do ranking de motoristas', type: :request do
  include_context 'espelho de rastreio'

  let(:inicio) { '2026-08-01' }
  let(:fim)    { '2026-08-14' }

  before do
    create(:configuracao, chave: 'preco_entrega', valor: '10.0')
    sign_in create(:gerente)
  end

  # Só o conteúdo da aba consolidada: a aba estimada renderiza o MESMO markup
  # (moeda + "N entregas"), então asserção no body inteiro passaria por acidente.
  def painel_consolidado
    get dashboard_path, params: { inicio: inicio, fim: fim }
    expect(response).to have_http_status(:ok)
    Nokogiri::HTML(response.body).at_css('#ranking-painel-consolidado').text
  end

  # cria as entregas ANTES do motorista: ConsolidacaoMotorista#recalcular_valor
  # (before_save) soma as consolidacao_entregas do mesmo nome — sem elas o
  # valor_total nasceria zerado.
  def consolidar!(nome, linhas, consolidacao)
    linhas.each { |l| create(:consolidacao_entrega, { consolidacao: consolidacao, motorista_nome: nome }.merge(l)) }
    create(:consolidacao_motorista, consolidacao: consolidacao, motorista_nome: nome)
  end

  let(:consolidacao) do
    create(:consolidacao, status: :finalizada,
           data_inicio: Date.new(2026, 8, 1), data_fim: Date.new(2026, 8, 14))
  end

  it 'mostra o valor fechado e a quantidade exata de entregas de cada motorista' do
    # JOSE: 2 entregas (TRK-A e TRK-B). TRK-A tem DOIS pilares (normal + bônus),
    # então são 3 linhas para 2 entregas — é o caso que quebra se alguém contar
    # linhas em vez de tracking_id distinto.
    consolidar!('JOSE DA SILVA', [
      { tracking_id: 'TRK-A', tipo: :entrega_normal, valor_aplicado: 10.0 },
      { tracking_id: 'TRK-A', tipo: :bonus,          valor_aplicado: 5.0  },
      { tracking_id: 'TRK-B', tipo: :entrega_normal, valor_aplicado: 10.0 }
    ], consolidacao)

    consolidar!('MARIA SOUZA', [
      { tracking_id: 'TRK-C', tipo: :entrega_normal, valor_aplicado: 10.0 }
    ], consolidacao)

    texto = painel_consolidado

    expect(texto).to include('JOSE DA SILVA')
    expect(texto).to include('R$ 25,00')  # 10 + 5 + 10, valor REAL do fechamento
    expect(texto).to include('2 entregas') # e NÃO 3: TRK-A conta uma vez só

    expect(texto).to include('MARIA SOUZA')
    expect(texto).to include('R$ 10,00')
    expect(texto).to include('1 entregas')
  end

  it 'subtrai o desconto do valor fechado' do
    consolidar!('JOSE DA SILVA', [
      { tracking_id: 'TRK-A', tipo: :entrega_normal, valor_aplicado: 10.0 },
      { tracking_id: 'TRK-A', tipo: :desconto,       valor_aplicado: 4.0 }
    ], consolidacao)

    expect(painel_consolidado).to include('R$ 6,00')
  end

  it 'não lista motorista arquivado, que saiu do fechamento' do
    consolidar!('JOSE DA SILVA', [
      { tracking_id: 'TRK-A', tipo: :entrega_normal, valor_aplicado: 10.0 }
    ], consolidacao)
    cm = consolidar!('MARIA SOUZA', [
      { tracking_id: 'TRK-C', tipo: :entrega_normal, valor_aplicado: 10.0 }
    ], consolidacao)
    cm.arquivar!(nil)

    texto = painel_consolidado

    expect(texto).to include('JOSE DA SILVA')
    expect(texto).not_to include('MARIA SOUZA')
  end

  it 'ignora consolidação em rascunho — só entra o que foi finalizado' do
    rascunho = create(:consolidacao, status: :rascunho,
                      data_inicio: Date.new(2026, 8, 1), data_fim: Date.new(2026, 8, 14))
    consolidar!('JOSE DA SILVA', [
      { tracking_id: 'TRK-A', tipo: :entrega_normal, valor_aplicado: 10.0 }
    ], rascunho)

    expect(painel_consolidado).to include('Nenhuma consolidação finalizada neste período')
  end
end

# Tela "Entregas em aberto" — o que há por trás do card "N pendentes".
#
# Em aberto = nem concluída nem falhada, pela data PLANEJADA (é o único recorte
# sem checkout). Tem que usar o MESMO recorte do card, senão o número do
# dashboard leva a uma lista que não bate com ele.
RSpec.describe 'Dashboard — entregas em aberto', type: :request do
  include_context 'espelho de rastreio'

  let(:inicio) { '2026-08-01' }
  let(:fim)    { '2026-08-14' }

  before { sign_in create(:gerente) }

  def abrir_pendentes
    get dashboard_pendentes_path, params: { inicio: inicio, fim: fim }
    expect(response).to have_http_status(:ok)
    response.body
  end

  it 'lista só o que está em aberto dentro do período' do
    semear([
      # Em aberto no período — a única que deve aparecer.
      { reference_id: 85_382, driver: nil, status: 'pending',
        planned_date: Time.zone.local(2026, 8, 3, 8, 0), checkout: nil },
      # Fechadas: não são "em aberto", mesmo planejadas no período.
      { reference_id: 85_383, driver: 'CARLOS', status: 'completed',
        planned_date: Time.zone.local(2026, 8, 4, 8, 0), checkout: Time.zone.local(2026, 8, 4, 10, 0) },
      { reference_id: 85_384, driver: 'CARLOS', status: 'failed',
        planned_date: Time.zone.local(2026, 8, 5, 8, 0), checkout: Time.zone.local(2026, 8, 5, 10, 0) },
      # Em aberto, mas planejada FORA do período.
      { reference_id: 85_385, driver: nil, status: 'pending',
        planned_date: Time.zone.local(2026, 9, 2, 8, 0), checkout: nil }
    ])

    corpo = abrir_pendentes
    expect(corpo).to include('85382')
    expect(corpo).not_to include('85383')
    expect(corpo).not_to include('85384')
    expect(corpo).not_to include('85385')
  end

  # Sem nenhuma tabela gade_entregas_* no banco de teste, toda NF é "fora da
  # operação" — que é exatamente o caso real da NF 85382 que motivou a tela.
  it 'marca a NF que não está em nenhuma planilha de operação' do
    semear([{ reference_id: 85_382, driver: nil, status: 'pending',
              planned_date: Time.zone.local(2026, 8, 3, 8, 0), checkout: nil }])

    expect(abrir_pendentes).to include('fora da operação')
  end

  it 'o card do dashboard aponta para esta tela com o mesmo período' do
    create(:configuracao, chave: 'preco_entrega', valor: '10.0')
    semear([{ reference_id: 85_382, driver: nil, status: 'pending',
              planned_date: Time.zone.local(2026, 8, 3, 8, 0), checkout: nil }])

    get dashboard_path, params: { inicio: inicio, fim: fim }
    # O href sai HTML-escapado (&amp;) e a ordem dos params varia — confere o
    # caminho e o período separadamente.
    expect(response.body).to include(dashboard_pendentes_path)
    expect(response.body).to match(%r{/dashboard/pendentes\?[^"]*inicio=2026-08-01})
  end
end
