#!/usr/bin/env ruby
# frozen_string_literal: true
#
# Sonda a API do SimpliRoute para descobrir se dá para ALTERAR as fotos de uma
# visita. A documentação oficial não diz — este script responde na prática.
#
# Rode NO SERVIDOR (é lá que vive o SIMPLIROUTE_TOKEN):
#
#   # 1) Leitura — não muda nada. Comece sempre por aqui.
#   SIMPLIROUTE_TOKEN=xxx bin/sondar_fotos_simpliroute --visita 871407488
#
#   # 2) Teste de escrita — adiciona uma foto de teste e RESTAURA em seguida.
#   SIMPLIROUTE_TOKEN=xxx bin/sondar_fotos_simpliroute --visita 871407488 --testar-escrita
#
# Para achar o id numérico de uma visita: é o mesmo que a tela "Editar
# Lançamento" mostra em "Visita <id>" depois de buscar pela NF.
#
# ⚠️ O teste de escrita mexe numa visita REAL. Use uma visita de teste ou uma
# entrega antiga/sem importância. O valor original é impresso antes de qualquer
# alteração e a restauração roda em `ensure` — se algo falhar, dá para refazer
# na mão com o JSON impresso.

require 'net/http'
require 'json'
require 'uri'

BASE  = ENV.fetch('SIMPLIROUTE_BASE_URL', 'https://api.simpliroute.com')
TOKEN = ENV['SIMPLIROUTE_TOKEN'].to_s

# URL pública qualquer, só para ver se a API aceita o campo. Não é baixada por nós.
URL_TESTE = 'https://via.placeholder.com/64.png#sondagem-reem'

def sair(msg)
  warn msg
  exit 1
end

sair('Defina SIMPLIROUTE_TOKEN no ambiente.') if TOKEN.empty?

visita_id = nil
testar_escrita = false
ARGV.each_with_index do |a, i|
  visita_id = ARGV[i + 1] if a == '--visita'
  testar_escrita = true   if a == '--testar-escrita'
end
sair('Uso: bin/sondar_fotos_simpliroute --visita <id> [--testar-escrita]') if visita_id.to_s.empty?

def requisicao(metodo, caminho, corpo = nil)
  uri = URI.join(BASE, caminho)
  req = case metodo
        when :get   then Net::HTTP::Get.new(uri)
        when :patch then Net::HTTP::Patch.new(uri)
        end
  req['Authorization'] = "Token #{TOKEN}"
  req['Content-Type']  = 'application/json'
  req['Accept']        = 'application/json'
  req.body = corpo.to_json if corpo

  res = Net::HTTP.start(uri.host, uri.port, use_ssl: uri.scheme == 'https',
                                            open_timeout: 10, read_timeout: 30) { |h| h.request(req) }
  body = begin
    res.body.to_s.empty? ? nil : JSON.parse(res.body)
  rescue JSON::ParserError
    res.body
  end
  [res.code.to_i, body]
end

def titulo(t)
  puts "\n#{'─' * 66}\n#{t}\n#{'─' * 66}"
end

# ── 1. Leitura: o que cada endpoint devolve de imagem ────────────────────────
# As fotos REAIS do motorista ficam em extra_field_values (foto_nf,
# foto_prova_visita, ...). O array `pictures` costuma ter só 1 imagem genérica.
titulo("1. GET /v1/routes/visits/#{visita_id}/  (endpoint de escrita)")
cod, visita = requisicao(:get, "/v1/routes/visits/#{visita_id}/")
sair("Falhou (HTTP #{cod}): #{visita.inspect}") unless cod == 200

efv_orig = visita['extra_field_values'].is_a?(Hash) ? visita['extra_field_values'] : {}
puts "  status .............. #{visita['status'].inspect}"
puts "  reference (NF) ...... #{visita['reference'].inspect}"
puts "  pictures ............ #{Array(visita['pictures']).size} item(ns) (genéricas)"
puts "  signature ........... #{visita['signature'].inspect}"
puts "  extra_field_values .. #{efv_orig.size} campo(s) — AQUI estão as fotos reais:"
efv_orig.each { |campo, url| puts "     #{campo.ljust(20)} #{url.nil? ? '(vazio)' : url}" }

titulo("2. GET /v1/plans/visits/#{visita_id}/detail/  (POD — costuma ser + completo)")
cod_d, detalhe = requisicao(:get, "/v1/plans/visits/#{visita_id}/detail/")
if cod_d == 200 && detalhe.is_a?(Hash)
  efv_det = detalhe['extra_field_values'].is_a?(Hash) ? detalhe['extra_field_values'] : {}
  puts "  extra_field_values .. #{efv_det.size} campo(s):"
  efv_det.each { |campo, url| puts "     #{campo.ljust(20)} #{url.nil? ? '(vazio)' : url}" }
else
  puts "  Indisponível (HTTP #{cod_d}) — a galeria segue só com a visita."
end

unless testar_escrita
  titulo('Leitura concluída — nada foi alterado')
  puts '  Para descobrir se dá para GRAVAR foto, rode de novo com --testar-escrita'
  puts '  (de preferência numa visita de teste/antiga).'
  exit 0
end

# ── 3. Escrita: mexe num campo VAZIO e restaura ──────────────────────────────
# Alvo: um campo de foto que esteja vazio (por padrão foto_termo). Assim o teste
# NÃO sobrescreve nenhuma foto real — só preenche um espaço em branco e desfaz.
# Ao gravar, mandamos o dict INTEIRO (a API pode substituir o objeto todo).
titulo('3. TESTE DE ESCRITA — PATCH extra_field_values')

alvo = efv_orig.key?('foto_termo') && efv_orig['foto_termo'].nil? ? 'foto_termo' :
       efv_orig.find { |_c, v| v.nil? }&.first
if alvo.nil?
  sair('  Nenhum campo de foto vazio nesta visita — para não sobrescrever uma ' \
       'foto real, escolha outra visita (com foto_termo vazio) para o teste.')
end

puts "  Campo-alvo (vazio) .. #{alvo}"
puts "  extra_field_values ORIGINAL (guarde p/ restaurar na mão, se precisar):"
puts "  #{efv_orig.to_json}"

veredito = 'INDEFINIDO'
begin
  novo = efv_orig.merge(alvo => URL_TESTE)
  cod_p, resp = requisicao(:patch, "/v1/routes/visits/#{visita_id}/", { 'extra_field_values' => novo })
  puts "\n  PATCH respondeu HTTP #{cod_p}"

  if cod_p != 200
    veredito = 'NÃO É POSSÍVEL — a API recusou o PATCH'
    puts "  corpo: #{resp.inspect[0, 400]}"
  else
    # 200 não basta: a API pode aceitar e ignorar o campo silenciosamente.
    _, confere = requisicao(:get, "/v1/routes/visits/#{visita_id}/")
    atual = confere['extra_field_values'].is_a?(Hash) ? confere['extra_field_values'] : {}
    persistiu = atual[alvo] == URL_TESTE
    veredito = persistiu ? 'É POSSÍVEL — o valor de teste persistiu no campo de foto' :
                           'NÃO — a API respondeu 200 mas IGNOROU extra_field_values'
    puts "  #{alvo} após o PATCH: #{atual[alvo].inspect}"
  end
ensure
  # Restaura sempre, mesmo se algo acima estourar.
  titulo('4. RESTAURANDO o valor original')
  cod_r, = requisicao(:patch, "/v1/routes/visits/#{visita_id}/", { 'extra_field_values' => efv_orig })
  _, final = requisicao(:get, "/v1/routes/visits/#{visita_id}/")
  restaurado = final['extra_field_values'].is_a?(Hash) ? final['extra_field_values'] : {}
  ok = restaurado[alvo].to_s == efv_orig[alvo].to_s && restaurado[alvo] != URL_TESTE
  puts "  PATCH de restauração: HTTP #{cod_r}"
  puts(ok ? "  ✔ Restaurado — #{alvo} voltou a #{efv_orig[alvo].inspect}." :
            "  ✘ ATENÇÃO: confira manualmente. Agora #{alvo} = #{restaurado[alvo].inspect}")
end

titulo("VEREDITO: #{veredito}")
puts <<~FIM
  Se deu "É POSSÍVEL", dá para implementar substituir/remover/adicionar foto:
  a edição é um PATCH em extra_field_values (o campo certo: foto_nf, foto_termo,
  foto_prova_visita, ...). Falta só resolver ONDE hospedar a imagem nova — o app
  ainda não tem ActiveStorage com migrations/storage.yml, então a foto enviada
  pelo ADM precisa virar uma URL pública antes do PATCH.

  Se deu "NÃO", a alteração terá de ser feita pela interface web do SimpliRoute.
  Vale confirmar o caminho de upload com contact@simpliroute.com.
FIM
