<?php

namespace Drupal\Tests\mailjet_api\Kernel;

use Drupal\KernelTests\KernelTestBase;

/**
 * Tests building of the mailjet message array.
 *
 * @group mailjet_api
 */
class MessageBodyBuilderTest extends KernelTestBase {

  /**
   * {@inheritdoc}
   */
  protected static $modules = [
    'system',
    'mailjet_api',
  ];

  /**
   * The Mailjet API mail handler.
   *
   * @var \Drupal\mailjet_api\MailjetApiHandlerInterface
   */
  protected $mailHandler;

  /**
   * {@inheritdoc}
   */
  protected function setUp(): void {
    parent::setUp();

    $this->installConfig('system');
    $this->installConfig('mailjet_api');
    $this->mailHandler = \Drupal::service('mailjet_api.mail_handler');
  }

  /**
   * Test the validation of From address in the message array.
   */
  public function testFromAddressValidation(): void {
    $validFromAddress = $this->randomMachineName() . '@drupal.org';
    $message = [
      'from' => $validFromAddress,
      'to' => $this->randomMachineName() . '@drupal.org',
      'subject' => $this->randomString(),
      'body' => $this->randomString(),
    ];

    // Validation success.
    $mailjetMessage = $this->mailHandler->buildMessagesBody($message);
    $this->assertEquals($validFromAddress, $mailjetMessage['Messages'][0]['From']['Email'], "Valid from address correctly inserted");

    $invalidFromAddress = $this->randomString();
    $message['from'] = $invalidFromAddress;
    $siteEmail = $this->randomMachineName() . '@drupal.org';
    $this->config('system.site')->set('mail', $siteEmail)->save();

    // Validation failure.
    $mailjetMessage = $this->mailHandler->buildMessagesBody($message);
    $this->assertEquals($siteEmail, $mailjetMessage['Messages'][0]['From']['Email'], "Invalid from address falls back to site address");
  }

  /**
   * Test the fallback or setting of From name in the message array.
   */
  public function testFromNameSettings(): void {
    $message = [
      'from' => $this->randomMachineName() . '@drupal.org',
      'to' => $this->randomMachineName() . '@drupal.org',
      'subject' => $this->randomString(),
      'body' => $this->randomString(),
    ];
    $siteName = $this->randomString();
    $this->config('system.site')->set('name', $siteName)->save();

    // Fallback to site name.
    $mailjetMessage = $this->mailHandler->buildMessagesBody($message);
    $this->assertEquals($siteName, $mailjetMessage['Messages'][0]['From']['Name'], "From name falls back to site name if not set.");

    $fromName = $this->randomString();
    $message['params']['from_name'] = $fromName;

    // Use from name set in message array.
    $mailjetMessage = $this->mailHandler->buildMessagesBody($message);
    $this->assertEquals($fromName, $mailjetMessage['Messages'][0]['From']['Name'], "From name correctly set.");

    $message['params']['from_name'] = '';

    // Unset the from name if the paramenter is empty.
    $mailjetMessage = $this->mailHandler->buildMessagesBody($message);
    $this->assertArrayNotHasKey('Name', $mailjetMessage['Messages'][0]['From'], "From name correctly unset.");
  }

  /**
   * Test the validation of To addresses in the message array.
   */
  public function testToAddressValidation(): void {
    $validToAddress1 = $this->randomMachineName() . '@drupal.org';
    $validToAddress2 = $this->randomMachineName() . '@drupal.org';
    $message = [
      'from' => $this->randomMachineName() . '@drupal.org',
      'to' => implode(',', [
        $this->randomString(),
        $validToAddress1,
        $this->randomString(),
        $validToAddress2,
        $this->randomString(),
      ]),
      'subject' => $this->randomString(),
      'body' => $this->randomString(),
    ];

    $mailjetMessage = $this->mailHandler->buildMessagesBody($message);
    $this->assertCount(2, $mailjetMessage['Messages'][0]['To'], "Invalid addresses removed from send array");
    $this->assertEquals($validToAddress1, $mailjetMessage['Messages'][0]['To'][0]['Email'], "Valid addressee correctly inserted");
    $this->assertEquals($validToAddress2, $mailjetMessage['Messages'][0]['To'][1]['Email'], "Valid addressee correctly inserted");
  }

  /**
   * Helper for the repetitive addressee tests.
   *
   * @param string $addresseeParam
   * @param string $messageParam
   */
  private function addresseeValidation(string $addresseeParam, string $messageParam): void {
    $validAddressee1 = $this->randomMachineName() . '@drupal.org';
    $validAddressee2 = $this->randomMachineName() . '@drupal.org';
    $message = [
      'from' => $this->randomMachineName() . '@drupal.org',
      'to' => $this->randomMachineName() . '@drupal.org',
      'subject' => $this->randomString(),
      'body' => $this->randomString(),
      'params' => [
        $addresseeParam => implode(',', [
          $this->randomString(),
          $validAddressee1,
          $this->randomString(),
          $validAddressee2,
          $this->randomString(),
        ]),
      ],
    ];

    $mailjetMessage = $this->mailHandler->buildMessagesBody($message);
    $this->assertCount(2, $mailjetMessage['Messages'][0][$messageParam], "Invalid addresses removed from send array");
    $this->assertEquals($validAddressee1, $mailjetMessage['Messages'][0][$messageParam][0]['Email'], "Valid addressee correctly inserted");
    $this->assertEquals($validAddressee2, $mailjetMessage['Messages'][0][$messageParam][1]['Email'], "Valid addressee correctly inserted");
  }

  /**
   * Test cc and bcc addressees.
   */
  public function testAddressees(): void {
    $this->addresseeValidation('cc', 'Cc');
    $this->addresseeValidation('cc_mail', 'Cc');
    $this->addresseeValidation('bcc', 'Bcc');
    $this->addresseeValidation('bcc_mail', 'Bcc');
  }

}
