# lib/tasks/entregas_motorista.rake
#
# Lista as entregas de um motorista num período lendo o ESPELHO LOCAL
# (model Entrega / tabela db_reem_simplerout_2026) — sem tocar na API do
# SimpliRoute, logo sem precisar de SIMPLIROUTE_TOKEN.
#
# Por que aqui e não na API: a API não tem filtro de intervalo nem de motorista
# (ver bin/entregas_do_motorista), então um período vira N requisições de vários
# MB. No espelho é uma query só. O preço é a defasagem da sync — se precisar do
# estado AO VIVO, use bin/entregas_do_motorista.
#
# SÓ LEITURA: Entrega#readonly? é true; nada aqui escreve.
#
#   rake "entregas:motorista[JOSE DA SILVA,2026-08-01,2026-08-14]"
#   rake "entregas:motorista[JOSE DA SILVA,2026-08-01,2026-08-14,/tmp/saida.csv]"
#   rake "entregas:motoristas[2026-08-01,2026-08-14]"   # quem operou no período
#
# ⚠️ O nome tem que ser a grafia EXATA da coluna `driver` (do_motorista usa
# igualdade). Rode `entregas:motoristas` primeiro para ver a lista; se o nome
# passado não bater exatamente, a task sugere os parecidos em vez de devolver
# vazio silenciosamente.
#
# ⚠️ Período pelo `planned_date` (dia planejado da visita), que é o mesmo eixo
# do dashboard. As análises FINANCEIRAS usam `checkout` (data real da entrega) —
# são recortes diferentes; passe FONTE=checkout para usar esse outro eixo.

namespace :entregas do
  desc 'Entregas de um motorista no período, lidas do espelho local (sem API)'
  task :motorista, %i[nome inicio fim csv] => :environment do |_t, args|
    nome   = args[:nome].to_s.strip
    inicio = args[:inicio].to_s.strip
    fim    = args[:fim].to_s.strip

    if nome.empty? || inicio.empty? || fim.empty?
      abort 'Uso: rake "entregas:motorista[NOME,YYYY-MM-DD,YYYY-MM-DD,/caminho/opcional.csv]"'
    end

    d1 = Date.parse(inicio)
    d2 = Date.parse(fim)
    abort 'Início é depois do fim.' if d1 > d2

    # planned_date = dia planejado; checkout = dia em que a entrega ocorreu.
    por_checkout = ENV['FONTE'].to_s.casecmp('checkout').zero?
    base = Entrega.da_conta_gade
    base = por_checkout ? base.no_periodo_checkout(d1, d2) : base.no_periodo(d1, d2)

    entregas = base.do_motorista(nome).order(:planned_date, :checkout).to_a

    if entregas.empty?
      puts "Nenhuma entrega de #{nome.inspect} entre #{d1.strftime('%d/%m/%Y')} e #{d2.strftime('%d/%m/%Y')}."
      # Nome quase certo é o erro mais comum aqui — mostrar o vizinho evita
      # concluir "o motorista não rodou" quando na verdade a grafia divergiu.
      alvo = nome.upcase
      parecidos = Entrega.motoristas_ativos(inicio: d1, fim: d2)
                         .select { |n| n.upcase.include?(alvo) || alvo.include?(n.upcase) }
      puts "Nomes parecidos no período: #{parecidos.inspect}" if parecidos.any?
      puts 'Rode: rake "entregas:motoristas[' + "#{d1},#{d2}" + ']" para ver a grafia exata.'
      next
    end

    eixo = por_checkout ? 'checkout (data real)' : 'planned_date (dia planejado)'
    puts "#{'─' * 104}"
    puts "#{entregas.size} entrega(s) de #{nome} · #{d1.strftime('%d/%m/%Y')} a #{d2.strftime('%d/%m/%Y')} · eixo: #{eixo}"
    puts '─' * 104
    printf("%-11s %-10s %-10s %-10s %-17s %-38s\n", 'DATA', 'NF', 'VEÍCULO', 'STATUS', 'CHECKOUT', 'DESTINO')
    entregas.each do |e|
      printf("%-11s %-10s %-10s %-10s %-17s %-38s\n",
             e.planned_date&.strftime('%d/%m/%Y').to_s,
             e.reference_id.to_s[0, 10],
             e.vehicle.to_s[0, 10],
             e.status.to_s[0, 10],
             e.checkout&.strftime('%d/%m %H:%M').to_s,
             e.local.to_s[0, 38])
    end
    puts '─' * 104

    por_status = entregas.group_by { |e| e.status.to_s }.transform_values(&:size)
    puts "Total: #{entregas.size}   " + por_status.sort_by { |_, n| -n }.map { |s, n| "#{s}=#{n}" }.join('  ')
    # "Atendidas" = foi ao local (sucesso OU insucesso) com checkout — é o
    # conjunto elegível da consolidação, e não o mesmo que "entregues".
    puts "Entregues (completed + checkout) ..... #{entregas.count { |e| e.concluida? && e.checkout_registrado? }}"
    puts "Insucessos (failed) .................. #{entregas.count(&:falhada?)}"
    puts "Atendidas (foi ao local c/ checkout) . #{entregas.count { |e| Entrega::STATUS_ATENDIDO.include?(e.status) && e.checkout_registrado? }}"
    puts "Dias com entrega ..................... #{entregas.map { |e| e.planned_date&.to_date }.compact.uniq.size}"
    puts "Veículos ............................. #{entregas.map(&:vehicle).compact.reject(&:empty?).uniq.join(', ')}"

    if args[:csv].present?
      require 'csv'
      CSV.open(args[:csv], 'w') do |csv|
        csv << ['Data planejada', 'NF', 'Tracking', 'Motorista', 'Veículo', 'Status', 'Checkout', 'Local', 'Endereço', 'Motivo']
        entregas.each do |e|
          csv << [e.planned_date, e.reference_id, e.tracking_id, e.driver, e.vehicle,
                  e.status, e.checkout, e.local, e.try(:address), e.try(:observation)]
        end
      end
      puts "\nCSV gravado em #{args[:csv]}"
    end
  end

  desc 'Motoristas que aparecem no espelho dentro do período (grafia exata + volume)'
  task :motoristas, %i[inicio fim] => :environment do |_t, args|
    abort 'Uso: rake "entregas:motoristas[YYYY-MM-DD,YYYY-MM-DD]"' if args[:inicio].blank? || args[:fim].blank?

    d1 = Date.parse(args[:inicio])
    d2 = Date.parse(args[:fim])

    contagem = Entrega.da_conta_gade.no_periodo(d1, d2)
                      .where.not(driver: [nil, '']).group(:driver).count

    if contagem.empty?
      puts "Nenhuma entrega no espelho entre #{d1.strftime('%d/%m/%Y')} e #{d2.strftime('%d/%m/%Y')}."
      next
    end

    puts "Motoristas · #{d1.strftime('%d/%m/%Y')} a #{d2.strftime('%d/%m/%Y')} (#{contagem.values.sum} entregas)"
    contagem.sort_by { |_, n| -n }.each { |nome, n| puts "  #{n.to_s.rjust(5)}  #{nome}" }
  end
end
