# Copyright (C) 2012-2024 Zammad Foundation, https://zammad-foundation.org/

require 'rails_helper'

RSpec.describe Whatsapp::Webhook::Message::Status::Failed, :aggregate_failures, current_user_id: 1 do
  describe '#process' do
    let(:channel) { create(:whatsapp_channel) }

    let(:from) do
      {
        phone: Faker::PhoneNumber.cell_phone_in_e164.delete('+'),
        name:  Faker::Name.unique.name,
      }
    end

    let(:error_code) { 131_047 }

    let(:json) do
      {
        object: 'whatsapp_business_account',
        entry:  [
          {
            id:      '244742992051543',
            changes: [
              {
                value: {
                  messaging_product: 'whatsapp',
                  metadata:          {
                    display_phone_number: '15551340563',
                    phone_number_id:      channel.options[:phone_number_id],
                  },
                  statuses:          [
                    {
                      id:           message_id,
                      status:       'failed',
                      timestamp:    '1708603746',
                      recipient_id: '15551340563',
                      errors:       [
                        {
                          code:       error_code,
                          title:      'Re-engagement message',
                          message:    'Re-engagement message',
                          error_data: {
                            details: 'Message failed to send because more than 24 hours have passed since the customer last replied to this number.'
                          },
                          href:       'https://developers.facebook.com/docs/whatsapp/cloud-api/support/error-codes/'
                        }
                      ]
                    }
                  ]
                },
                field: 'messages'
              }
            ]
          }
        ]
      }.to_json
    end

    let(:data) { JSON.parse(json).deep_symbolize_keys }

    let(:article) { create(:whatsapp_article, :inbound, ticket: ticket) }
    let(:ticket)  { create(:whatsapp_ticket, channel: channel) }

    let(:message_id) { article.message_id }

    context 'when all data is valid' do
      before { article }

      context 'with an recoverable error' do
        it 'creates an internal article with all error related information' do
          described_class.new(data:, channel:).process

          expect(Ticket::Article.last).to have_attributes(
            body:         "Unable to handle WhatsApp message: Re-engagement message (131047)\n\nMessage failed to send because more than 24 hours have passed since the customer last replied to this number.\n\nhttps://developers.facebook.com/docs/whatsapp/cloud-api/support/error-codes/",
            content_type: 'text/plain',
            internal:     true,
          )

          expect(channel.reload).to have_attributes(
            status_out:   nil,
            last_log_out: nil,
          )
        end
      end

      context 'with an unrecoverable error' do
        let(:error_code) { 0 }

        it 'creates an internal article with all error related information and updates the channel as well' do
          described_class.new(data:, channel:).process

          expect(channel.reload).to have_attributes(
            status_out:   'error',
            last_log_out: 'Re-engagement message (0)',
          )
        end
      end
    end

    context 'when no related article exists' do
      before { article }

      let(:message_id) { "wamid.#{Faker::Number.unique.number}" }

      it 'raises an error' do
        expect { described_class.new(data:, channel:).process }
          .to raise_error(
            an_instance_of(Whatsapp::Webhook::Payload::ProcessableError)
            .and(
              having_attributes(
                reason: 'No related article found to process the status message on.'
              )
            )
          )
      end
    end
  end
end