<?php
/**
 * Email Provider Configuration and Management
 * 
 * Handles configuration and sending emails through various email service providers
 * including AWS SES, Mailgun, Resend, SendGrid, and Google SMTP. This class provides a unified interface
 * for email operations across the Guard Dog plugin.
 *
 * @package GuardDog
 * @since 1.8.0
 */

if (!defined('ABSPATH')) {
    exit; // Exit if accessed directly
}

class Guard_Dog_Email_Provider {

    /**
     * Prefix used to identify encrypted sensitive settings values.
     */
    private const ENCRYPTED_PREFIX = '{gd:enc}';

    /**
     * Supported Google authentication modes.
     */
    private const GOOGLE_AUTH_MODE_APP_PASSWORD = 'app_password';
    private const GOOGLE_AUTH_MODE_OAUTH = 'oauth';

    /**
     * Available email providers
     * @var array
     */
    const PROVIDERS = [
        'aws_ses' => [
            'name' => 'Amazon SES',
            'description' => 'Amazon Simple Email Service',
            'fields' => [
                'aws_access_key_id' => [
                    'label' => 'AWS Access Key ID',
                    'type' => 'text',
                    'required' => true,
                    'description' => 'Your AWS access key ID'
                ],
                'aws_secret_access_key' => [
                    'label' => 'AWS Secret Access Key',
                    'type' => 'password',
                    'required' => true,
                    'description' => 'Your AWS secret access key'
                ],
                'aws_region' => [
                    'label' => 'AWS Region',
                    'type' => 'select',
                    'required' => true,
                    'options' => [
                        'us-east-1' => 'US East (N. Virginia)',
                        'us-east-2' => 'US East (Ohio)',
                        'us-west-1' => 'US West (N. California)',
                        'us-west-2' => 'US West (Oregon)',
                        'eu-west-1' => 'Europe (Ireland)',
                        'eu-central-1' => 'Europe (Frankfurt)',
                        'ap-southeast-1' => 'Asia Pacific (Singapore)',
                        'ap-southeast-2' => 'Asia Pacific (Sydney)',
                        'ap-northeast-1' => 'Asia Pacific (Tokyo)'
                    ],
                    'default' => 'us-east-1'
                ],
                'aws_ses_from_email' => [
                    'label' => 'From Email Address',
                    'type' => 'email',
                    'required' => true,
                    'description' => 'Verified email address in SES'
                ]
            ]
        ],
        'mailgun' => [
            'name' => 'Mailgun',
            'description' => 'Mailgun Email Service',
            'fields' => [
                'mailgun_api_key' => [
                    'label' => 'Mailgun API Key',
                    'type' => 'password',
                    'required' => true,
                    'description' => 'Your Mailgun API key'
                ],
                'mailgun_domain' => [
                    'label' => 'Mailgun Domain',
                    'type' => 'text',
                    'required' => true,
                    'description' => 'Your verified Mailgun domain'
                ],
                'mailgun_from_email' => [
                    'label' => 'From Email Address',
                    'type' => 'email',
                    'required' => true,
                    'description' => 'Email address to send from'
                ]
            ]
        ],
        'resend' => [
            'name' => 'Resend',
            'description' => 'Resend Email Service',
            'fields' => [
                'resend_api_key' => [
                    'label' => 'Resend API Key',
                    'type' => 'password',
                    'required' => true,
                    'description' => 'Your Resend API key'
                ],
                'resend_from_email' => [
                    'label' => 'From Email Address',
                    'type' => 'email',
                    'required' => true,
                    'description' => 'Email address to send from'
                ]
            ]
        ],
        'sendgrid' => [
            'name' => 'SendGrid',
            'description' => 'Twilio SendGrid Email Service',
            'fields' => [
                'sendgrid_api_key' => [
                    'label' => 'SendGrid API Key',
                    'type' => 'password',
                    'required' => true,
                    'description' => 'Your SendGrid API key (starts with SG.)'
                ],
                'sendgrid_from_email' => [
                    'label' => 'From Email Address',
                    'type' => 'email',
                    'required' => true,
                    'description' => 'Verified sender email address in SendGrid'
                ]
            ]
        ],
        'google' => [
            'name' => 'Google',
            'description' => 'Gmail and Google Workspace (OAuth or SMTP App Password)',
            'fields' => [
                'google_auth_mode' => [
                    'label' => 'Authentication Mode',
                    'type' => 'select',
                    'required' => true,
                    'options' => [
                        'oauth' => 'OAuth (Recommended)',
                        'app_password' => 'App Password (Legacy)'
                    ],
                    'default' => 'oauth',
                    'description' => 'Use OAuth for future compatibility, or App Password for legacy SMTP setups.'
                ],
                'google_auth_email' => [
                    'label' => 'Google Account Email (Auth User)',
                    'type' => 'email',
                    'required' => false,
                    'description' => 'Mailbox used to authenticate with Google. If empty, From Email is used.'
                ],
                'google_from_email' => [
                    'label' => 'From Email Address',
                    'type' => 'email',
                    'required' => true,
                    'description' => 'Email address recipients will see in the From header (alias supported if configured in Gmail Send mail as).'
                ],
                'google_from_name' => [
                    'label' => 'From Name (Optional)',
                    'type' => 'text',
                    'required' => false,
                    'description' => 'Display name for the From address.'
                ],
                'google_app_password' => [
                    'label' => 'App Password',
                    'type' => 'password',
                    'required' => false,
                    'description' => 'Used only for App Password mode. Generate at myaccount.google.com/apppasswords.'
                ],
                'google_oauth_client_id' => [
                    'label' => 'OAuth Client ID',
                    'type' => 'text',
                    'required' => false,
                    'description' => 'Paste the OAuth Client ID from Google Cloud Console. This tells Google which website is requesting permission.'
                ],
                'google_oauth_client_secret' => [
                    'label' => 'OAuth Client Secret',
                    'type' => 'password',
                    'required' => false,
                    'description' => 'Paste the matching OAuth Client Secret from Google Cloud Console. Guard Dog stores it securely.'
                ],
                'google_oauth_refresh_token' => [
                    'label' => 'OAuth Refresh Token',
                    'type' => 'password',
                    'required' => false,
                    'description' => 'Usually filled in automatically after you click Connect Google Account. Guard Dog uses it to mint short-lived access tokens.'
                ]
            ]
        ]
    ];

    /**
     * Current provider configuration
     * @var array
     */
    private $config;

    /**
     * Constructor
     */
    public function __construct() {
        $this->load_configuration();
        $this->add_hooks();
    }

    /**
     * Add WordPress hooks for global email override.
     *
     * @since 1.9.0
     * @return void
     */
    private function add_hooks() {
        // Hook into wp_mail to intercept all WordPress emails if global override is enabled
        add_filter('pre_wp_mail', [$this, 'handle_wp_mail'], 10, 2);
    }

    /**
     * Load email provider configuration from WordPress options
     */
    private function load_configuration() {
        $this->config = [
            'provider' => get_option('guard_dog_email_provider', ''),
            'settings' => get_option('guard_dog_email_provider_settings', [])
        ];
    }

    /**
     * Get available providers
     *
     * @return array
     */
    public function get_available_providers() {
        return self::PROVIDERS;
    }

    /**
     * Get current provider
     *
     * @return string
     */
    public function get_current_provider() {
        return $this->config['provider'];
    }

    /**
     * Get provider configuration
     *
     * @param string $provider Provider key
     * @return array|null
     */
    public function get_provider_config($provider = null) {
        if ($provider === null) {
            $provider = $this->get_current_provider();
        }
        
        return isset(self::PROVIDERS[$provider]) ? self::PROVIDERS[$provider] : null;
    }

    /**
     * Get provider settings
     *
     * @return array
     */
    public function get_provider_settings() {
        return $this->config['settings'];
    }

    /**
     * Sanitize provider settings payload.
     *
     * @param string $provider Provider key.
     * @param array $input Submitted settings payload.
     * @param array $existing_settings Existing stored settings.
     * @return array
     */
    public static function sanitize_provider_settings($provider, $input, $existing_settings = []) {
        if (!is_array($input)) {
            return [];
        }

        $provider = is_string($provider) ? $provider : '';
        $field_configs = [];
        if (!empty($provider) && isset(self::PROVIDERS[$provider]['fields']) && is_array(self::PROVIDERS[$provider]['fields'])) {
            $field_configs = self::PROVIDERS[$provider]['fields'];
        }

        $sanitized = [];

        foreach ($input as $key => $value) {
            $sanitized_key = sanitize_text_field((string) $key);
            $raw_value = is_scalar($value) ? (string) $value : '';
            $field_config = $field_configs[$sanitized_key] ?? [];
            $field_type = $field_config['type'] ?? 'text';

            if ($field_type === 'password') {
                $sanitized_value = sanitize_text_field($raw_value);
                $is_obfuscated = !empty($sanitized_value) && preg_match('/^•+$/u', $sanitized_value);

                if ($is_obfuscated && isset($existing_settings[$sanitized_key])) {
                    $sanitized[$sanitized_key] = (string) $existing_settings[$sanitized_key];
                    continue;
                }

                if (self::is_sensitive_provider_field($provider, $sanitized_key)) {
                    $sanitized[$sanitized_key] = self::encrypt_sensitive_value($sanitized_value);
                    continue;
                }

                $sanitized[$sanitized_key] = $sanitized_value;
                continue;
            }

            if ($field_type === 'email') {
                $sanitized[$sanitized_key] = sanitize_email($raw_value);
                continue;
            }

            if ($field_type === 'select') {
                $selected_value = sanitize_key($raw_value);
                $options = isset($field_config['options']) && is_array($field_config['options']) ? $field_config['options'] : [];
                if (!empty($options) && !isset($options[$selected_value])) {
                    $selected_value = isset($field_config['default']) ? sanitize_key((string) $field_config['default']) : (string) array_key_first($options);
                }
                $sanitized[$sanitized_key] = $selected_value;
                continue;
            }

            $sanitized[$sanitized_key] = sanitize_text_field($raw_value);
        }

        return $sanitized;
    }

    /**
     * Encrypt a sensitive setting value for storage.
     *
     * @param string $plaintext Plain value.
     * @return string
     */
    public static function encrypt_sensitive_value($plaintext) {
        $plaintext = (string) $plaintext;

        if ($plaintext === '') {
            return '';
        }

        if (strpos($plaintext, self::ENCRYPTED_PREFIX) === 0) {
            return $plaintext;
        }

        if (!defined('AUTH_KEY') || !defined('AUTH_SALT')) {
            return $plaintext;
        }

        $key = hash('sha256', AUTH_KEY, true);
        $iv = substr(hash('sha256', AUTH_SALT, true), 0, 16);
        $encrypted = openssl_encrypt($plaintext, 'aes-256-cbc', $key, 0, $iv);

        if ($encrypted === false) {
            return $plaintext;
        }

        return self::ENCRYPTED_PREFIX . $encrypted;
    }

    /**
     * Decrypt a sensitive setting value from storage.
     *
     * @param string $stored Stored value.
     * @return string
     */
    public static function decrypt_sensitive_value($stored) {
        $stored = (string) $stored;

        if ($stored === '') {
            return '';
        }

        if (strpos($stored, self::ENCRYPTED_PREFIX) !== 0) {
            return $stored;
        }

        if (!defined('AUTH_KEY') || !defined('AUTH_SALT')) {
            return '';
        }

        $key = hash('sha256', AUTH_KEY, true);
        $iv = substr(hash('sha256', AUTH_SALT, true), 0, 16);
        $encrypted = substr($stored, strlen(self::ENCRYPTED_PREFIX));
        $decrypted = openssl_decrypt($encrypted, 'aes-256-cbc', $key, 0, $iv);

        if ($decrypted === false) {
            return '';
        }

        return $decrypted;
    }

    /**
     * Check whether a provider field should be encrypted at rest.
     *
     * @param string $provider Provider key.
     * @param string $field_key Settings key.
     * @return bool
     */
    private static function is_sensitive_provider_field($provider, $field_key) {
        if ($provider !== 'google') {
            return false;
        }

        return in_array($field_key, [
            'google_app_password',
            'google_oauth_client_secret',
            'google_oauth_refresh_token',
        ], true);
    }

    /**
     * Check if email provider is configured
     *
     * @return bool
     */
    public function is_configured() {
        $provider = $this->get_current_provider();
        if (empty($provider) || !isset(self::PROVIDERS[$provider])) {
            return false;
        }

        $settings = $this->get_provider_settings();
        return $this->validate_provider_settings($provider, $settings);
    }

    /**
     * Send email using the configured provider
     *
     * @param string $to Recipient email address
     * @param string $subject Email subject
     * @param string $message Email message (HTML)
     * @param string $text_message Optional plain text version
     * @return array Result array with 'success' boolean and 'message' string
     */
    public function send_email($to, $subject, $message, $text_message = '') {
        if (!$this->is_configured()) {
            return [
                'success' => false,
                'message' => __('Email provider is not properly configured.', 'guard-dog')
            ];
        }

        $provider = $this->get_current_provider();
        $settings = $this->get_provider_settings();

        try {
            switch ($provider) {
                case 'aws_ses':
                    return $this->send_via_aws_ses($to, $subject, $message, $text_message, $settings);
                case 'mailgun':
                    return $this->send_via_mailgun($to, $subject, $message, $text_message, $settings);
                case 'resend':
                    return $this->send_via_resend($to, $subject, $message, $text_message, $settings);
                case 'sendgrid':
                    return $this->send_via_sendgrid($to, $subject, $message, $text_message, $settings);
                case 'google':
                    return $this->send_via_google($to, $subject, $message, $text_message, $settings);
                default:
                    return [
                        'success' => false,
                        'message' => __('Unsupported email provider.', 'guard-dog')
                    ];
            }
        } catch (Exception $e) {
            // Log the error
            if (function_exists('Guard_Dog') && Guard_Dog()->debug) {
                Guard_Dog()->debug->error('Email sending failed: ' . $e->getMessage(), 'email_provider');
            }

            return [
                'success' => false,
                'message' => __('Failed to send email. Please check your configuration.', 'guard-dog')
            ];
        }
    }



    /**
     * Send email via AWS SES
     *
     * @param string $to Recipient email
     * @param string $subject Email subject
     * @param string $message HTML message
     * @param string $text_message Plain text message
     * @param array $settings Provider settings
     * @return array
     */
    private function send_via_aws_ses($to, $subject, $message, $text_message, $settings) {
        $request = $this->build_aws_ses_request($to, $subject, $message, $text_message, $settings);

        $response = wp_remote_post($request['url'], [
            'headers' => $request['headers'],
            'body' => $request['body'],
            'timeout' => 30
        ]);

        if (is_wp_error($response)) {
            return [
                'success' => false,
                'message' => 'AWS SES Error: ' . $response->get_error_message()
            ];
        }

        $response_code = (int) wp_remote_retrieve_response_code($response);
        $response_body = wp_remote_retrieve_body($response);

        if ($response_code >= 200 && $response_code < 300) {
            $message_id = $this->parse_aws_ses_message_id($response_body);

            return [
                'success' => true,
                'message' => __('Email sent successfully via AWS SES.', 'guard-dog'),
                'message_id' => $message_id
            ];
        }

        return [
            'success' => false,
            'message' => 'AWS SES Error: ' . $this->parse_aws_ses_error_message($response_body, $response_code)
        ];
    }

    /**
     * Build a signed Amazon SES Query API request.
     *
     * @param string $to Recipient email.
     * @param string $subject Email subject.
     * @param string $message HTML message.
     * @param string $text_message Plain text message.
     * @param array $settings Provider settings.
     * @param int|null $timestamp Optional Unix timestamp for deterministic tests.
     * @return array Request URL, headers, and body.
     */
    private function build_aws_ses_request($to, $subject, $message, $text_message, $settings, $timestamp = null) {
        $region = sanitize_key($settings['aws_region']);
        $host = sprintf('email.%s.amazonaws.com', $region);
        $url = 'https://' . $host . '/';
        $content_type = 'application/x-www-form-urlencoded; charset=utf-8';
        $body = $this->build_aws_ses_request_body($to, $subject, $message, $text_message, $settings);
        $amz_date = $timestamp === null ? gmdate('Ymd\THis\Z') : gmdate('Ymd\THis\Z', $timestamp);
        $date_stamp = substr($amz_date, 0, 8);
        $credential_scope = $date_stamp . '/' . $region . '/ses/aws4_request';
        $signed_headers = 'content-type;host;x-amz-date';
        $payload_hash = hash('sha256', $body);

        $canonical_headers = 'content-type:' . $content_type . "\n"
            . 'host:' . $host . "\n"
            . 'x-amz-date:' . $amz_date . "\n";

        $canonical_request = "POST\n/\n\n"
            . $canonical_headers . "\n"
            . $signed_headers . "\n"
            . $payload_hash;

        $string_to_sign = "AWS4-HMAC-SHA256\n"
            . $amz_date . "\n"
            . $credential_scope . "\n"
            . hash('sha256', $canonical_request);

        $signing_key = $this->get_aws_signature_key($settings['aws_secret_access_key'], $date_stamp, $region, 'ses');
        $signature = hash_hmac('sha256', $string_to_sign, $signing_key);

        $authorization_header = 'AWS4-HMAC-SHA256 '
            . 'Credential=' . $settings['aws_access_key_id'] . '/' . $credential_scope . ', '
            . 'SignedHeaders=' . $signed_headers . ', '
            . 'Signature=' . $signature;

        return [
            'url' => $url,
            'headers' => [
                'Authorization' => $authorization_header,
                'Content-Type' => $content_type,
                'Host' => $host,
                'X-Amz-Date' => $amz_date
            ],
            'body' => $body
        ];
    }

    /**
     * Build the Amazon SES SendEmail form body.
     *
     * @param string $to Recipient email.
     * @param string $subject Email subject.
     * @param string $message HTML message.
     * @param string $text_message Plain text message.
     * @param array $settings Provider settings.
     * @return string
     */
    private function build_aws_ses_request_body($to, $subject, $message, $text_message, $settings) {
        $params = [
            'Action' => 'SendEmail',
            'Destination.ToAddresses.member.1' => $to,
            'Message.Body.Html.Charset' => 'UTF-8',
            'Message.Body.Html.Data' => $message,
            'Message.Subject.Charset' => 'UTF-8',
            'Message.Subject.Data' => $subject,
            'Source' => $settings['aws_ses_from_email'],
            'Version' => '2010-12-01'
        ];

        if (!empty($text_message)) {
            $params['Message.Body.Text.Charset'] = 'UTF-8';
            $params['Message.Body.Text.Data'] = $text_message;
        }

        ksort($params);

        return http_build_query($params, '', '&', PHP_QUERY_RFC3986);
    }

    /**
     * Create an AWS Signature Version 4 signing key.
     *
     * @param string $secret_key AWS secret access key.
     * @param string $date_stamp Date in Ymd format.
     * @param string $region AWS region.
     * @param string $service AWS service name.
     * @return string Binary signing key.
     */
    private function get_aws_signature_key($secret_key, $date_stamp, $region, $service) {
        $date_key = hash_hmac('sha256', $date_stamp, 'AWS4' . $secret_key, true);
        $region_key = hash_hmac('sha256', $region, $date_key, true);
        $service_key = hash_hmac('sha256', $service, $region_key, true);

        return hash_hmac('sha256', 'aws4_request', $service_key, true);
    }

    /**
     * Parse a successful Amazon SES SendEmail response.
     *
     * @param string $response_body XML response body.
     * @return string|null
     */
    private function parse_aws_ses_message_id($response_body) {
        if (preg_match('/<MessageId>([^<]+)<\/MessageId>/', $response_body, $matches)) {
            return html_entity_decode($matches[1], ENT_QUOTES | ENT_XML1, 'UTF-8');
        }

        return null;
    }

    /**
     * Parse an Amazon SES error response.
     *
     * @param string $response_body XML response body.
     * @param int $response_code HTTP status code.
     * @return string
     */
    private function parse_aws_ses_error_message($response_body, $response_code) {
        $code = '';
        $message = '';

        if (preg_match('/<Code>([^<]+)<\/Code>/', $response_body, $matches)) {
            $code = html_entity_decode($matches[1], ENT_QUOTES | ENT_XML1, 'UTF-8');
        }

        if (preg_match('/<Message>([^<]+)<\/Message>/', $response_body, $matches)) {
            $message = html_entity_decode($matches[1], ENT_QUOTES | ENT_XML1, 'UTF-8');
        }

        if ($code !== '' && $message !== '') {
            return $code . ': ' . $message;
        }

        if ($message !== '') {
            return $message;
        }

        return sprintf(__('HTTP %d from Amazon SES.', 'guard-dog'), $response_code);
    }

    /**
     * Send email via Mailgun
     *
     * @param string $to Recipient email
     * @param string $subject Email subject
     * @param string $message HTML message
     * @param string $text_message Plain text message
     * @param array $settings Provider settings
     * @return array
     */
    private function send_via_mailgun($to, $subject, $message, $text_message, $settings) {
        $url = "https://api.mailgun.net/v3/{$settings['mailgun_domain']}/messages";
        
        $data = [
            'from' => $settings['mailgun_from_email'],
            'to' => $to,
            'subject' => $subject,
            'html' => $message
        ];

        if (!empty($text_message)) {
            $data['text'] = $text_message;
        }

        $response = wp_remote_post($url, [
            'headers' => [
                'Authorization' => 'Basic ' . base64_encode('api:' . $settings['mailgun_api_key'])
            ],
            'body' => $data,
            'timeout' => 30
        ]);

        if (is_wp_error($response)) {
            return [
                'success' => false,
                'message' => 'Mailgun Error: ' . $response->get_error_message()
            ];
        }

        $response_code = wp_remote_retrieve_response_code($response);
        $response_body = wp_remote_retrieve_body($response);

        if ($response_code === 200) {
            return [
                'success' => true,
                'message' => __('Email sent successfully via Mailgun.', 'guard-dog')
            ];
        } else {
            return [
                'success' => false,
                'message' => 'Mailgun Error: HTTP ' . $response_code . ' - ' . $response_body
            ];
        }
    }

    /**
     * Send email via Resend
     *
     * @param string $to Recipient email
     * @param string $subject Email subject
     * @param string $message HTML message
     * @param string $text_message Plain text message
     * @param array $settings Provider settings
     * @return array
     */
    private function send_via_resend($to, $subject, $message, $text_message, $settings) {
        // Rate limiting: Resend allows 2 requests per second
        // Use transient to track last send time and throttle if needed
        $last_send_key = 'guard_dog_resend_last_send';
        $last_send_time = get_transient($last_send_key);
        
        if ($last_send_time !== false) {
            $time_since_last_send = microtime(true) - $last_send_time;
            // If less than 0.5 seconds since last send, wait
            if ($time_since_last_send < 0.5) {
                $wait_time = (0.5 - $time_since_last_send) * 1000000; // Convert to microseconds
                usleep((int) $wait_time);
            }
        }
        
        // Update last send time
        set_transient($last_send_key, microtime(true), 2); // Expire after 2 seconds
        
        $url = 'https://api.resend.com/emails';
        
        $data = [
            'from' => $settings['resend_from_email'],
            'to' => [$to],
            'subject' => $subject,
            'html' => $message
        ];

        if (!empty($text_message)) {
            $data['text'] = $text_message;
        }

        $response = wp_remote_post($url, [
            'headers' => [
                'Authorization' => 'Bearer ' . $settings['resend_api_key'],
                'Content-Type' => 'application/json'
            ],
            'body' => wp_json_encode($data),
            'timeout' => 30
        ]);

        if (is_wp_error($response)) {
            return [
                'success' => false,
                'message' => 'Resend Error: ' . $response->get_error_message()
            ];
        }

        $response_code = wp_remote_retrieve_response_code($response);
        $response_body = wp_remote_retrieve_body($response);

        if ($response_code === 201 || $response_code === 200) {
            $response_data = json_decode($response_body, true);
            
            // Check if the response contains an ID (success indicator)
            if (isset($response_data['id'])) {
                // Log successful send
                if (function_exists('Guard_Dog') && Guard_Dog()->debug) {
                    Guard_Dog()->debug->info('Resend email sent successfully', 'email_provider', [
                        'to' => $to,
                        'subject' => $subject,
                        'message_id' => $response_data['id'],
                    ]);
                }
                return [
                    'success' => true,
                    'message' => __('Email sent successfully via Resend.', 'guard-dog'),
                    'message_id' => $response_data['id']
                ];
            }
        }
        
        // Handle rate limiting (429) - retry after delay
        if ($response_code === 429) {
            // Wait 0.6 seconds and retry once
            usleep(600000); // 0.6 seconds in microseconds
            
            // Retry the request
            $retry_response = wp_remote_post($url, [
                'headers' => [
                    'Authorization' => 'Bearer ' . $settings['resend_api_key'],
                    'Content-Type' => 'application/json'
                ],
                'body' => wp_json_encode($data),
                'timeout' => 30
            ]);
            
            $retry_code = wp_remote_retrieve_response_code($retry_response);
            $retry_body = wp_remote_retrieve_body($retry_response);
            
            if ($retry_code === 201 || $retry_code === 200) {
                $retry_data = json_decode($retry_body, true);
                if (isset($retry_data['id'])) {
                    if (function_exists('Guard_Dog') && Guard_Dog()->debug) {
                        Guard_Dog()->debug->info('Resend email sent successfully after rate limit retry', 'email_provider', [
                            'to' => $to,
                            'subject' => $subject,
                            'message_id' => $retry_data['id'],
                        ]);
                    }
                    return [
                        'success' => true,
                        'message' => __('Email sent successfully via Resend (after rate limit retry).', 'guard-dog'),
                        'message_id' => $retry_data['id']
                    ];
                }
            }
        }
        
        // If we get here, it's an error - parse error message if available
        $error_message = 'Resend Error: HTTP ' . $response_code;
        $response_data = json_decode($response_body, true);
        
        // Parse error details
        $error_details = [];
        if (is_array($response_data)) {
            if (isset($response_data['message'])) {
                $error_message .= ' - ' . $response_data['message'];
                $error_details['api_message'] = $response_data['message'];
            }
            if (isset($response_data['errors']) && is_array($response_data['errors'])) {
                $error_details['api_errors'] = $response_data['errors'];
                $error_message .= ' - Errors: ' . wp_json_encode($response_data['errors']);
            }
        } elseif (!empty($response_body)) {
            // If response isn't JSON, include first 500 chars of body
            $error_details['raw_response'] = substr($response_body, 0, 500);
            $error_message .= ' - ' . substr($response_body, 0, 500);
        }
        
        // Log the error with details
        if (function_exists('Guard_Dog') && Guard_Dog()->debug) {
            Guard_Dog()->debug->warning('Resend API error', 'email_provider', [
                'response_code' => $response_code,
                'error_message' => $error_message,
                'error_details' => $error_details,
                'from_email' => $settings['resend_from_email'] ?? 'not set',
                'to' => $to,
                'subject' => $subject,
            ]);
        }
        
        return [
            'success' => false,
            'message' => $error_message
        ];
    }

    /**
     * Send email via SendGrid
     *
     * @since 1.9.31
     * @param string $to Recipient email
     * @param string $subject Email subject
     * @param string $message HTML message
     * @param string $text_message Plain text message
     * @param array $settings Provider settings
     * @return array
     */
    private function send_via_sendgrid($to, $subject, $message, $text_message, $settings) {
        $url = 'https://api.sendgrid.com/v3/mail/send';

        $content = [
            [
                'type'  => 'text/html',
                'value' => $message,
            ],
        ];

        if (!empty($text_message)) {
            // Plain text must come before HTML in the content array
            array_unshift($content, [
                'type'  => 'text/plain',
                'value' => $text_message,
            ]);
        }

        $data = [
            'personalizations' => [
                [
                    'to' => [
                        ['email' => $to],
                    ],
                ],
            ],
            'from'    => ['email' => $settings['sendgrid_from_email']],
            'subject' => $subject,
            'content' => $content,
        ];

        $response = wp_remote_post($url, [
            'headers' => [
                'Authorization' => 'Bearer ' . $settings['sendgrid_api_key'],
                'Content-Type'  => 'application/json',
            ],
            'body'    => wp_json_encode($data),
            'timeout' => 30,
        ]);

        if (is_wp_error($response)) {
            if (function_exists('Guard_Dog') && Guard_Dog()->debug) {
                Guard_Dog()->debug->error('SendGrid request failed', 'email_provider', [
                    'to'    => $to,
                    'error' => $response->get_error_message(),
                ]);
            }

            return [
                'success' => false,
                'message' => 'SendGrid Error: ' . $response->get_error_message(),
            ];
        }

        $response_code = wp_remote_retrieve_response_code($response);

        // SendGrid returns 202 Accepted on success (empty body)
        if ($response_code === 202) {
            $message_id = wp_remote_retrieve_header($response, 'x-message-id');

            if (function_exists('Guard_Dog') && Guard_Dog()->debug) {
                Guard_Dog()->debug->info('SendGrid email sent successfully', 'email_provider', [
                    'to'         => $to,
                    'subject'    => $subject,
                    'message_id' => $message_id,
                ]);
            }

            return [
                'success'    => true,
                'message'    => __('Email sent successfully via SendGrid.', 'guard-dog'),
                'message_id' => $message_id ?: null,
            ];
        }

        // Parse error response
        $response_body = wp_remote_retrieve_body($response);
        $error_message = 'SendGrid Error: HTTP ' . $response_code;
        $response_data = json_decode($response_body, true);

        if (is_array($response_data) && isset($response_data['errors']) && is_array($response_data['errors'])) {
            $error_details = array_map(function ($err) {
                return $err['message'] ?? '';
            }, $response_data['errors']);
            $error_message .= ' - ' . implode('; ', array_filter($error_details));
        }

        if (function_exists('Guard_Dog') && Guard_Dog()->debug) {
            Guard_Dog()->debug->warning('SendGrid API error', 'email_provider', [
                'response_code' => $response_code,
                'error_message' => $error_message,
                'to'            => $to,
                'subject'       => $subject,
            ]);
        }

        return [
            'success' => false,
            'message' => $error_message,
        ];
    }

    /**
     * Send email via Google provider using the selected auth mode.
     *
     * @since 1.9.31
     * @param string $to Recipient email
     * @param string $subject Email subject
     * @param string $message HTML message
     * @param string $text_message Plain text message
     * @param array $settings Provider settings
     * @return array
     */
    private function send_via_google($to, $subject, $message, $text_message, $settings) {
        $auth_mode = $this->get_google_auth_mode($settings);

        if ($auth_mode === self::GOOGLE_AUTH_MODE_OAUTH) {
            return $this->send_via_google_oauth($to, $subject, $message, $text_message, $settings);
        }

        return $this->send_via_google_app_password($to, $subject, $message, $text_message, $settings);
    }

    /**
     * Send email via Google SMTP with App Password authentication.
     *
     * @param string $to Recipient email
     * @param string $subject Email subject
     * @param string $message HTML message
     * @param string $text_message Plain text message
     * @param array $settings Provider settings
     * @return array
     */
    private function send_via_google_app_password($to, $subject, $message, $text_message, $settings) {
        if (!class_exists('PHPMailer\PHPMailer\PHPMailer')) {
            require_once ABSPATH . WPINC . '/PHPMailer/PHPMailer.php';
            require_once ABSPATH . WPINC . '/PHPMailer/SMTP.php';
            require_once ABSPATH . WPINC . '/PHPMailer/Exception.php';
        }

        $from_email = isset($settings['google_from_email']) ? (string) $settings['google_from_email'] : '';
        $from_name = isset($settings['google_from_name']) ? (string) $settings['google_from_name'] : '';
        $auth_email = isset($settings['google_auth_email']) ? (string) $settings['google_auth_email'] : '';
        if ($auth_email === '') {
            $auth_email = $from_email;
        }
        $app_password = self::decrypt_sensitive_value((string) ($settings['google_app_password'] ?? ''));

        try {
            $phpmailer = new \PHPMailer\PHPMailer\PHPMailer(true);

            // SMTP configuration for Google
            $phpmailer->isSMTP();
            $phpmailer->Host       = 'smtp.gmail.com';
            $phpmailer->SMTPAuth   = true;
            $phpmailer->Username   = $auth_email;
            $phpmailer->Password   = $app_password;
            $phpmailer->SMTPSecure = \PHPMailer\PHPMailer\PHPMailer::ENCRYPTION_STARTTLS;
            $phpmailer->Port       = 587;
            $phpmailer->CharSet    = 'UTF-8';
            $phpmailer->Timeout    = 30;

            // Sender and recipient
            $phpmailer->setFrom($from_email, $from_name);
            $phpmailer->addAddress($to);

            // Content
            $phpmailer->isHTML(true);
            $phpmailer->Subject = $subject;
            $phpmailer->Body    = $message;
            $phpmailer->AltBody = !empty($text_message) ? $text_message : $this->extract_plain_text($message);

            $phpmailer->send();

            if (function_exists('Guard_Dog') && Guard_Dog()->debug) {
                Guard_Dog()->debug->info('Google SMTP email sent successfully', 'email_provider', [
                    'to' => $to,
                    'subject' => $subject,
                    'message_id' => $phpmailer->getLastMessageID(),
                    'from_email' => $from_email,
                    'auth_email' => $auth_email,
                ]);
            }

            return [
                'success'    => true,
                'message'    => __('Email sent successfully via Google SMTP.', 'guard-dog'),
                'message_id' => $phpmailer->getLastMessageID(),
            ];
        } catch (\PHPMailer\PHPMailer\Exception $e) {
            $error_message = 'Google SMTP Error: ' . $e->getMessage();
            if (stripos($e->getMessage(), 'Sender address rejected') !== false || stripos($e->getMessage(), 'not owned by user') !== false) {
                $error_message = __('Google rejected the From address. Confirm this alias is configured in Gmail "Send mail as" for the authenticated account.', 'guard-dog');
            }

            if (function_exists('Guard_Dog') && Guard_Dog()->debug) {
                Guard_Dog()->debug->error('Google SMTP send failed', 'email_provider', [
                    'to' => $to,
                    'subject' => $subject,
                    'error' => $e->getMessage(),
                    'from_email' => $from_email,
                    'auth_email' => $auth_email,
                ]);
            }

            return [
                'success' => false,
                'message' => $error_message,
            ];
        }
    }

    /**
     * Send email via Gmail API using OAuth refresh token.
     *
     * @param string $to Recipient email
     * @param string $subject Email subject
     * @param string $message HTML message
     * @param string $text_message Plain text message
     * @param array $settings Provider settings
     * @return array
     */
    private function send_via_google_oauth($to, $subject, $message, $text_message, $settings) {
        $token_result = $this->get_google_oauth_access_token($settings);
        if (empty($token_result['success'])) {
            return [
                'success' => false,
                'message' => $token_result['message'] ?? __('Google OAuth authentication failed.', 'guard-dog'),
            ];
        }

        $from_email = isset($settings['google_from_email']) ? (string) $settings['google_from_email'] : '';
        $from_name = isset($settings['google_from_name']) ? (string) $settings['google_from_name'] : '';
        $raw_message = $this->build_google_raw_message($to, $subject, $message, $text_message, $from_email, $from_name);
        if ($raw_message === '') {
            return [
                'success' => false,
                'message' => __('Failed to prepare Google OAuth message payload.', 'guard-dog'),
            ];
        }

        $response = wp_remote_post('https://gmail.googleapis.com/gmail/v1/users/me/messages/send', [
            'headers' => [
                'Authorization' => 'Bearer ' . $token_result['access_token'],
                'Content-Type' => 'application/json',
            ],
            'body' => wp_json_encode([
                'raw' => $raw_message,
            ]),
            'timeout' => 30,
        ]);

        if (is_wp_error($response)) {
            return [
                'success' => false,
                'message' => 'Google OAuth Error: ' . $response->get_error_message(),
            ];
        }

        $status = wp_remote_retrieve_response_code($response);
        $body = wp_remote_retrieve_body($response);
        $data = json_decode($body, true);

        if ($status >= 200 && $status < 300) {
            if (function_exists('Guard_Dog') && Guard_Dog()->debug) {
                Guard_Dog()->debug->info('Google OAuth email sent successfully', 'email_provider', [
                    'to' => $to,
                    'subject' => $subject,
                    'message_id' => $data['id'] ?? null,
                    'from_email' => $from_email,
                ]);
            }

            return [
                'success' => true,
                'message' => __('Email sent successfully via Google OAuth.', 'guard-dog'),
                'message_id' => $data['id'] ?? null,
            ];
        }

        $api_error = is_array($data) ? ($data['error']['message'] ?? '') : '';
        $error_message = 'Google OAuth Error: HTTP ' . $status;
        if ($api_error !== '') {
            $error_message .= ' - ' . $api_error;
        }

        if (stripos($api_error, 'Invalid From header') !== false || stripos($api_error, 'from header') !== false) {
            $error_message = __('Google rejected the From address. Confirm this alias is configured in Gmail "Send mail as" for the connected account.', 'guard-dog');
        }

        if (function_exists('Guard_Dog') && Guard_Dog()->debug) {
            Guard_Dog()->debug->error('Google OAuth send failed', 'email_provider', [
                'to' => $to,
                'subject' => $subject,
                'status' => $status,
                'api_error' => $api_error,
                'from_email' => $from_email,
            ]);
        }

        return [
            'success' => false,
            'message' => $error_message,
        ];
    }

    /**
     * Exchange refresh token for a short-lived Google OAuth access token.
     *
     * @param array $settings Google provider settings.
     * @return array
     */
    private function get_google_oauth_access_token($settings) {
        $client_id = isset($settings['google_oauth_client_id']) ? trim((string) $settings['google_oauth_client_id']) : '';
        $client_secret = self::decrypt_sensitive_value((string) ($settings['google_oauth_client_secret'] ?? ''));
        $refresh_token = self::decrypt_sensitive_value((string) ($settings['google_oauth_refresh_token'] ?? ''));

        if ($client_id === '' || $client_secret === '' || $refresh_token === '') {
            return [
                'success' => false,
                'message' => __('Google OAuth credentials are incomplete.', 'guard-dog'),
            ];
        }

        $cache_key = 'guard_dog_google_oauth_access_' . md5($client_id . '|' . $refresh_token);
        $cached = get_transient($cache_key);
        if (is_array($cached) && !empty($cached['token']) && !empty($cached['expires_at']) && (int) $cached['expires_at'] > (time() + 60)) {
            return [
                'success' => true,
                'access_token' => (string) $cached['token'],
            ];
        }

        $response = wp_remote_post('https://oauth2.googleapis.com/token', [
            'timeout' => 30,
            'body' => [
                'client_id' => $client_id,
                'client_secret' => $client_secret,
                'refresh_token' => $refresh_token,
                'grant_type' => 'refresh_token',
            ],
        ]);

        if (is_wp_error($response)) {
            return [
                'success' => false,
                'message' => 'Google OAuth token refresh failed: ' . $response->get_error_message(),
            ];
        }

        $status = wp_remote_retrieve_response_code($response);
        $body = wp_remote_retrieve_body($response);
        $data = json_decode($body, true);

        if ($status < 200 || $status >= 300 || !is_array($data) || empty($data['access_token'])) {
            $error_message = is_array($data) ? ($data['error_description'] ?? ($data['error'] ?? '')) : '';
            return [
                'success' => false,
                'message' => $error_message !== '' ? 'Google OAuth token refresh failed: ' . $error_message : __('Google OAuth token refresh failed.', 'guard-dog'),
            ];
        }

        $expires_in = isset($data['expires_in']) ? max(120, (int) $data['expires_in']) : 3600;
        $expires_at = time() + $expires_in;
        set_transient($cache_key, [
            'token' => (string) $data['access_token'],
            'expires_at' => $expires_at,
        ], max(60, $expires_in - 30));

        return [
            'success' => true,
            'access_token' => (string) $data['access_token'],
        ];
    }

    /**
     * Build base64url-encoded RFC822 message for Gmail API.
     *
     * @param string $to Recipient email.
     * @param string $subject Email subject.
     * @param string $message HTML body.
     * @param string $text_message Plain text body.
     * @param string $from_email From email address.
     * @param string $from_name From display name.
     * @return string
     */
    private function build_google_raw_message($to, $subject, $message, $text_message, $from_email, $from_name) {
        if (!class_exists('PHPMailer\PHPMailer\PHPMailer')) {
            require_once ABSPATH . WPINC . '/PHPMailer/PHPMailer.php';
            require_once ABSPATH . WPINC . '/PHPMailer/SMTP.php';
            require_once ABSPATH . WPINC . '/PHPMailer/Exception.php';
        }

        try {
            $mail = new \PHPMailer\PHPMailer\PHPMailer(true);
            $mail->CharSet = 'UTF-8';
            $mail->setFrom($from_email, $from_name);
            $mail->addAddress($to);
            $mail->Subject = $subject;
            $mail->isHTML(true);
            $mail->Body = $message;
            $mail->AltBody = !empty($text_message) ? $text_message : $this->extract_plain_text($message);

            $mail->preSend();
            $mime_message = $mail->getSentMIMEMessage();
            return rtrim(strtr(base64_encode($mime_message), '+/', '-_'), '=');
        } catch (\PHPMailer\PHPMailer\Exception $e) {
            if (function_exists('Guard_Dog') && Guard_Dog()->debug) {
                Guard_Dog()->debug->error('Failed to build Google OAuth raw message', 'email_provider', [
                    'error' => $e->getMessage(),
                ]);
            }

            return '';
        }
    }

    /**
     * Fetch configured Gmail "sendAs" aliases for the authenticated account.
     *
     * @param array|null $settings Optional Google settings override.
     * @return array
     */
    public function get_google_send_as_aliases($settings = null) {
        if ($settings === null) {
            $settings = $this->get_provider_settings();
        }

        if (!is_array($settings)) {
            return [
                'success' => false,
                'message' => __('Google settings are invalid.', 'guard-dog'),
            ];
        }

        if ($this->get_google_auth_mode($settings) !== self::GOOGLE_AUTH_MODE_OAUTH) {
            return [
                'success' => false,
                'message' => __('Google alias preflight requires OAuth authentication mode.', 'guard-dog'),
            ];
        }

        $token_result = $this->get_google_oauth_access_token($settings);
        if (empty($token_result['success'])) {
            return [
                'success' => false,
                'message' => $token_result['message'] ?? __('Unable to authenticate with Google OAuth.', 'guard-dog'),
            ];
        }

        $response = wp_remote_get('https://gmail.googleapis.com/gmail/v1/users/me/settings/sendAs', [
            'headers' => [
                'Authorization' => 'Bearer ' . $token_result['access_token'],
            ],
            'timeout' => 30,
        ]);

        if (is_wp_error($response)) {
            return [
                'success' => false,
                'message' => 'Google Alias Preflight Error: ' . $response->get_error_message(),
            ];
        }

        $status = wp_remote_retrieve_response_code($response);
        $body = wp_remote_retrieve_body($response);
        $data = json_decode($body, true);

        if ($status < 200 || $status >= 300) {
            $api_error = is_array($data) ? ($data['error']['message'] ?? '') : '';
            $error_message = 'Google Alias Preflight Error: HTTP ' . $status;
            if ($api_error !== '') {
                $error_message .= ' - ' . $api_error;
            }

            return [
                'success' => false,
                'message' => $error_message,
            ];
        }

        $aliases = [];
        $send_as_list = isset($data['sendAs']) && is_array($data['sendAs']) ? $data['sendAs'] : [];
        foreach ($send_as_list as $send_as) {
            $email = isset($send_as['sendAsEmail']) ? sanitize_email((string) $send_as['sendAsEmail']) : '';
            if ($email === '') {
                continue;
            }

            $aliases[] = [
                'email' => $email,
                'display_name' => isset($send_as['displayName']) ? sanitize_text_field((string) $send_as['displayName']) : '',
                'is_primary' => !empty($send_as['isPrimary']),
                'is_default' => !empty($send_as['isDefault']),
                'verification_status' => isset($send_as['verificationStatus']) ? sanitize_key((string) $send_as['verificationStatus']) : 'unknown',
            ];
        }

        return [
            'success' => true,
            'aliases' => $aliases,
            'message' => __('Google alias preflight completed.', 'guard-dog'),
        ];
    }

    /**
     * Test email configuration
     *
     * @param string $test_email Email address to send test to
     * @return array
     */
    public function test_configuration($test_email) {
        if (!is_email($test_email)) {
            return [
                'success' => false,
                'message' => __('Invalid email address.', 'guard-dog')
            ];
        }

        // Translators: %s is the site name.
        $subject = sprintf(esc_html__('[%s] Email Provider Test', 'guard-dog'), esc_html(get_bloginfo('name')));
        $message = sprintf(
            '<p>%s</p><p>%s</p>',
            __('This is a test email from your Guard Dog email provider configuration.', 'guard-dog'),
            // Translators: %s is the date and time when the email was sent.
            sprintf(esc_html__('Sent at: %s', 'guard-dog'), esc_html(current_time('Y-m-d H:i:s')))
        );

        return $this->send_email($test_email, $subject, $message);
    }

    /**
     * Save provider configuration
     *
     * @param string $provider Provider key
     * @param array $settings Provider settings
     * @return bool
     */
    public function save_configuration($provider, $settings) {
        if (!isset(self::PROVIDERS[$provider])) {
            return false;
        }

        if (!is_array($settings)) {
            return false;
        }

        $existing_settings = get_option('guard_dog_email_provider_settings', []);
        if (!is_array($existing_settings)) {
            $existing_settings = [];
        }

        $sanitized_settings = self::sanitize_provider_settings($provider, $settings, $existing_settings);

        if (!$this->validate_provider_settings($provider, $sanitized_settings)) {
            return false;
        }

        update_option('guard_dog_email_provider', $provider);
        update_option('guard_dog_email_provider_settings', $sanitized_settings);

        // Reload configuration
        $this->load_configuration();

        return true;
    }

    /**
     * Validate provider settings.
     *
     * @param string $provider Provider key.
     * @param array $settings Settings array.
     * @return bool
     */
    private function validate_provider_settings($provider, $settings) {
        if ($provider === 'google') {
            return $this->validate_google_settings($settings);
        }

        $config = $this->get_provider_config($provider);
        if (empty($config) || empty($config['fields']) || !is_array($config['fields'])) {
            return false;
        }

        foreach ($config['fields'] as $field_key => $field_config) {
            if (!empty($field_config['required']) && empty($settings[$field_key])) {
                return false;
            }
        }

        return true;
    }

    /**
     * Validate Google provider settings for the active auth mode.
     *
     * @param array $settings Provider settings.
     * @return bool
     */
    private function validate_google_settings($settings) {
        if (!is_array($settings)) {
            return false;
        }

        $from_email = isset($settings['google_from_email']) ? $settings['google_from_email'] : '';
        if (empty($from_email) || !is_email($from_email)) {
            return false;
        }

        $auth_mode = $this->get_google_auth_mode($settings);
        if ($auth_mode === self::GOOGLE_AUTH_MODE_OAUTH) {
            $client_id = isset($settings['google_oauth_client_id']) ? trim((string) $settings['google_oauth_client_id']) : '';
            $client_secret = self::decrypt_sensitive_value((string) ($settings['google_oauth_client_secret'] ?? ''));
            $refresh_token = self::decrypt_sensitive_value((string) ($settings['google_oauth_refresh_token'] ?? ''));

            return $client_id !== '' && $client_secret !== '' && $refresh_token !== '';
        }

        $auth_email = isset($settings['google_auth_email']) ? (string) $settings['google_auth_email'] : '';
        if ($auth_email === '') {
            $auth_email = (string) $from_email;
        }

        $app_password = self::decrypt_sensitive_value((string) ($settings['google_app_password'] ?? ''));

        return is_email($auth_email) && $app_password !== '';
    }

    /**
     * Resolve Google auth mode with backward compatibility defaults.
     *
     * @param array $settings Google settings array.
     * @return string
     */
    private function get_google_auth_mode($settings) {
        $mode = isset($settings['google_auth_mode']) ? sanitize_key((string) $settings['google_auth_mode']) : '';
        if ($mode === self::GOOGLE_AUTH_MODE_OAUTH || $mode === self::GOOGLE_AUTH_MODE_APP_PASSWORD) {
            return $mode;
        }

        // Backward compatibility: existing installs used App Password mode only.
        return self::GOOGLE_AUTH_MODE_APP_PASSWORD;
    }

    /**
     * Get provider field value
     *
     * @param string $field_key Field key
     * @return string
     */
    public function get_field_value($field_key) {
        $settings = $this->get_provider_settings();
        return isset($settings[$field_key]) ? $settings[$field_key] : '';
    }

    /**
     * Generate HTML for provider configuration form.
     *
     * @param string $provider Provider key.
     * @param string $row_class Optional class applied to each field row.
     * @param string $row_style Optional inline style applied to each field row.
     * @return string
     */
    public function render_provider_form($provider, $row_class = '', $row_style = '') {
        if (!isset(self::PROVIDERS[$provider])) {
            return '<p>' . esc_html__('Invalid provider selected.', 'guard-dog') . '</p>';
        }

        $config = self::PROVIDERS[$provider];
        $settings = $this->get_provider_settings();
        $html = '';
        $row_class = is_string($row_class) ? trim($row_class) : '';
        $row_style = is_string($row_style) ? trim($row_style) : '';

        foreach ($config['fields'] as $field_key => $field_config) {
            $value = isset($settings[$field_key]) ? $settings[$field_key] : '';

            if ($field_key === 'google_auth_mode' && $value === '') {
                // Backward compatibility: existing Google configs were App Password only.
                if (!empty($settings['google_app_password'])) {
                    $value = self::GOOGLE_AUTH_MODE_APP_PASSWORD;
                } elseif (isset($field_config['default'])) {
                    $value = (string) $field_config['default'];
                }
            } elseif ($value === '' && isset($field_config['default'])) {
                $value = (string) $field_config['default'];
            }

            $required = $field_config['required'] ? 'required' : '';
            $required_mark = $field_config['required'] ? ' <span class="required">*</span>' : '';
            $row_class_attr = $row_class !== '' ? ' class="' . esc_attr($row_class) . '"' : '';
            $row_style_attr = $row_style !== '' ? ' style="' . esc_attr($row_style) . '"' : '';

            $html .= '<tr' . $row_class_attr . $row_style_attr . ' data-provider="' . esc_attr($provider) . '">';
            $html .= '<th scope="row">';
            $html .= '<label for="' . esc_attr($field_key) . '">' . esc_html($field_config['label']) . $required_mark . '</label>';
            $html .= '</th>';
            $html .= '<td>';

            switch ($field_config['type']) {
                case 'password':
                    // Obfuscate the value for display to prevent API key exposure in DOM
                    $obfuscated_value = !empty($value) ? str_repeat('•', 20) : '';
                    $html .= '<input type="password" id="' . esc_attr($field_key) . '" name="guard_dog_email_provider_settings[' . esc_attr($field_key) . ']" value="' . esc_attr($obfuscated_value) . '" class="regular-text" autocomplete="new-password" data-has-value="' . esc_attr(!empty($value) ? '1' : '0') . '" ' . $required . ' />';
                    break;
                case 'email':
                    $html .= '<input type="email" id="' . esc_attr($field_key) . '" name="guard_dog_email_provider_settings[' . esc_attr($field_key) . ']" value="' . esc_attr($value) . '" class="regular-text" ' . $required . ' />';
                    break;
                case 'select':
                    $html .= '<select id="' . esc_attr($field_key) . '" name="guard_dog_email_provider_settings[' . esc_attr($field_key) . ']" ' . $required . '>';
                    foreach ($field_config['options'] as $option_value => $option_label) {
                        $selected = ($value === $option_value) ? 'selected' : '';
                        $html .= '<option value="' . esc_attr($option_value) . '" ' . $selected . '>' . esc_html($option_label) . '</option>';
                    }
                    $html .= '</select>';
                    break;
                default:
                    $html .= '<input type="text" id="' . esc_attr($field_key) . '" name="guard_dog_email_provider_settings[' . esc_attr($field_key) . ']" value="' . esc_attr($value) . '" class="regular-text" ' . $required . ' />';
                    break;
            }

            if (!empty($field_config['description'])) {
                $html .= '<p class="description">' . esc_html($field_config['description']) . '</p>';
            }

            $html .= '</td>';
            $html .= '</tr>';
        }

        return $html;
    }

    /**
     * Handle WordPress wp_mail() calls when global override is enabled.
     *
     * @since 1.9.0
     * @param null|bool $return Short-circuit return value.
     * @param array $atts Email arguments.
     * @return null|bool Return null to allow WordPress default, or bool to short-circuit.
     */
    public function handle_wp_mail($return, $atts) {
        // Check if global override is enabled
        if (!get_option('guard_dog_email_provider_global_override', false)) {
            return $return; // Allow WordPress default behavior
        }

        // Check if provider is configured
        if (!$this->is_configured()) {
            // Log warning but allow WordPress default behavior
            if (function_exists('Guard_Dog') && Guard_Dog()->debug) {
                Guard_Dog()->debug->warning('Global email override enabled but provider not configured', 'email_provider');
            }
            return $return;
        }

        // Parse email arguments
        $to = isset($atts['to']) ? $atts['to'] : '';
        $subject = isset($atts['subject']) ? $atts['subject'] : '';
        $message = isset($atts['message']) ? $atts['message'] : '';
        $headers = isset($atts['headers']) ? $atts['headers'] : '';
        $attachments = isset($atts['attachments']) ? $atts['attachments'] : [];

        if (empty($to) || empty($subject) || empty($message)) {
            return $return; // Invalid email, allow WordPress to handle error
        }

        // Parse headers
        $parsed_headers = $this->parse_email_headers($headers);
        
        // Extract recipients
        $recipients = $this->extract_recipients($to, $parsed_headers);

        // Extract plain text from HTML if needed
        $text_message = $this->extract_plain_text($message);

        // Determine sender
        $from_email = $parsed_headers['from']['email'] ?? '';
        $from_name = $parsed_headers['from']['name'] ?? '';

        // Attachments are not yet supported by provider override, so fall back
        // before any provider request is made to avoid duplicate deliveries.
        if (!empty($attachments)) {
            if (function_exists('Guard_Dog') && Guard_Dog()->debug) {
                Guard_Dog()->debug->info('Email attachments detected but not yet supported in global override', 'email_provider', [
                    'attachments' => $attachments,
                ]);
            }

            return $return;
        }

        // Send emails to each recipient
        // Note: Some providers require separate calls for each recipient when CC/BCC are involved
        $all_success = true;
        $error_messages = [];

        foreach ($recipients as $recipient) {
            // Build message with appropriate subject line
            $email_message = $message;
            
            // If this is a CC/BCC recipient, we might need to adjust the message
            // For now, send the same message to all recipients
            
            $result = $this->send_email_with_headers(
                $recipient['email'],
                $recipient['name'] ?? '',
                $subject,
                $email_message,
                $text_message,
                $from_email,
                $from_name,
                $recipient['type'] ?? 'to',
                $parsed_headers
            );

            if (!$result['success']) {
                $all_success = false;
                $error_messages[] = $result['message'];
            }
        }

        // Log result
        if (function_exists('Guard_Dog') && Guard_Dog()->debug) {
            Guard_Dog()->debug->debug('Global email override intercepted wp_mail()', 'email_provider', [
                'to' => $to,
                'subject' => $subject,
                'success' => $all_success,
                'errors' => $error_messages,
            ]);
        }

        // If successful, return true to short-circuit WordPress default
        if ($all_success) {
            return true;
        }

        // If failed, return null to allow WordPress default wp_mail() to try
        // This provides a fallback when the provider is misconfigured or fails
        if (function_exists('Guard_Dog') && Guard_Dog()->debug) {
            Guard_Dog()->debug->warning('Guard Dog email provider failed, falling back to WordPress default wp_mail()', 'email_provider', [
                'errors' => $error_messages,
            ]);
        }
        return null;
    }

    /**
     * Send email with headers support.
     *
     * @since 1.9.0
     * @param string $to Recipient email.
     * @param string $to_name Recipient name.
     * @param string $subject Email subject.
     * @param string $message Email message (HTML).
     * @param string $text_message Plain text message.
     * @param string $from_email Sender email.
     * @param string $from_name Sender name.
     * @param string $recipient_type Type: 'to', 'cc', or 'bcc'.
     * @param array $parsed_headers Parsed email headers.
     * @return array Result array.
     */
    private function send_email_with_headers($to, $to_name, $subject, $message, $text_message, $from_email, $from_name, $recipient_type, $parsed_headers) {
        $provider = $this->get_current_provider();
        $settings = $this->get_provider_settings();
        
        // Determine which from email key to use for this provider
        $from_key = '';
        switch ($provider) {
            case 'aws_ses':
                $from_key = 'aws_ses_from_email';
                break;
            case 'mailgun':
                $from_key = 'mailgun_from_email';
                break;
            case 'resend':
                $from_key = 'resend_from_email';
                break;
            case 'sendgrid':
                $from_key = 'sendgrid_from_email';
                break;
            case 'google':
                $from_key = 'google_from_email';
                break;
        }

        // Ensure provider's from email is configured
        if (empty($from_key) || empty($settings[$from_key])) {
            return [
                'success' => false,
                'message' => __('Email provider from address is not configured.', 'guard-dog')
            ];
        }
        
        $configured_from = $settings[$from_key];
        
        // Validate and potentially use custom from email
        // Only use custom from if it matches the domain of the configured from (safer for Resend)
        // This prevents 400 errors from unverified domains
        $original_from = $configured_from;
        $use_custom_from = false;
        
        if (!empty($from_email) && is_email($from_email)) {
            $custom_domain = substr(strrchr($from_email, "@"), 1);
            $configured_domain = substr(strrchr($configured_from, "@"), 1);
            
            // Google supports cross-domain aliases if configured in Gmail "Send mail as".
            if ($provider === 'google') {
                $settings[$from_key] = $from_email;
                if (empty($settings['google_auth_email'])) {
                    $settings['google_auth_email'] = $configured_from;
                }
                $use_custom_from = true;
            // For non-Google providers, only use custom from if domain matches (verified domain).
            } elseif ($custom_domain === $configured_domain && !empty($custom_domain)) {
                $settings[$from_key] = $from_email;
                $use_custom_from = true;
            }
        }

        // Preserve explicit From name when provided via wp_mail() headers.
        if ($provider === 'google' && !empty($from_name)) {
            $settings['google_from_name'] = $from_name;
        }

        // Call provider method directly with potentially modified settings
        try {
            switch ($provider) {
                case 'aws_ses':
                    return $this->send_via_aws_ses($to, $subject, $message, $text_message, $settings);
                case 'mailgun':
                    return $this->send_via_mailgun($to, $subject, $message, $text_message, $settings);
                case 'resend':
                    return $this->send_via_resend($to, $subject, $message, $text_message, $settings);
                case 'sendgrid':
                    return $this->send_via_sendgrid($to, $subject, $message, $text_message, $settings);
                case 'google':
                    return $this->send_via_google($to, $subject, $message, $text_message, $settings);
                default:
                    return [
                        'success' => false,
                        'message' => __('Unsupported email provider.', 'guard-dog')
                    ];
            }
        } finally {
            // Restore original from email if we modified it
            if ($use_custom_from) {
                $settings[$from_key] = $original_from;
            }
        }
    }

    /**
     * Parse email headers into structured array.
     *
     * @since 1.9.0
     * @param string|array $headers Email headers.
     * @return array Parsed headers.
     */
    private function parse_email_headers($headers) {
        $parsed = [
            'from' => ['email' => '', 'name' => ''],
            'reply_to' => ['email' => '', 'name' => ''],
            'cc' => [],
            'bcc' => [],
            'content_type' => 'text/plain',
        ];

        // Convert headers to array if string
        if (is_string($headers)) {
            $headers = explode("\n", str_replace("\r\n", "\n", $headers));
        }

        if (!is_array($headers)) {
            return $parsed;
        }

        foreach ($headers as $header) {
            if (empty($header)) {
                continue;
            }

            // Split header into name and value
            if (strpos($header, ':') === false) {
                continue;
            }

            list($name, $value) = explode(':', $header, 2);
            $name = trim($name);
            $value = trim($value);

            switch (strtolower($name)) {
                case 'from':
                    $parsed['from'] = $this->parse_email_address($value);
                    break;
                case 'reply-to':
                    $parsed['reply_to'] = $this->parse_email_address($value);
                    break;
                case 'cc':
                    $cc_addresses = $this->parse_multiple_addresses($value);
                    foreach ($cc_addresses as $addr) {
                        $parsed['cc'][] = $addr;
                    }
                    break;
                case 'bcc':
                    $bcc_addresses = $this->parse_multiple_addresses($value);
                    foreach ($bcc_addresses as $addr) {
                        $parsed['bcc'][] = $addr;
                    }
                    break;
                case 'content-type':
                    if (stripos($value, 'text/html') !== false) {
                        $parsed['content_type'] = 'text/html';
                    } else {
                        $parsed['content_type'] = 'text/plain';
                    }
                    break;
            }
        }

        return $parsed;
    }

    /**
     * Parse email address with optional name.
     *
     * @since 1.9.0
     * @param string $address Email address string (e.g., "Name <email@example.com>").
     * @return array Array with 'email' and 'name' keys.
     */
    private function parse_email_address($address) {
        $result = ['email' => '', 'name' => ''];

        // Check if address contains name in format "Name <email@example.com>"
        if (preg_match('/(.*?)\s*<(.+?)>/', $address, $matches)) {
            $result['name'] = trim($matches[1], ' "\'');
            $result['email'] = trim($matches[2]);
        } else {
            $result['email'] = trim($address, ' "\'');
        }

        // Validate email
        if (!is_email($result['email'])) {
            $result['email'] = '';
        }

        return $result;
    }

    /**
     * Parse multiple email addresses from string.
     *
     * @since 1.9.0
     * @param string $addresses Comma-separated email addresses.
     * @return array Array of parsed addresses.
     */
    private function parse_multiple_addresses($addresses) {
        $result = [];
        $address_list = explode(',', $addresses);

        foreach ($address_list as $address) {
            $parsed = $this->parse_email_address(trim($address));
            if (!empty($parsed['email'])) {
                $result[] = $parsed;
            }
        }

        return $result;
    }

    /**
     * Extract recipients (To, CC, BCC) into a single list.
     *
     * @since 1.9.0
     * @param string|array $to Primary recipients.
     * @param array $parsed_headers Parsed headers.
     * @return array Array of recipient arrays with 'email', 'name', and 'type' keys.
     */
    private function extract_recipients($to, $parsed_headers) {
        $recipients = [];

        // Parse primary recipients
        if (is_string($to)) {
            $to_addresses = $this->parse_multiple_addresses($to);
            foreach ($to_addresses as $addr) {
                $addr['type'] = 'to';
                $recipients[] = $addr;
            }
        } elseif (is_array($to)) {
            foreach ($to as $addr) {
                $parsed = $this->parse_email_address($addr);
                if (!empty($parsed['email'])) {
                    $parsed['type'] = 'to';
                    $recipients[] = $parsed;
                }
            }
        }

        // Add CC recipients
        foreach ($parsed_headers['cc'] as $cc) {
            $cc['type'] = 'cc';
            $recipients[] = $cc;
        }

        // Add BCC recipients
        foreach ($parsed_headers['bcc'] as $bcc) {
            $bcc['type'] = 'bcc';
            $recipients[] = $bcc;
        }

        return $recipients;
    }

    /**
     * Extract plain text from HTML message.
     *
     * @since 1.9.0
     * @param string $html_message HTML message.
     * @return string Plain text version.
     */
    private function extract_plain_text($html_message) {
        // If message doesn't look like HTML, return as-is
        if (stripos($html_message, '<html') === false && stripos($html_message, '<body') === false && stripos($html_message, '<p') === false) {
            return $html_message;
        }

        // Simple HTML to text conversion
        // Strip HTML tags and decode entities
        $text = wp_strip_all_tags($html_message);
        $text = html_entity_decode($text, ENT_QUOTES, 'UTF-8');
        $text = preg_replace('/\s+/', ' ', $text); // Normalize whitespace
        $text = trim($text);

        return $text;
    }
}
