<?php

namespace Vendtics\App\Mail;

defined( 'ABSPATH' ) || exit;

use Vendtics\WpMVC\View\View;

abstract class Mailer {
    /**
     * @var array List of email headers.
     */
    public array $headers = [];

    /**
     * @var string Recipient email address.
     */
    protected string $to;

    /**
     * @var string Email subject.
     */
    protected string $subject;

    /**
     * @var string Email body content.
     */
    protected string $body;

    /**
     * @var string Email content type, defaulting to 'text/html'.
     */
    private string $content_type = 'text/html';

    /**
     * Get the recipient email address.
     *
     * @return string Recipient email address.
     */
    public function get_to(): string {
        return $this->to;
    }

    /**
     * Set the recipient email address.
     *
     * @param string $to Recipient email address.
     *
     * @return self Returns the current instance for method chaining.
     */
    public function set_to( string $to ): self {
        $this->to = $to;
        return $this;
    }

    /**
     * Get the email subject.
     *
     * @return string Email subject.
     */
    public function get_subject(): string {
        return $this->subject;
    }

    /**
     * Set the email subject.
     *
     * @param string $subject Email subject.
     *
     * @return self Returns the current instance for method chaining.
     */
    public function set_subject( string $subject ): self {
        $this->subject = $subject;
        return $this;
    }

    /**
     * Get the email body content.
     *
     * @return string Email body content.
     */
    public function get_body(): string {
        return $this->body;
    }

    /**
     * Set the email body content.
     *
     * @param string $body Email body content.
     *
     * @return self Returns the current instance for method chaining.
     */
    public function set_body( string $body ): self {
        $this->body = $body;
        return $this;
    }

    /**
     * Add or update a header in the email headers.
     *
     * @param string $key   Header name.
     * @param string $value Header value.
     *
     * @return self Returns the current instance for method chaining.
     */
    public function push_header( string $key, string $value ): self {
        $this->headers[] = "{$key}: {$value}";
        return $this;
    }

    /**
     * Remove a header from the email headers.
     *
     * @param string $key Header name to remove.
     *
     * @return self Returns the current instance for method chaining.
     */
    public function remove_header( string $key ): self {
        $this->headers = array_filter(
            $this->headers, function ( $header ) use ( $key ) {
                return stripos( $header, "{$key}:" ) !== 0;
            }
        );
        return $this;
    }

    /**
     * Send the email.
     *
     * This method sends an email using the wp_mail function and triggers
     * WordPress hooks before and after the email is sent.
     * 
     * @param mixed ...$args Additional arguments to pass to the hooks.
     * 
     * @return bool True if the email was sent successfully, false otherwise.
     */
    public function send( ...$args ): bool {
        // Trigger an action before sending the email, allowing developers to modify or cancel the process.
        do_action( 'vendtics_before_sending_email', $args );

        // Prepare email headers, including the content type.
        $headers   = $this->headers;
        $headers[] = "Content-Type: {$this->content_type}";

        $settings_repository = vendtics_settings_repository();
        $email_settings      = $settings_repository->get_settings()['email'];

        // Add the from name and email to the email headers.
        if ( ! empty( $email_settings['from_name'] ) && ! empty( $email_settings['from_email'] ) ) {
            $headers[] = "From: {$email_settings['from_name']} <{$email_settings['from_email']}>";
        }

        // Prepare the email body content.
        $body = $this->get_body();

        // Send the email using the wp_mail function.
        $email = wp_mail( $this->to, $this->get_subject(), View::get( 'classic-email', compact( 'body' ) ), $headers );

        // Trigger an action after the email is sent, passing the result and any additional arguments.
        do_action( 'vendtics_after_sending_email', $email, ...$args );

        return $email;
    }
}