<?php
declare(strict_types=1);

use PharIo\Version\InvalidVersionException;

class Agro_MailTest {
  private $api_mail_test_protocol = API_MAIL_TEST_PROTOCOL ?? 'http';
  private $api_mail_test_url = API_MAIL_TEST_URL ?? 'localhost';
  private $api_mail_test_port = API_MAIL_TEST_PORT ?? 8025;
  private $api_mail_test_path = API_MAIL_TEST_PATH ?? 'api';
  private $api_mail_test_version = API_MAIL_TEST_VERSION ?? 'v1';
  private ?stdClass $payload = null;
  private $curl;

  public function __construct() {
    $this->payload = new stdClass();
  }

  /**
   * @param array - Array of attachments [['Content' => 'base64', 'Filename' => 'name']]
   * @return void
   */
  public function setAttachment(array $attachment) : void {
    
    if (!is_array($attachment) || empty($attachment)) {
      throw new InvalidArgumentException("Anexo não pode ser nulo.");
    }

    foreach ($attachment as $att) {
        if (!isset($att['Content']) || !isset($att['Filename'])) {
            throw new \InvalidArgumentException('Content ou Filename não podem ser nulos');
        }
        $this->payload->Attachments = [];
        $attch = new stdClass();
        $attch->Content = $att['Content'];
        $attch->Filename = $att['Filename'];
        array_push($this->payload->Attachments, $attch);
    }
  }

  /**
   * @param $code - String HTML message content
   * @return void
   */
  public function setHTML(string $code) : void {
    if ($code === null) {
      throw new \InvalidArgumentException("Html não pode ser nulo.");
    }
    if (!isset($this->payload->HTML) || !$this->payload->HTML instanceof stdClass){
    	$this->payload->HTML = new stdClass();
    }
    $this->payload->HTML = $code;
  }

  /**
   * @param $email - String mail address "from"
   * @param $name - String name "from"
   * @return void
   */
  public function setFrom(string $email, string $name) : void {
    if ($email === null || $name === null) {
      throw new \InvalidArgumentException("Email e name não podem ser nulos.");
    }
    if (!isset($this->payload->From) || !$this->payload->From instanceof stdClass){
    	$this->payload->From = new stdClass();
    }
    $this->payload->From->Email = $email;
    $this->payload->From->Name = $name;
  }

  /**
   * @param $subject - String subject of mail
   * @return void
   */
  public function setSubject(string $subject) : void {
    if ($subject === null) {
      throw new \InvalidArgumentException("Subject não pode ser nulo.");
    }
    $this->payload->Subject = $subject;
  }

  /**
   * @param $to - Array [['email' => '', 'name' => '']]
   * @return void
  */
  public function setTo(array $to) : void {
    foreach ($to as $dt) {
      if (!isset($dt['email']) ||
        !is_string($dt['email']) ||
        !isset($dt['name']) ||
        !is_string($dt['name']))
      {
        throw new \InvalidArgumentException("Email ou name não podem ser nulos.");
      }

      $this->payload->To = [];
      $obj = new stdClass();
      $obj->email = $dt['email'];
      $obj->name = $dt['name'];

      array_push($this->payload->To, $obj);
    }
  }

  public function setText(String $text) : void {
      if ($text === null) {
          throw new \InvalidArgumentException("Text não pode ser nulo.");
      }

      $this->payload->Text = $text;
  }

  /**
   * @return string json formatted
   */
  private function jsonFactory() : string {
    return json_encode($this->payload, JSON_PRETTY_PRINT);
  }

  /**
   * Create and configure cURL object
   * @param String $method
   * @throws Exception
   * @return void
   */
  private function curlFactory(String $method) : void {
    if ($method === '') {
      throw new \InvalidArgumentException("Parâmetro method não pode ser nulo.");
    }

    $url = $this->api_mail_test_protocol.'://'.
      $this->api_mail_test_url.':'.
      $this->api_mail_test_port.'/'.
      $this->api_mail_test_path.'/'.
      $this->api_mail_test_version.'/'.
      $method;
    
    try {
      $js = $this->jsonFactory();

      $this->curl = curl_init();
      curl_setopt($this->curl, CURLOPT_URL, $url);
      curl_setopt($this->curl, CURLOPT_RETURNTRANSFER, true);
      curl_setopt($this->curl, CURLOPT_POST, true);
      curl_setopt($this->curl, CURLOPT_POSTFIELDS, $js);
      curl_setopt($this->curl, CURLOPT_HTTPHEADER, [
        'Content-Type: application/json',
        'Content-Length: '. strlen($js),
        'Accept: application/json'
      ]);
    } catch (Throwable $e) {
      echo 'Erro ao configurar envio: ('.$e->getMessage().')';
    }
  }

  /**
   * Send mail to Mailpit by cURL POST calling
   * @throws Exception
   * @return void
   */
  public function send() {
    $this->curlFactory('send');
    try {
      if (!$result = curl_exec($this->curl)) {
        throw new Exception("Ocorreu erro ao enviar e-mail: ".curl_error($this->curl));
      }
      curl_close($this->curl);
      return $result;
    } catch (Exception $e) {
      echo 'Erro ao enviar e-mail: ('.$e->getMessage().')';
    }
  }
}
