class Captain::Tools::GeneratePixTool < BaseTool
  def name
    'generate_pix'
  end

  def description
    'Generates a Pix payment for the ACTIVE DRAFT reservation. Returns a structured object with formatted_message and raw_payload.'
  end

  def tool_parameters_schema
    {
      type: 'object',
      properties: {
        amount: {
          type: 'number',
          description: 'Opcional. Valor final exato para cobrar no Pix. Se informado, atualiza o valor da reserva antes de gerar.'
        }
      }
    }
  end

  def execute(*args, **params)
    actual_params = resolve_params(args, params)
    input_amount = actual_params[:amount].to_s.gsub(/[^\d,.]/, '').tr(',', '.')
    override_amount = input_amount.to_f if input_amount.present? && input_amount.to_f.positive?

    # ... (Validation Logic) ...
    # 1. Validate Contact Info
    contact = @conversation.contact
    return error_response('Erro: CPF não cadastrado. Use a ferramenta de atualizar contato primeiro.') if contact.custom_attributes['cpf'].blank?
    return error_response('Erro: Nome não cadastrado. Use a ferramenta de atualizar contato primeiro.') if contact.name.blank?

    pending = Captain::Reservation.where(conversation_id: @conversation.id, status: 'pending_payment').last
    if pending
      # [AMOUT CHECK]
      # If an explicit amount was passed, but we found a pending charge with different amount,
      # we should probably CANCEL/EXPIRE the old one and generate a new one.
      if override_amount && (pending.total_amount.to_f - override_amount).abs > 0.1
        Rails.logger.info "[GeneratePixTool] Montante mudou (#{pending.total_amount} -> #{override_amount}). Forçando novo Pix."
        pending.update!(total_amount: override_amount)

        # Expire old charges
        Captain::PixCharge.where(reservation_id: pending.id).update_all(status: 'expired')
        return generate_new_pix(pending, prefix: "Atualizei o valor para R$ #{format('%.2f', override_amount)}. Novo Pix abaixo:")
      end

      charge = current_pix_charge_for(pending)
      if charge&.pix_copia_e_cola.present?
        if charge.expired? || charge.expired_by_time?
          charge.update!(status: 'expired') unless charge.expired?
          return generate_new_pix(pending, prefix: 'Pix expirado. Gerando um novo agora.')
        end

        return build_pix_response(charge, pending,
                                  prefix: 'Pix ainda válido. Segue abaixo para pagamento:')
      end

      return generate_new_pix(pending, prefix: 'Nenhuma cobrança ativa encontrada. Gerando um novo Pix.')
    end

    reservation = Captain::Reservation.where(conversation_id: @conversation.id, status: 'draft')
                                      .where('updated_at > ?', 2.hours.ago)
                                      .order(created_at: :desc)
                                      .first

    unless reservation
      return error_response('Erro: Nenhuma intenção de reserva recente (últimas 2h) encontrada. Por favor, confirme a suíte e o valor novamente usando "Quero reservar".')
    end

    # [AMOUNT OVERRIDE]
    if override_amount
      Rails.logger.info "[GeneratePixTool] Atualizando valor da reserva #{reservation.id} de #{reservation.total_amount} para #{override_amount} antes de gerar Pix."
      reservation.update!(total_amount: override_amount)
    end

    Rails.logger.info "[GeneratePixTool] Usando Reserva ID #{reservation.id} | Valor no Banco: #{reservation.total_amount}"
    generate_new_pix(reservation)
  end

  private

  def error_response(msg)
    { formatted_message: msg, success: false }
  end

  def current_pix_charge_for(reservation)
    return nil unless reservation
    return reservation.current_pix_charge if reservation.respond_to?(:current_pix_charge)

    Captain::PixCharge.where(reservation_id: reservation.id).order(created_at: :desc).first
  end

  def generate_new_pix(reservation, prefix: nil)
    service = Captain::Inter::CobService.new(reservation)
    charge = service.call

    # Force status update to make it visible in Admin Panel immediately
    reservation.update!(status: 'pending_payment')
    Rails.logger.info "[GeneratePixTool] Reserva #{reservation.id} movida para pending_payment"

    final_prefix = prefix || 'Cobrança Pix gerada com sucesso.'
    build_pix_response(charge, reservation, prefix: final_prefix)
  rescue StandardError => e
    Rails.logger.error "[GeneratePixTool] Falha ao gerar Pix: #{e.message}"
    error_response('Erro técnico ao gerar o Pix. Por favor, tente novamente em alguns instantes.')
  end

  def build_pix_response(charge, reservation, prefix: nil)
    intro = prefix.present? ? "#{prefix}\n\n" : ''

    # [Architecture Update] One-Tap Copy Link (SGID)
    # Fix: Ensure host is reachable (localhost instead of 0.0.0.0 for local dev) and instruct LLM to NOT use Markdown.
    base_url = ENV.fetch('FRONTEND_URL', 'https://app.chatwoot.com')
    base_url = base_url.gsub('0.0.0.0', '127.0.0.1') if base_url.include?('0.0.0.0')

    token = charge.to_sgid(expires_in: 2.hours, purpose: :pix_payment).to_s
    link = Rails.application.routes.url_helpers.short_payment_link_url(token, host: base_url)

    instructions = "Para facilitar, gerei um link de pagamento rápido com botão COPIAR.\n" \
                   "1. Clique no link abaixo\n" \
                   "2. Aperte 'COPIAR CÓDIGO PIX'\n" \
                   "3. Cole no app do seu banco e pague.\n\n" \
                   "Link Seguro: #{link}\n\n" \
                   '(IMPORTANTE PARA A I.A.: Envie este link EXATAMENTE como está acima. NÃO use formatação Markdown [texto](url) NEM coloque entre colchetes [url]. O WhatsApp não reconhece. Envie APENAS a URL pura, solta no texto.)'

    # Fallback raw payload in case the user asks for it explicitly later (hidden from formatted msg by default now)
    final_code = charge.pix_copia_e_cola.to_s.strip
    if final_code.start_with?('/spi/')
      header = '00020101021226930014BR.GOV.BCB.PIX2571spi-qrcode.bancointer.com.br'
      final_code = "#{header}#{final_code}"
    end

    full_message = "#{intro}#{instructions}"

    {
      formatted_message: full_message,
      raw_payload: final_code, # Kept for debugging/fallback
      payment_link: link,
      amount: reservation.total_amount.to_f,
      reservation_id: reservation.id,
      success: true
    }
  end
end
