<?php

namespace Inoby;

require_once INOBY_BASE . "/inoby-plugins/contact-form/inc/class-validator.php";

class ContactForm {
  /**
   * Array with response data
   */
  private array $response = [
    "status" => "",
    "message" => "",
    "errors" => [],
  ];

  /**
   * Handle incoming request. Validate form inputs,
   * compose and attempt to send email. If somtehing
   * goes wrong, notify user with error messages.
   */
  public function handle() {
    // validate fields
    $errors = $this->validate_request();

    // validation not successful -> send errors to frontend
    if (!empty($errors)) {
      $this->response["errors"] = $errors;
      $this->response["status"] = "error";
      $this->response["message"] = __("Nastala chyba\nSkontrolujte formulár.", "inoby");

      $this->send_response(400);
    }

    // get recipient email from db
    $to = rwmb_meta("contact_form_email_to", ["object_type" => "setting"], "options");

    // recipient email not provided -> send error to frontend
    if (empty($to)) {
      $this->error();
    }

    // Compose email
    $subject = __("Nová správa od", "inoby") . " " . $_POST["name"];
    $message = $_POST["message"];
    $sender = $_POST["name"] . "<" . $_POST["email"] . ">";
    $headers = ["Cc:" . $sender, "Reply-To:" . $sender];

    add_action("wp_mail_failed", [$this, "error"]);
    add_action("wp_mail_succeeded", [$this, "success"]);
    // send email -> success/fail is handled by wp_mail_succeded and wp_mail_failed hooks
    wp_mail($to, $subject, $message, $headers);
    // remove hooks not to interfere with other wp mails
    remove_action("wp_mail_failed", [$this, "error"]);
    remove_action("wp_mail_succeeded", [$this, "success"]);

    // something went wrong with success/fail hooks -> email state is unknown -> send error to frontend
    $this->error();
  }

  /**
   * Email sent successfully. Send success response to user.
   */
  public function success($mail_data) {
    $this->response = [
      "status" => "success",
      "message" => __("Email bol úspešne odoslaný.", "inoby"),
    ];

    $this->send_response();
  }

  /**
   * Error occured. Send error response to user.
   */
  public function error($error = null) {
    $this->response = [
      "status" => "error",
      "message" => __("Nastal problém pri posielaní emailu.\nSkúste to znova neskôr.", "inoby"),
    ];

    $this->send_response(502);
  }

  /**
   * Validate incoming request
   */
  private function validate_request() {
    // initialize validator
    $validator = new \Inoby\Validator([
      "message" => "required",
      "name" => "required",
      "email" => ["required", "email"],
      "gdpr" => "required",
    ]);

    // set field names for error messages
    $validator->set_fields_names([
      "message" => "správa",
      "name" => "meno",
    ]);

    // validate request
    return $validator->validate();
  }

  /**
   * Send response to user
   */
  private function send_response(int $status_code = 200) {
    wp_send_json($this->response, $status_code);
    wp_die();
  }

  /**
   * Get template part with contact form
   *
   * @param array $args Optional arguments passed to template part.
   *              Arguments "class" and "textarea-rows" are supported
   * @return void
   */
  public static function template(array $args = []) {
    if (self::config_is_valid()) {
      get_template_part("template-parts/contact-form", null, $args);
    }
  }

  /**
   * Check config for required SMTP constants.
   * Print undefined constants if WP_DEBUG set to true
   *
   * @return bool True if check passed, false otherwise
   */
  public static function config_is_valid(): bool {
    $required_constants = ["SMTP_USER", "SMTP_PASS", "SMTP_HOST", "SMTP_FROM", "SMTP_NAME", "SMTP_PORT", "SMTP_SECURE", "SMTP_AUTH", "SMTP_DEBUG"];
    $is_valid = true;

    // check each required constant
    foreach ($required_constants as $i => $constant) {
      if (!defined($constant)) {
        // print errors if in debug mode
        if (defined("WP_DEBUG") && WP_DEBUG) {
          // first error found -> print heading
          if ($is_valid) {
            echo "<b>SMTP config check failed!</b><br>Define these constant in wp-config.php to use contact form:<br><br>";
          }
          // print undefined constant
          echo " [\"" . $constant . "\"]" . "<br>";
        }

        $is_valid = false;
      }
    }

    return $is_valid;
  }
}
