<?php
/**
 * Email Notifications
 *
 * @author    Wpayme <hi@wpayme.com>
 * @copyright 2024-2025 Wpayme
 * @license   GPL-3.0-or-later
 * @package   Wpayme\WordPress\Pay\Forms
 */

namespace Wpayme\WordPress\Pay\Forms;

use Wpayme\WordPress\Pay\Payments\Payment;
use Wpayme\WordPress\Pay\Payments\PaymentStatus;

/**
 * Email Notifications class
 *
 * Handles email notifications for form payments
 */
class EmailNotifications {
    /**
     * Instance of this class.
     *
     * @var self
     */
    private static $instance;

    /**
     * Get instance of this class.
     *
     * @return self
     */
    public static function instance() {
        if (null === self::$instance) {
            self::$instance = new self();
        }

        return self::$instance;
    }

    /**
     * Constructor.
     */
    public function __construct() {
        // Hook into the payment status update actions for form payments
        \add_action('wpayme_payment_status_update', array($this, 'payment_status_update'), 10, 4);
        
        // Also hook specifically for our forms source
        \add_action('wpayme_payment_status_update_payment_form', array($this, 'payment_status_update'), 10, 4);
        
        // Rate limit hook
        \add_action('wpayme_pay_form_rate_limit_reached', array($this, 'handle_rate_limit'), 10, 2);
    }

    /**
     * Handle payment status updates
     *
     * @param Payment $payment         The payment object.
     * @param bool    $can_redirect    Whether redirection is allowed.
     * @param string  $previous_status The previous payment status.
     * @param string  $new_status      The new payment status.
     * @return void
     */
    public function payment_status_update($payment, $can_redirect, $previous_status, $new_status) {
        // Only process our payment form payments
        if (!in_array($payment->source, array('payment_form', 'payment-form', FormsSource::PAYMENT_FORM))) {
            return;
        }
        
        // Check the new status and handle the notification accordingly
        switch ($new_status) {
            case PaymentStatus::SUCCESS:
                $this->handle_payment_complete($payment);
                break;
                
            case PaymentStatus::FAILURE:
            case PaymentStatus::EXPIRED:
            case PaymentStatus::CANCELLED:
                $this->handle_payment_failed($payment);
                break;
                
            default:
                // No action for other statuses
                break;
        }
    }

    /**
     * Handle successful payment completion
     *
     * @param Payment $payment The payment object.
     * @return void
     */
    public function handle_payment_complete($payment) {
        $form_id = $payment->get_origin_id();
        
        if (empty($form_id)) {
            return;
        }
        
        // Check if buyer notifications are enabled
        $buyer_notifications_enabled = get_post_meta($form_id, '_wpayme_payment_form_enable_buyer_email', true) === 'yes';
        
        // Check if seller notifications are enabled
        $seller_notifications_enabled = get_post_meta($form_id, '_wpayme_payment_form_enable_seller_email', true) === 'yes';
        
        // Send notifications if enabled
        if ($buyer_notifications_enabled) {
            $this->send_buyer_success_email($payment);
        }
        
        if ($seller_notifications_enabled) {
            $this->send_seller_success_email($payment);
        }
        
        // Allow other plugins to hook into successful payment
        \do_action('wpayme_pay_form_payment_complete', $payment);
    }

    /**
     * Handle failed payment
     *
     * @param Payment $payment The payment object.
     * @return void
     */
    public function handle_payment_failed($payment) {
        $form_id = $payment->get_origin_id();
        
        if (empty($form_id)) {
            return;
        }
        
        // Check if failure notifications are enabled
        $failure_notifications_enabled = get_post_meta($form_id, '_wpayme_payment_form_enable_failure_email', true) === 'yes';
        
        if ($failure_notifications_enabled) {
            $this->send_failure_notification($payment);
        }
        
        // Allow other plugins to hook into failed payment
        \do_action('wpayme_pay_form_payment_failed', $payment);
    }

    /**
     * Handle rate limit reached
     *
     * @param int   $form_id The form ID.
     * @param array $data    Additional data about the rate limit event.
     * @return void
     */
    public function handle_rate_limit($form_id, $data) {
        $rate_limit_notifications_enabled = get_post_meta($form_id, '_wpayme_payment_form_enable_rate_limit_email', true) === 'yes';
        
        if ($rate_limit_notifications_enabled) {
            $this->send_rate_limit_notification($form_id, $data);
        }
        
        // Allow other plugins to hook into this event
        \do_action('wpayme_pay_form_rate_limit_processed', $form_id, $data);
    }

    /**
     * Send buyer success email
     *
     * @param Payment $payment The payment object.
     * @return void
     */
    private function send_buyer_success_email($payment) {
        $customer = $payment->get_customer();
        
        if (null === $customer || empty($customer->get_email())) {
            return;
        }
        
        $form_id = $payment->get_origin_id();
        $subject = get_post_meta($form_id, '_wpayme_payment_form_buyer_email_subject', true);
        $body = get_post_meta($form_id, '_wpayme_payment_form_buyer_email_body', true);
        $content_type = get_post_meta($form_id, '_wpayme_payment_form_email_content_type', true);
        
        if (empty($subject)) {
            /* translators: %s: Site name */
            $subject = sprintf(__('Payment Confirmation - %s', 'wpayme'), get_bloginfo('name'));
        }
        
        if (empty($body)) {
            $body = $this->get_default_buyer_email_body();
        }
        
        $content_type = empty($content_type) ? 'text/html' : $content_type;
        
        // Process the template
        $body = $this->process_email_template($body, $payment);
        
        // Send the email
        $this->send_email($customer->get_email(), $subject, $body, $content_type);
    }

    /**
     * Send seller success email
     *
     * @param Payment $payment The payment object.
     * @return void
     */
    private function send_seller_success_email($payment) {
        $form_id = $payment->get_origin_id();
        $to = get_post_meta($form_id, '_wpayme_payment_form_seller_email', true);
        
        if (empty($to)) {
            $to = get_option('admin_email');
        }
        
        $subject = get_post_meta($form_id, '_wpayme_payment_form_seller_email_subject', true);
        $body = get_post_meta($form_id, '_wpayme_payment_form_seller_email_body', true);
        $content_type = get_post_meta($form_id, '_wpayme_payment_form_email_content_type', true);
        
        if (empty($subject)) {
            /* translators: %s: Site name */
            $subject = sprintf(__('New Payment Received - %s', 'wpayme'), get_bloginfo('name'));
        }
        
        if (empty($body)) {
            $body = $this->get_default_seller_email_body();
        }
        
        $content_type = empty($content_type) ? 'text/html' : $content_type;
        
        // Process the template
        $body = $this->process_email_template($body, $payment);
        
        // Send the email
        $this->send_email($to, $subject, $body, $content_type);
    }

    /**
     * Send failure notification
     *
     * @param Payment $payment The payment object.
     * @return void
     */
    private function send_failure_notification($payment) {
        $form_id = $payment->get_origin_id();
        $to = get_post_meta($form_id, '_wpayme_payment_form_failure_email', true);
        
        if (empty($to)) {
            $to = get_option('admin_email');
        }
        
        $subject = get_post_meta($form_id, '_wpayme_payment_form_failure_email_subject', true);
        $body = get_post_meta($form_id, '_wpayme_payment_form_failure_email_body', true);
        $content_type = get_post_meta($form_id, '_wpayme_payment_form_email_content_type', true);
        
        if (empty($subject)) {
            /* translators: %s: Site name */
            $subject = sprintf(__('Payment Failed - %s', 'wpayme'), get_bloginfo('name'));
        }
        
        if (empty($body)) {
            $body = $this->get_default_failure_email_body();
        }
        
        $content_type = empty($content_type) ? 'text/html' : $content_type;
        
        // Process the template
        $body = $this->process_email_template($body, $payment);
        
        // Send the email
        $this->send_email($to, $subject, $body, $content_type);
        
        // Also notify buyer if they have an email
        $customer = $payment->get_customer();
        if (null !== $customer && !empty($customer->get_email())) {
            $buyer_failure_notifications_enabled = get_post_meta($form_id, '_wpayme_payment_form_enable_buyer_failure_email', true) === 'yes';
            
            if ($buyer_failure_notifications_enabled) {
                $buyer_subject = get_post_meta($form_id, '_wpayme_payment_form_buyer_failure_subject', true);
                $buyer_body = get_post_meta($form_id, '_wpayme_payment_form_buyer_failure_body', true);
                
                if (empty($buyer_subject)) {
                    /* translators: %s: Site name */
                    $buyer_subject = sprintf(__('Payment Failed - %s', 'wpayme'), get_bloginfo('name'));
                }
                
                if (empty($buyer_body)) {
                    $buyer_body = $this->get_default_buyer_failure_email_body();
                }
                
                $buyer_body = $this->process_email_template($buyer_body, $payment);
                
                $this->send_email($customer->get_email(), $buyer_subject, $buyer_body, $content_type);
            }
        }
    }

    /**
     * Send rate limit notification
     *
     * @param int   $form_id The form ID.
     * @param array $data    Additional data about the rate limit event.
     * @return void
     */
    private function send_rate_limit_notification($form_id, $data) {
        $to = get_post_meta($form_id, '_wpayme_payment_form_rate_limit_email', true);
        
        if (empty($to)) {
            $to = get_option('admin_email');
        }
        
        $subject = sprintf(
            /* translators: %d: Form ID */
            __('Rate Limit Reached - Form #%d', 'wpayme'),
            $form_id
        );
        $body = sprintf(
            /* translators: 1: Form ID, 2: Additional details */
            __('<p>The rate limit has been reached for payment form #%1$d.</p><p>Additional Details: %2$s</p>', 'wpayme'),
            $form_id,
            !empty($data) ? wp_json_encode($data) : __('No additional details available', 'wpayme')
        );
        
        // Send the email
        $this->send_email($to, $subject, $body);
    }

    /**
     * Send email
     *
     * @param string $to           Email recipient.
     * @param string $subject      Email subject.
     * @param string $body         Email body.
     * @param string $content_type Email content type.
     * @return bool
     */
    private function send_email($to, $subject, $body, $content_type = 'text/html') {
        // Set up headers
        $headers = array();
        
        if ('text/html' === $content_type) {
            $headers[] = 'Content-Type: text/html; charset=UTF-8';
        } else {
            $headers[] = 'Content-Type: text/plain; charset=UTF-8';
        }
        
        // Check if we should use async emails
        $use_async = \apply_filters('wpayme_pay_forms_use_async_emails', true);
        
        if ($use_async) {
            // Schedule the email to be sent asynchronously
            $email_data = array(
                'to' => $to,
                'subject' => $subject,
                'body' => $body,
                'headers' => $headers
            );
            
            wp_schedule_single_event(time(), 'wpayme_pay_async_email', array($email_data));
            
            return true;
        } else {
            // Send email immediately
            return \wp_mail($to, $subject, $body, $headers);
        }
    }

    /**
     * Process email template
     *
     * @param string  $template The email template.
     * @param Payment $payment  The payment object.
     * @return string
     */
    private function process_email_template($template, $payment) {
        $customer = $payment->get_customer();
        $form_id = $payment->get_origin_id();
        $form_title = get_the_title($form_id);
        
        // Basic replacement tags
        $replacements = array(
            '{site_name}' => get_bloginfo('name'),
            '{site_url}' => get_bloginfo('url'),
            '{payment_date}' => date_i18n(get_option('date_format') . ' ' . get_option('time_format'), current_time('timestamp')),
            '{payment_id}' => $payment->get_id(),
            '{transaction_id}' => $payment->get_transaction_id(),
            '{payment_amount}' => $payment->get_total_amount()->format_i18n(),
            '{payment_method}' => $payment->get_payment_method(),
            '{form_id}' => $form_id,
            '{form_title}' => $form_title,
            '{order_id}' => $payment->order_id,
        );
        
        // Add customer information if available
        if (null !== $customer) {
            $customer_name = $customer->get_name();
            $first_name = '';
            $last_name = '';
            
            if (null !== $customer_name) {
                $first_name = $customer_name->get_first_name();
                $last_name = $customer_name->get_last_name();
            }
            
            $replacements['{customer_first_name}'] = $first_name;
            $replacements['{customer_last_name}'] = $last_name;
            $replacements['{customer_full_name}'] = trim($first_name . ' ' . $last_name);
            $replacements['{customer_email}'] = $customer->get_email();
        }
        
        // Replace all tags
        foreach ($replacements as $tag => $value) {
            $template = str_replace($tag, $value, $template);
        }
        
        // Apply filters to allow extensions
        $template = \apply_filters('wpayme_pay_forms_email_template', $template, $payment);
        
        return $template;
    }

    /**
     * Get default buyer email body
     *
     * @return string
     */
    private function get_default_buyer_email_body() {
        $body = '<p>' . __('Dear {customer_first_name},', 'wpayme') . '</p>';
        $body .= '<p>' . __('Thank you for your payment. Your transaction has been completed successfully.', 'wpayme') . '</p>';
        $body .= '<p>' . __('Here are the details of your payment:', 'wpayme') . '</p>';
        $body .= '<ul>';
        $body .= '<li>' . __('Payment ID: {payment_id}', 'wpayme') . '</li>';
        $body .= '<li>' . __('Transaction ID: {transaction_id}', 'wpayme') . '</li>';
        $body .= '<li>' . __('Amount: {payment_amount}', 'wpayme') . '</li>';
        $body .= '<li>' . __('Payment Method: {payment_method}', 'wpayme') . '</li>';
        $body .= '<li>' . __('Date: {payment_date}', 'wpayme') . '</li>';
        $body .= '</ul>';
        $body .= '<p>' . __('Thank you for your business!', 'wpayme') . '</p>';
        $body .= '<p>' . __('Regards,', 'wpayme') . '<br/>{site_name}</p>';
        
        return $body;
    }

    /**
     * Get default seller email body
     *
     * @return string
     */
    private function get_default_seller_email_body() {
        $body = '<p>' . __('Hello,', 'wpayme') . '</p>';
        $body .= '<p>' . __('A new payment has been received through your payment form.', 'wpayme') . '</p>';
        $body .= '<p>' . __('Payment details:', 'wpayme') . '</p>';
        $body .= '<ul>';
        $body .= '<li>' . __('Form: {form_title} (ID: {form_id})', 'wpayme') . '</li>';
        $body .= '<li>' . __('Payment ID: {payment_id}', 'wpayme') . '</li>';
        $body .= '<li>' . __('Transaction ID: {transaction_id}', 'wpayme') . '</li>';
        $body .= '<li>' . __('Amount: {payment_amount}', 'wpayme') . '</li>';
        $body .= '<li>' . __('Payment Method: {payment_method}', 'wpayme') . '</li>';
        $body .= '<li>' . __('Date: {payment_date}', 'wpayme') . '</li>';
        $body .= '</ul>';
        $body .= '<p>' . __('Customer information:', 'wpayme') . '</p>';
        $body .= '<ul>';
        $body .= '<li>' . __('Name: {customer_full_name}', 'wpayme') . '</li>';
        $body .= '<li>' . __('Email: {customer_email}', 'wpayme') . '</li>';
        $body .= '</ul>';
        
        return $body;
    }

    /**
     * Get default failure email body
     *
     * @return string
     */
    private function get_default_failure_email_body() {
        $body = '<p>' . __('Hello,', 'wpayme') . '</p>';
        $body .= '<p>' . __('A payment has failed for your payment form.', 'wpayme') . '</p>';
        $body .= '<p>' . __('Payment details:', 'wpayme') . '</p>';
        $body .= '<ul>';
        $body .= '<li>' . __('Form: {form_title} (ID: {form_id})', 'wpayme') . '</li>';
        $body .= '<li>' . __('Payment ID: {payment_id}', 'wpayme') . '</li>';
        $body .= '<li>' . __('Amount: {payment_amount}', 'wpayme') . '</li>';
        $body .= '<li>' . __('Payment Method: {payment_method}', 'wpayme') . '</li>';
        $body .= '<li>' . __('Date: {payment_date}', 'wpayme') . '</li>';
        $body .= '</ul>';
        $body .= '<p>' . __('Customer information:', 'wpayme') . '</p>';
        $body .= '<ul>';
        $body .= '<li>' . __('Name: {customer_full_name}', 'wpayme') . '</li>';
        $body .= '<li>' . __('Email: {customer_email}', 'wpayme') . '</li>';
        $body .= '</ul>';
        
        return $body;
    }

    /**
     * Get default buyer failure email body
     *
     * @return string
     */
    private function get_default_buyer_failure_email_body() {
        $body = '<p>' . __('Dear {customer_first_name},', 'wpayme') . '</p>';
        $body .= '<p>' . __('We regret to inform you that your recent payment attempt was not successful.', 'wpayme') . '</p>';
        $body .= '<p>' . __('Payment details:', 'wpayme') . '</p>';
        $body .= '<ul>';
        $body .= '<li>' . __('Payment ID: {payment_id}', 'wpayme') . '</li>';
        $body .= '<li>' . __('Amount: {payment_amount}', 'wpayme') . '</li>';
        $body .= '<li>' . __('Date: {payment_date}', 'wpayme') . '</li>';
        $body .= '</ul>';
        $body .= '<p>' . __('Please try again or contact us if you need assistance.', 'wpayme') . '</p>';
        $body .= '<p>' . __('Regards,', 'wpayme') . '<br/>{site_name}</p>';
        
        return $body;
    }
} 