<?php
/**
 * 247ChatMate — Fallback Mail Delivery Foundation
 * ------------------------------------------------
 * Plugin-side delivery safety layer for lead alerts and weekly summaries.
 *
 * Scope for 247CHATMATEFALLBACKMAILDELIVERY1:
 * - Save the outbound email payload before attempting delivery.
 * - Prefer a future managed 247ChatMate sender when a server-side module/filter exists.
 * - Fall back to the site WordPress mail route, including SMTP plugins such as WP Mail SMTP.
 * - Queue failed lead/summary emails locally for admin retry.
 * - Store no provider API keys and expose no unfinished provider controls to clients.
 */

defined('ABSPATH') || exit;

if (!defined('MATEWA_FALLBACK_MAIL_QUEUE_OPTION')) {
    define('MATEWA_FALLBACK_MAIL_QUEUE_OPTION', 'matewa_fallback_mail_failed_queue');
}

if (!defined('MATEWA_FALLBACK_MAIL_LAST_RESULT_OPTION')) {
    define('MATEWA_FALLBACK_MAIL_LAST_RESULT_OPTION', 'matewa_fallback_mail_last_result');
}

if (!function_exists('matewa_fallback_mail_now')) {
    function matewa_fallback_mail_now() {
        return current_time('mysql');
    }
}

if (!function_exists('matewa_fallback_mail_sanitise_context')) {
    function matewa_fallback_mail_sanitise_context($context) {
        $context = sanitize_key((string) $context);
        $allowed = array('lead', 'phone_only_lead', 'weekly_summary', 'weekly_summary_test', 'agency_notice');
        return in_array($context, $allowed, true) ? $context : 'lead';
    }
}

if (!function_exists('matewa_fallback_mail_safe_sender_email')) {
    function matewa_fallback_mail_safe_sender_email() {
        $host = wp_parse_url(home_url('/'), PHP_URL_HOST);
        $host = strtolower(preg_replace('/[^a-z0-9\.\-]/', '', (string) $host));
        $host = preg_replace('/^www\./', '', $host);

        $options = function_exists('matewa_client_mail_delivery_get_options') ? matewa_client_mail_delivery_get_options() : array();
        $candidate = isset($options['sender_email']) ? sanitize_email((string) $options['sender_email']) : '';
        if (is_email($candidate)) {
            $candidate_domain = strtolower((string) substr(strrchr($candidate, '@'), 1));
            if ('' === $host || $candidate_domain === $host) {
                return $candidate;
            }
        }

        /*
         * Do not use a Gmail/Outlook/Yahoo admin address as the From address for
         * plugin-generated mail. Many hosts reject or silently drop that because
         * the site is not authorised to send as that mailbox. Use a same-domain
         * sender first, then leave customer/admin addresses for Reply-To/content.
         */
        if ('' !== $host && false !== strpos($host, '.')) {
            foreach (array('leads@' . $host, 'wordpress@' . $host, 'noreply@' . $host) as $fallback) {
                if (is_email($fallback)) {
                    return $fallback;
                }
            }
        }

        $admin_email = sanitize_email((string) get_option('admin_email', ''));
        if (is_email($admin_email)) {
            return $admin_email;
        }

        return '';
    }
}

if (!function_exists('matewa_fallback_mail_header_display_name')) {
    function matewa_fallback_mail_header_display_name($value, $fallback = 'Website Leads') {
        $value = trim((string) $value);
        if (preg_match('/^(.+?)<[^>]+>$/', $value, $match)) {
            $value = trim((string) $match[1]);
        }

        if (is_email($value)) {
            $value = '';
        }

        $value = wp_strip_all_tags($value);
        $value = str_replace(array("\r", "\n", '"', '\\'), ' ', $value);
        $value = trim(preg_replace('/\s+/', ' ', $value));

        if ('' === $value) {
            $value = $fallback;
        }

        return sanitize_text_field($value);
    }
}

if (!function_exists('matewa_fallback_mail_normalise_address_header')) {
    function matewa_fallback_mail_normalise_address_header($header_name, $value) {
        $header_name = ucfirst(strtolower((string) $header_name));
        $value = trim(str_replace(array("\r", "\n"), '', (string) $value));

        $email = '';
        if (preg_match('/<([^>]+)>/', $value, $match)) {
            $email = sanitize_email((string) $match[1]);
        } else {
            $email = sanitize_email($value);
        }

        if (!is_email($email) && 'From' === $header_name) {
            $email = matewa_fallback_mail_safe_sender_email();
        }

        if (!is_email($email)) {
            return '';
        }

        $name = matewa_fallback_mail_header_display_name($value, 'Website Leads');
        if ('reply-to' === strtolower($header_name)) {
            return 'Reply-To: ' . $email;
        }

        return 'From: ' . $name . ' <' . $email . '>';
    }
}

if (!function_exists('matewa_fallback_mail_normalise_headers')) {
    function matewa_fallback_mail_normalise_headers($headers) {
        if (is_string($headers)) {
            $headers = preg_split('/\r\n|\r|\n/', $headers);
        }

        $headers = is_array($headers) ? $headers : array();
        $clean = array();
        $has_content_type = false;
        $has_from = false;

        foreach ($headers as $header) {
            $header = trim((string) $header);
            if ('' === $header) {
                continue;
            }

            $header = trim(str_replace(array("\r", "\n"), '', $header));
            if ('' === $header || false === strpos($header, ':')) {
                continue;
            }

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

            if ('content-type' === $name_lower) {
                $has_content_type = true;
                $clean[] = 'Content-Type: text/html; charset=UTF-8';
                continue;
            }

            if ('from' === $name_lower || 'reply-to' === $name_lower) {
                $address_header = matewa_fallback_mail_normalise_address_header('from' === $name_lower ? 'From' : 'Reply-To', $value);
                if ('' !== $address_header) {
                    $clean[] = $address_header;
                    if ('from' === $name_lower) {
                        $has_from = true;
                    }
                }
                continue;
            }

            $safe_name = preg_replace('/[^A-Za-z0-9\-]/', '', $name);
            $safe_value = sanitize_text_field(wp_strip_all_tags($value));
            if ('' !== $safe_name && '' !== $safe_value) {
                $clean[] = $safe_name . ': ' . $safe_value;
            }
        }

        if (!$has_content_type) {
            array_unshift($clean, 'Content-Type: text/html; charset=UTF-8');
        }

        if (!$has_from) {
            $safe_from = matewa_fallback_mail_safe_sender_email();
            if (is_email($safe_from)) {
                $options = function_exists('matewa_client_mail_delivery_get_options') ? matewa_client_mail_delivery_get_options() : array();
                $name = matewa_fallback_mail_header_display_name((string) ($options['sender_name'] ?? ''), 'Website Leads');
                $clean[] = 'From: ' . $name . ' <' . $safe_from . '>';
            }
        }

        return array_values(array_unique($clean));
    }
}

if (!function_exists('matewa_fallback_mail_build_payload')) {
    function matewa_fallback_mail_build_payload($context, $to, $subject, $message, $headers = array(), $meta = array()) {
        $to = sanitize_email((string) $to);
        $subject = sanitize_text_field((string) $subject);
        $message = wp_kses_post((string) $message);
        $headers = matewa_fallback_mail_normalise_headers($headers);
        $meta = is_array($meta) ? $meta : array();

        $safe_meta = array();
        foreach ($meta as $key => $value) {
            $safe_key = sanitize_key((string) $key);
            if ('' === $safe_key) {
                continue;
            }

            if (is_scalar($value)) {
                $safe_meta[$safe_key] = sanitize_text_field((string) $value);
            }
        }

        return array(
            'id'         => function_exists('wp_generate_uuid4') ? wp_generate_uuid4() : uniqid('matewa_mail_', true),
            'context'    => matewa_fallback_mail_sanitise_context($context),
            'to'         => $to,
            'subject'    => $subject,
            'message'    => $message,
            'headers'    => $headers,
            'meta'       => $safe_meta,
            'created_at' => matewa_fallback_mail_now(),
            'retries'    => 0,
            'last_error' => '',
        );
    }
}

if (!function_exists('matewa_fallback_mail_queue_limit')) {
    function matewa_fallback_mail_queue_limit() {
        return 30;
    }
}

if (!function_exists('matewa_fallback_mail_get_queue')) {
    function matewa_fallback_mail_get_queue() {
        $queue = get_option(MATEWA_FALLBACK_MAIL_QUEUE_OPTION, array());
        return is_array($queue) ? $queue : array();
    }
}

if (!function_exists('matewa_fallback_mail_save_queue')) {
    function matewa_fallback_mail_save_queue(array $queue) {
        $limit = matewa_fallback_mail_queue_limit();
        if (count($queue) > $limit) {
            $queue = array_slice($queue, -1 * $limit, null, true);
        }

        return update_option(MATEWA_FALLBACK_MAIL_QUEUE_OPTION, $queue, false);
    }
}

if (!function_exists('matewa_fallback_mail_queue_count')) {
    function matewa_fallback_mail_queue_count() {
        return count(matewa_fallback_mail_get_queue());
    }
}

if (!function_exists('matewa_fallback_mail_store_failed')) {
    function matewa_fallback_mail_store_failed(array $payload, $error = '') {
        $queue = matewa_fallback_mail_get_queue();
        $payload['last_error'] = sanitize_text_field((string) $error);
        $payload['failed_at'] = matewa_fallback_mail_now();
        $payload['retries'] = absint($payload['retries'] ?? 0);

        $id = sanitize_key((string) ($payload['id'] ?? ''));
        if ('' === $id) {
            $id = function_exists('wp_generate_uuid4') ? wp_generate_uuid4() : uniqid('mail_', true);
            $payload['id'] = $id;
        }

        $queue[$id] = $payload;
        matewa_fallback_mail_save_queue($queue);

        return $id;
    }
}

if (!function_exists('matewa_fallback_mail_update_last_result')) {
    function matewa_fallback_mail_update_last_result(array $result) {
        $result['updated_at'] = matewa_fallback_mail_now();
        update_option(MATEWA_FALLBACK_MAIL_LAST_RESULT_OPTION, $result, false);
    }
}

if (!function_exists('matewa_fallback_mail_get_last_result')) {
    function matewa_fallback_mail_get_last_result() {
        $result = get_option(MATEWA_FALLBACK_MAIL_LAST_RESULT_OPTION, array());
        return is_array($result) ? $result : array();
    }
}

if (!function_exists('matewa_fallback_mail_try_managed_sender')) {
    function matewa_fallback_mail_try_managed_sender(array $payload) {
        /**
         * Future server-side sender hook.
         * A later 247ChatMate relay module can return:
         * array('sent' => true, 'method' => '247chatmate_managed_sender')
         */
        $result = apply_filters('matewa_fallback_mail_managed_sender_result', null, $payload);

        if (is_array($result)) {
            return array(
                'sent'   => !empty($result['sent']),
                'method' => !empty($result['method']) ? sanitize_key((string) $result['method']) : '247chatmate_managed_sender',
                'error'  => !empty($result['error']) ? sanitize_text_field((string) $result['error']) : '',
            );
        }

        return array(
            'sent'   => false,
            'method' => '247chatmate_managed_sender_not_configured',
            'error'  => 'Managed sender module is not configured on this site.',
        );
    }
}

if (!function_exists('matewa_fallback_mail_send_via_site_mail')) {
    function matewa_fallback_mail_send_via_site_mail(array $payload) {
        $last_mail_error = '';
        $failure_hook = function($wp_error) use (&$last_mail_error) {
            if (is_wp_error($wp_error)) {
                $last_mail_error = $wp_error->get_error_message();
            }
        };

        add_action('wp_mail_failed', $failure_hook, 10, 1);
        $sent = wp_mail(
            $payload['to'],
            wp_specialchars_decode((string) $payload['subject'], ENT_QUOTES),
            (string) $payload['message'],
            matewa_fallback_mail_normalise_headers($payload['headers'] ?? array())
        );
        remove_action('wp_mail_failed', $failure_hook, 10);

        return array(
            'sent'   => (bool) $sent,
            'method' => 'site_wp_mail_or_smtp',
            'error'  => $sent ? '' : ('' !== $last_mail_error ? $last_mail_error : 'wp_mail returned false.'),
        );
    }
}

if (!function_exists('matewa_fallback_mail_deliver_payload')) {
    function matewa_fallback_mail_deliver_payload(array $payload) {
        $managed = matewa_fallback_mail_try_managed_sender($payload);
        if (!empty($managed['sent'])) {
            return array(
                'sent'   => true,
                'method' => $managed['method'],
                'error'  => '',
            );
        }

        $client_route = function_exists('matewa_client_mail_delivery_get_route')
            ? matewa_client_mail_delivery_get_route()
            : 'site_mail';

        $client_result = array();
        if ('client_smtp' === $client_route && function_exists('matewa_client_mail_delivery_send_via_smtp')) {
            $client_result = matewa_client_mail_delivery_send_via_smtp($payload);
            if (!empty($client_result['sent'])) {
                return array(
                    'sent'   => true,
                    'method' => !empty($client_result['method']) ? sanitize_key((string) $client_result['method']) : 'client_smtp',
                    'error'  => '',
                );
            }

            $allow_site_fallback = function_exists('matewa_client_mail_delivery_allow_site_fallback')
                ? matewa_client_mail_delivery_allow_site_fallback()
                : true;

            if (!$allow_site_fallback) {
                return array(
                    'sent'   => false,
                    'method' => !empty($client_result['method']) ? sanitize_key((string) $client_result['method']) : 'client_smtp_failed',
                    'error'  => !empty($client_result['error']) ? sanitize_text_field((string) $client_result['error']) : 'Client SMTP route failed.',
                );
            }
        }

        $site_mail = matewa_fallback_mail_send_via_site_mail($payload);
        if (!empty($site_mail['sent'])) {
            return array(
                'sent'   => true,
                'method' => !empty($client_result) ? 'client_smtp_fallback_site_mail' : $site_mail['method'],
                'error'  => '',
            );
        }

        $client_error = !empty($client_result['error']) ? sanitize_text_field((string) $client_result['error']) : '';
        $site_error = !empty($site_mail['error']) ? sanitize_text_field((string) $site_mail['error']) : 'wp_mail returned false.';
        $error = '' !== $client_error ? 'Client SMTP failed: ' . $client_error . ' Site mail failed: ' . $site_error : $site_error;

        return array(
            'sent'   => false,
            'method' => !empty($client_result) ? 'client_smtp_then_site_mail_failed' : $site_mail['method'],
            'error'  => $error,
        );
    }
}

if (!function_exists('matewa_fallback_mail_send')) {
    function matewa_fallback_mail_send($context, $to, $subject, $message, $headers = array(), $meta = array(), $store_on_fail = true) {
        $payload = matewa_fallback_mail_build_payload($context, $to, $subject, $message, $headers, $meta);
        $result = array(
            'sent'       => false,
            'queued'     => false,
            'queue_id'   => '',
            'method'     => '',
            'error'      => '',
            'context'    => $payload['context'],
            'recipient'  => $payload['to'],
            'created_at' => $payload['created_at'],
        );

        if (!is_email($payload['to'])) {
            $result['error'] = 'Invalid recipient email.';
            matewa_fallback_mail_update_last_result($result);
            return $result;
        }

        $delivery = matewa_fallback_mail_deliver_payload($payload);
        if (!empty($delivery['sent'])) {
            $result['sent'] = true;
            $result['method'] = !empty($delivery['method']) ? sanitize_key((string) $delivery['method']) : 'mail_sent';
            matewa_fallback_mail_update_last_result($result);
            return $result;
        }

        $result['method'] = !empty($delivery['method']) ? sanitize_key((string) $delivery['method']) : 'mail_failed';
        $result['error'] = !empty($delivery['error']) ? sanitize_text_field((string) $delivery['error']) : 'Mail delivery failed.';

        if ($store_on_fail) {
            $queue_id = matewa_fallback_mail_store_failed($payload, $result['error']);
            $result['queued'] = '' !== $queue_id;
            $result['queue_id'] = $queue_id;
        }

        matewa_fallback_mail_update_last_result($result);
        return $result;
    }
}

if (!function_exists('matewa_fallback_mail_retry_failed_queue')) {
    function matewa_fallback_mail_retry_failed_queue($limit = 10) {
        $queue = matewa_fallback_mail_get_queue();
        $limit = max(1, min(25, absint($limit)));
        $attempted = 0;
        $sent = 0;
        $failed = 0;

        foreach ($queue as $id => $payload) {
            if ($attempted >= $limit) {
                break;
            }

            $payload = is_array($payload) ? $payload : array();
            $attempted++;
            $payload['retries'] = absint($payload['retries'] ?? 0) + 1;
            $mail_result = function_exists('matewa_fallback_mail_deliver_payload') ? matewa_fallback_mail_deliver_payload($payload) : matewa_fallback_mail_send_via_site_mail($payload);

            if (!empty($mail_result['sent'])) {
                unset($queue[$id]);
                $sent++;
                continue;
            }

            $payload['last_error'] = sanitize_text_field((string) ($mail_result['error'] ?? 'wp_mail returned false.'));
            $payload['last_retry_at'] = matewa_fallback_mail_now();
            $queue[$id] = $payload;
            $failed++;
        }

        matewa_fallback_mail_save_queue($queue);

        $result = array(
            'sent'      => 0 === $attempted ? false : (0 < $sent),
            'queued'    => 0 < count($queue),
            'method'    => 'selected_client_mail_route_retry',
            'error'     => 0 < $failed ? $failed . ' queued email(s) still failed.' : '',
            'context'   => 'retry_queue',
            'attempted' => $attempted,
            'retried'   => $attempted,
            'resent'    => $sent,
            'failed'    => $failed,
            'remaining' => count($queue),
        );

        matewa_fallback_mail_update_last_result($result);
        return $result;
    }
}

if (!function_exists('matewa_fallback_mail_status_label')) {
    function matewa_fallback_mail_status_label() {
        $last = matewa_fallback_mail_get_last_result();
        $queue_count = matewa_fallback_mail_queue_count();

        if (!empty($last['sent'])) {
            return 0 < $queue_count
                ? 'Mail is sending. ' . $queue_count . ' queued email(s) still need retry.'
                : 'Mail route active — last test/send succeeded.';
        }

        if (0 < $queue_count) {
            return 'Mail fallback queue active — ' . $queue_count . ' email(s) waiting for retry.';
        }

        return 'Mail route ready. Send a test weekly summary to confirm delivery.';
    }
}

if (!function_exists('matewa_fallback_mail_last_error_label')) {
    function matewa_fallback_mail_last_error_label() {
        $last = matewa_fallback_mail_get_last_result();
        $error = isset($last['error']) ? sanitize_text_field((string) $last['error']) : '';
        return $error;
    }
}

if (!function_exists('matewa_fallback_mail_handle_retry_request')) {
    function matewa_fallback_mail_handle_retry_request() {
        if (!is_admin() || !current_user_can('manage_options')) {
            return;
        }

        $page = isset($_GET['page']) ? sanitize_key(wp_unslash($_GET['page'])) : '';
        if ('247chatmate' !== $page || empty($_POST['matewa_fallback_mail_action'])) {
            return;
        }

        check_admin_referer('matewa_fallback_mail_nonce', 'matewa_fallback_mail_nonce');

        $action = sanitize_key(wp_unslash($_POST['matewa_fallback_mail_action']));
        if ('retry_failed' !== $action) {
            wp_safe_redirect(admin_url('admin.php?page=247chatmate&matewa_saved_section=setup&matewa_scroll_target=lead_tools&matewa_fallback_mail_notice=unknown_action#matewa-setup-lead-tools'));
            exit;
        }

        $result = matewa_fallback_mail_retry_failed_queue(10);
        $notice = 0 < absint($result['resent'] ?? 0) ? 'retry_sent' : 'retry_none';
        if (0 < absint($result['failed'] ?? 0)) {
            $notice = 'retry_failed';
        }

        wp_safe_redirect(admin_url('admin.php?page=247chatmate&matewa_saved_section=setup&matewa_scroll_target=lead_tools&matewa_fallback_mail_notice=' . $notice . '#matewa-setup-lead-tools'));
        exit;
    }
}

if (!function_exists('matewa_fallback_mail_render_action_forms')) {
    function matewa_fallback_mail_render_action_forms() {
        ?>
        <form id="matewa-fallback-mail-retry-form" class="matewa-admin-hidden-action-form" method="post" action="<?php echo esc_url(admin_url('admin.php?page=247chatmate')); ?>" aria-hidden="true">
            <?php wp_nonce_field('matewa_fallback_mail_nonce', 'matewa_fallback_mail_nonce'); ?>
            <input type="hidden" name="matewa_fallback_mail_action" value="retry_failed">
        </form>
        <?php
    }
}

add_action('admin_init', 'matewa_fallback_mail_handle_retry_request', 3);
