<?php
if (!defined('ABSPATH')) exit;

/**
 * VMO Email Marketing - ULTRA-COMPETITIVE SYSTEM
 * 
 * BEATS MAILCHIMP with:
 * - AI-powered campaign generation (GPT-4)
 * - Deep Research integration
 * - In-email shopping with Stripe
 * - 2 tokens per email (100% profit margin)
 * - 600 tokens per campaign creation (70% profit margin)
 * - Users can send 17,000-181,000 emails per plan
 */
class VMO_Email_Marketing {
    
    private $campaign_generator;
    private $identity_manager;
    
    public function __construct() {
        // Load our ultra-competitive email system
        require_once dirname(__FILE__) . '/class-vmo-ai-email-campaign-generator.php';
        require_once dirname(__FILE__) . '/class-vmo-email-identity-manager.php';
        require_once dirname(__FILE__) . '/class-vmo-email-router.php';
        
        $this->campaign_generator = new VMO_AI_Email_Campaign_Generator();
        $this->identity_manager = new VMO_Email_Identity_Manager();
        
        add_action('wp_ajax_vmo_email_generate_campaign', [$this, 'generate_campaign']);
        add_action('wp_ajax_vmo_email_send_campaign', [$this, 'send_campaign']);
        add_action('wp_ajax_vmo_get_email_overview', [$this, 'get_overview']);
        // Back-compat: older UI used these action names.
        add_action('wp_ajax_vmo_get_email_metrics', [$this, 'get_overview']);
        add_action('wp_ajax_vmo_get_email_campaigns', [$this, 'get_overview']);

        // AI auto-reply status/toggle (mailbox tab).
        add_action('wp_ajax_vmo_get_ai_reply_status', [$this, 'get_ai_reply_status']);
        add_action('wp_ajax_vmo_update_ai_reply_settings', [$this, 'update_ai_reply_settings']);

        add_action('wp_ajax_vmo_save_email_signature', [$this, 'save_signature']);
        add_action('wp_ajax_vmo_get_email_signature', [$this, 'get_signature']);
        add_action('wp_ajax_vmo_list_email_accounts', [$this, 'list_email_accounts']);
        add_action('wp_ajax_vmo_generate_email_content', [$this, 'generate_email_content']);
        add_action('init', [$this, 'maybe_create_tables']);
    }

    public function get_ai_reply_status() {
        if (!$this->verify_ajax_request()) {
            wp_send_json_error(['message' => 'Security check failed', 'status' => 'invalid_nonce']);
        }
        if (!is_user_logged_in()) {
            wp_send_json_error(['message' => 'Not logged in'], 401);
        }

        $user_id = get_current_user_id();
        $enabled = get_user_meta($user_id, 'vmo_ai_auto_reply_enabled', true);

        wp_send_json_success([
            'enabled' => !empty($enabled) ? 1 : 0,
        ]);
    }

    public function update_ai_reply_settings() {
        if (!$this->verify_ajax_request()) {
            wp_send_json_error(['message' => 'Security check failed', 'status' => 'invalid_nonce']);
        }
        if (!is_user_logged_in()) {
            wp_send_json_error(['message' => 'Not logged in'], 401);
        }

        $user_id = get_current_user_id();
        $enabled = isset($_POST['enabled']) ? intval($_POST['enabled']) : 0;
        update_user_meta($user_id, 'vmo_ai_auto_reply_enabled', $enabled ? 1 : 0);

        wp_send_json_success([
            'enabled' => $enabled ? 1 : 0,
        ]);
    }

    private function verify_ajax_request(): bool {
        // Accept either our legacy builder nonce or the WP REST nonce.
        $valid = check_ajax_referer('vmo_builder_nonce', 'security', false);
        if ($valid) {
            return true;
        }

        $rest_nonce = isset($_SERVER['HTTP_X_WP_NONCE']) ? sanitize_text_field($_SERVER['HTTP_X_WP_NONCE']) : '';
        if ($rest_nonce && wp_verify_nonce($rest_nonce, 'wp_rest')) {
            return true;
        }

        return false;
    }

    public function list_email_accounts() {
        if (!$this->verify_ajax_request()) {
            wp_send_json_error(['message' => 'Security check failed', 'status' => 'invalid_nonce']);
        }
        if (!is_user_logged_in()) {
            wp_send_json_error(['message' => 'Not logged in'], 401);
        }

        $user_id = get_current_user_id();
        global $wpdb;
        $table = $wpdb->prefix . 'vmo_email_sender_identities';
        $accounts = [];

        if ($wpdb->get_var($wpdb->prepare("SHOW TABLES LIKE %s", $table)) === $table) {
            $rows = $wpdb->get_results(
                $wpdb->prepare(
                    "SELECT email_address, email_role, display_name, verification_status, is_primary
                     FROM {$table}
                     WHERE user_id = %d
                     ORDER BY is_primary DESC, (verification_status = 'verified') DESC, email_role ASC, email_address ASC",
                    $user_id
                ),
                ARRAY_A
            );
            foreach ($rows as $r) {
                $email = sanitize_email($r['email_address'] ?? '');
                if (!$email) {
                    continue;
                }
                $accounts[] = [
                    'email' => $email,
                    'role' => sanitize_key($r['email_role'] ?? ''),
                    'display_name' => sanitize_text_field($r['display_name'] ?? ''),
                    'verification_status' => sanitize_text_field($r['verification_status'] ?? ''),
                    'is_primary' => !empty($r['is_primary']) ? 1 : 0,
                ];
            }
        }

        // Always include the current WP user email as a safe fallback option.
        $user = wp_get_current_user();
        $fallback_email = $user && $user->user_email ? sanitize_email($user->user_email) : '';
        if ($fallback_email) {
            $already = false;
            foreach ($accounts as $a) {
                if (strcasecmp($a['email'], $fallback_email) === 0) {
                    $already = true;
                    break;
                }
            }
            if (!$already) {
                array_unshift($accounts, [
                    'email' => $fallback_email,
                    'role' => 'primary',
                    'display_name' => $user->display_name ? sanitize_text_field($user->display_name) : '',
                    'verification_status' => 'fallback',
                    'is_primary' => 1,
                ]);
            }
        }

        wp_send_json_success(['accounts' => $accounts]);
    }

    public function save_signature() {
        if (!$this->verify_ajax_request()) {
            wp_send_json_error(['message' => 'Security check failed', 'status' => 'invalid_nonce']);
        }
        if (!is_user_logged_in()) {
            wp_send_json_error(['message' => 'Not logged in'], 401);
        }
        $user_id = get_current_user_id();

        $account = isset($_POST['account']) ? sanitize_email($_POST['account']) : '';
        if (!$account) {
            // Back-compat: allow a single default signature if no account selected.
            $account = 'default';
        }
        
        $name = isset($_POST['name']) ? sanitize_text_field(wp_unslash($_POST['name'])) : '';
        $designation = isset($_POST['designation']) ? sanitize_text_field(wp_unslash($_POST['designation'])) : '';
        $logo_url = isset($_POST['logo_url']) ? esc_url_raw(wp_unslash($_POST['logo_url'])) : '';
        $website_url = isset($_POST['website_url']) ? esc_url_raw(wp_unslash($_POST['website_url'])) : '';
        $theme_color = isset($_POST['theme_color']) ? sanitize_hex_color(wp_unslash($_POST['theme_color'])) : '';

        $social_links = null;
        if (isset($_POST['social_links'])) {
            $raw = wp_unslash($_POST['social_links']);
            $decoded = is_string($raw) ? json_decode($raw, true) : null;
            if (is_array($decoded)) {
                $clean = [];
                foreach ($decoded as $row) {
                    if (!is_array($row)) {
                        continue;
                    }
                    $platform = isset($row['platform']) ? sanitize_key($row['platform']) : '';
                    $url = isset($row['url']) ? esc_url_raw($row['url']) : '';
                    if ($url) {
                        $clean[] = ['platform' => $platform, 'url' => $url];
                    }
                }
                $social_links = wp_json_encode($clean);
            }
        }

        $custom_links = null;
        if (isset($_POST['custom_links'])) {
            $raw = wp_unslash($_POST['custom_links']);
            $decoded = is_string($raw) ? json_decode($raw, true) : null;
            if (is_array($decoded)) {
                $custom_links = wp_json_encode($decoded);
            }
        }
        
        global $wpdb;
        $table = $wpdb->prefix . 'vmo_email_signatures';
        
        // Check if exists
        $exists = $wpdb->get_var($wpdb->prepare("SELECT id FROM $table WHERE user_id = %d AND account = %s", $user_id, $account));
        
        $data = [
            'user_id' => $user_id,
            'account' => $account,
            'name' => $name,
            'designation' => $designation,
            'social_links' => $social_links,
            'custom_links' => $custom_links,
            'logo_url' => $logo_url,
            'website_url' => $website_url,
            'theme_color' => $theme_color,
            'is_default' => ($account === 'default') ? 1 : 0,
            'updated_at' => current_time('mysql')
        ];
        
        $ok = true;
        if ($exists) {
            // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
            $ok = (false !== $wpdb->update($table, $data, ['id' => $exists]));
        } else {
            $data['created_at'] = current_time('mysql');
            // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
            $ok = (false !== $wpdb->insert($table, $data));
        }

        if (!$ok) {
            wp_send_json_error(['message' => 'Failed to save signature', 'db_error' => $wpdb->last_error ?: null]);
        }

        wp_send_json_success(['message' => 'Signature saved successfully']);
    }

    public function get_signature() {
        if (!$this->verify_ajax_request()) {
            wp_send_json_error(['message' => 'Security check failed', 'status' => 'invalid_nonce']);
        }
        if (!is_user_logged_in()) {
            wp_send_json_error(['message' => 'Not logged in'], 401);
        }
        $user_id = get_current_user_id();
        $account = isset($_REQUEST['account']) ? sanitize_email($_REQUEST['account']) : '';
        if (!$account) {
            $account = 'default';
        }
        global $wpdb;
        $table = $wpdb->prefix . 'vmo_email_signatures';
        $sig = $wpdb->get_row($wpdb->prepare("SELECT * FROM $table WHERE user_id = %d AND account = %s", $user_id, $account), ARRAY_A);

        if (!$sig && $account !== 'default') {
            // Fallback to default signature if a specific account signature doesn't exist.
            $sig = $wpdb->get_row($wpdb->prepare("SELECT * FROM $table WHERE user_id = %d AND account = %s", $user_id, 'default'), ARRAY_A);
        }
        
        if ($sig) {
            $sig['social_links'] = json_decode($sig['social_links'], true);
            $sig['custom_links'] = json_decode($sig['custom_links'], true);
        }
        
        wp_send_json_success(['signature' => $sig]);
    }

    public function generate_email_content() {
        if (!$this->verify_ajax_request()) {
            wp_send_json_error(['message' => 'Security check failed', 'status' => 'invalid_nonce'], 403);
        }
        if (!is_user_logged_in()) wp_send_json_error(['message' => 'Not logged in'], 401);
        
        $intent = isset($_POST['intent']) ? sanitize_textarea_field(wp_unslash($_POST['intent'])) : '';
        $format = isset($_POST['format']) ? sanitize_text_field(wp_unslash($_POST['format'])) : 'plain';
        $user_id = get_current_user_id();

        if ($intent === '') {
            wp_send_json_error(['message' => 'Email intent is required'], 400);
        }

        if (!in_array($format, ['plain', 'html'], true)) {
            $format = 'plain';
        }
        
        // Get user profile for context
        $profile = function_exists('vmo_get_consultation_profile') ? vmo_get_consultation_profile($user_id) : [];
        $business_name = $profile['business_name'] ?? 'My Business';
        
        // Call AI
        $prompt = "Generate an email for a business named '$business_name'.\nIntent: $intent\nFormat: $format.\n";
        if ($format === 'html') {
            $prompt .= "Return a JSON object with keys: 'subject', 'html_body' (full HTML with inline CSS), 'plain_body'. Make the HTML modern and responsive.";
        } else {
            $prompt .= "Return a JSON object with keys: 'subject', 'plain_body'.";
        }
        
        // Use the existing generator class or direct OpenAI call
        // For simplicity, reusing the generator's method if available or mocking a direct call structure
        // Assuming VMO_AI_Email_Campaign_Generator has a generic method or we add one.
        // Let's add a generic method to VMO_AI_Email_Campaign_Generator
        
        $generator = new VMO_AI_Email_Campaign_Generator();
        $result = $generator->generate_custom_email($prompt, $format);

        if (isset($result['error'])) {
            wp_send_json_error(['message' => $result['error']], 500);
        }
        
        wp_send_json_success($result);
    }

    public function maybe_create_tables() {
        global $wpdb;
        $charset_collate = $wpdb->get_charset_collate();

        $campaigns = $wpdb->prefix . 'vmo_email_campaigns';
        $sends     = $wpdb->prefix . 'vmo_email_sends';
        $signatures = $wpdb->prefix . 'vmo_email_signatures';

        require_once ABSPATH . 'wp-admin/includes/upgrade.php';

        $sql1 = "CREATE TABLE IF NOT EXISTS $campaigns (
            id bigint(20) unsigned NOT NULL AUTO_INCREMENT,
            user_id bigint(20) unsigned NOT NULL,
            title varchar(255) NULL,
            payload longtext NULL,
            status varchar(32) NOT NULL DEFAULT 'draft',
            created_at datetime NOT NULL,
            updated_at datetime NOT NULL,
            PRIMARY KEY  (id),
            KEY user_id (user_id),
            KEY status (status)
        ) $charset_collate;";

        $sql2 = "CREATE TABLE IF NOT EXISTS $sends (
            id bigint(20) unsigned NOT NULL AUTO_INCREMENT,
            campaign_id bigint(20) unsigned NOT NULL,
            user_id bigint(20) unsigned NOT NULL,
            lead_email varchar(255) NOT NULL,
            lead_name varchar(255) NULL,
            subject text NULL,
            status varchar(32) NOT NULL DEFAULT 'queued',
            error text NULL,
            created_at datetime NOT NULL,
            sent_at datetime NULL,
            PRIMARY KEY  (id),
            KEY campaign_id (campaign_id),
            KEY user_id (user_id),
            KEY status (status)
        ) $charset_collate;";

        $sql3 = "CREATE TABLE IF NOT EXISTS $signatures (
            id bigint(20) unsigned NOT NULL AUTO_INCREMENT,
            user_id bigint(20) unsigned NOT NULL,
            account varchar(255) NULL,
            name varchar(255) NULL,
            designation varchar(255) NULL,
            social_links text NULL,
            custom_links text NULL,
            logo_url text NULL,
            website_url text NULL,
            theme_color varchar(32) NULL,
            is_default tinyint(1) DEFAULT 0,
            created_at datetime NOT NULL,
            updated_at datetime NOT NULL,
            PRIMARY KEY  (id),
            UNIQUE KEY uniq_user_account (user_id, account),
            KEY user_id (user_id)
        ) $charset_collate;";

        dbDelta($sql1);
        dbDelta($sql2);
        dbDelta($sql3);
    }

    public function generate_campaign() {
        if (!check_ajax_referer('vmo_builder_nonce', 'security', false)) {
            wp_send_json_error(['message' => 'Security check failed', 'status' => 'invalid_nonce']);
        }
        if (!is_user_logged_in()) wp_send_json_error(['message' => 'Not logged in'], 401);
        $user_id = get_current_user_id();

        if (!function_exists('vmo_require_profile_or_error')) {
            $consultation_profile_file = plugin_dir_path(__FILE__) . 'consultation-profile.php';
            if (file_exists($consultation_profile_file) && is_readable($consultation_profile_file)) {
                try {
                    require_once $consultation_profile_file;
                } catch (Exception $e) {
                    if (defined('WP_DEBUG') && WP_DEBUG) {
                        error_log('VMO: Failed to load consultation profile in email marketing: ' . $e->getMessage());
                    }
                }
            }
        }
        vmo_require_profile_or_error($user_id);

        // Get install_id for token operations - auto-create if needed
        global $wpdb;
        $activations_table = $wpdb->prefix . 'vmo_manager_activations';
        
        // ✅ Use helper function to get or create activation
        $install_id = null;
        if (function_exists('vmo_get_user_install_id')) {
            $install_id = vmo_get_user_install_id($user_id);
        } else {
            // Fallback: check table directly
            $table_exists = $wpdb->get_var($wpdb->prepare("SHOW TABLES LIKE %s", $activations_table));
            if ($table_exists) {
                $install_id = $wpdb->get_var($wpdb->prepare(
                    "SELECT install_id FROM {$activations_table} WHERE user_id = %d LIMIT 1",
                    $user_id
                ));
            }
        }
        
        if (!$install_id) {
            wp_send_json_error(['message' => 'Installation not found. Please activate your plan first.']);
        }

        // Check if user has enough tokens for campaign creation (600 tokens)
        $activation = $wpdb->get_row($wpdb->prepare(
            "SELECT token_balance FROM {$activations_table} WHERE install_id = %s",
            $install_id
        ));
        
        if (!$activation || intval($activation->token_balance) < 600) {
            wp_send_json_error([
                'message' => 'Insufficient tokens. Campaign creation requires 600 tokens.',
                'tokens_needed' => 600,
                'tokens_available' => $activation ? intval($activation->token_balance) : 0
            ]);
        }

        $api_key = get_option('vmo_openai_api_key');
        if (!$api_key) wp_send_json_error(['message' => 'OpenAI API key missing']);

        $profile = function_exists('vmo_get_consultation_profile') ? vmo_get_consultation_profile($user_id) : [];
        $business_name = sanitize_text_field($profile['business_name'] ?? ($profile['company'] ?? 'Your Business'));
        $industry = sanitize_text_field($profile['industry'] ?? 'General');
        $location = sanitize_text_field($profile['location'] ?? 'Local');
        $offer = sanitize_text_field($profile['offer'] ?? ($profile['value_proposition'] ?? 'your core service'));

        $lead_count = max(10, min(50, intval($_POST['lead_count'] ?? 25)));
        
        // ✅ NEW: Use our ultra-competitive AI campaign generator
        $campaign_data = [
            'business_data' => [
                'business_name' => $business_name,
                'industry' => $industry,
                'location' => $location,
                'brand_voice' => 'professional and engaging'
            ],
            'type' => 'promotional',
            'audience' => $profile['target_audience'] ?? 'local customers'
        ];
        
        // ✅ NEW: Use our ultra-competitive AI campaign generator
        $campaign = $this->campaign_generator->generate_campaign($install_id, $campaign_data);
        
        if (!$campaign || !$campaign['success']) {
            wp_send_json_error(['message' => 'Failed to generate campaign']);
        }
        
        // ✅ TOKEN DEDUCTION v8.1.0: Charge for email campaign AI generation (after successful generation)
        if (function_exists('vmo_deduct_tokens_for_operation')) {
            vmo_deduct_tokens_for_operation($user_id, 'email_campaign');
        } elseif (function_exists('vmo_deduct_tokens')) {
            // Fallback to direct deduction
            vmo_deduct_tokens($user_id, 800, 'email_campaign', 'AI email campaign generation');
        }
        
        // Generate A/B test variants (we get multiple subject lines)
        $ab_subjects = isset($campaign['ab_test_subjects']) ? $campaign['ab_test_subjects'] : [$campaign['subject']];
        
        // Create 4 campaign options with different subject lines and preview texts
        $options = [];
        for ($i = 0; $i < 4; $i++) {
            $subject_variant = isset($ab_subjects[$i]) ? $ab_subjects[$i] : $campaign['subject'];
            $preview_variant = $campaign['preview_text'];
            
            // Slight HTML variations if needed (for true A/B testing)
            $html_variant = $campaign['html_content'];
            
            $options[] = [
                'subject' => $subject_variant,
                'preheader' => $preview_variant,
                'html' => $html_variant,
                'text' => $campaign['plain_text']
            ];
        }
        
        // Recipient list from the CRM contacts table (never generate fake recipients).
        $contacts_table = $wpdb->prefix . 'vmo_contacts';
        $has_contacts = (bool) $wpdb->get_var($wpdb->prepare("SHOW TABLES LIKE %s", $wpdb->esc_like($contacts_table)));
        if (!$has_contacts) {
            wp_send_json_error(['message' => 'Contacts table missing. Please deactivate/reactivate the plugin to run database setup.']);
        }

        $existing_leads = $wpdb->get_results(
            $wpdb->prepare(
                "SELECT *
                 FROM {$contacts_table}
                 WHERE user_id = %d
                   AND lifecycle_stage <> 'customer'
                   AND email IS NOT NULL AND email <> ''
                 ORDER BY updated_at DESC, created_at DESC
                 LIMIT %d",
                $user_id,
                $lead_count
            ),
            ARRAY_A
        );
        
        $leads = [];
        foreach (($existing_leads ?: []) as $lead) {
            $lead_name = $lead['full_name'] ?? '';
            if (empty($lead_name)) {
                $lead_name = trim(($lead['first_name'] ?? '') . ' ' . ($lead['last_name'] ?? ''));
            }
            $leads[] = [
                'name' => sanitize_text_field($lead_name),
                'email' => sanitize_email($lead['email'] ?? ''),
                'company' => sanitize_text_field($lead['company'] ?? ''),
                'notes' => sanitize_text_field($lead['notes'] ?? '')
            ];
        }

        if (!count($leads)) {
            wp_send_json_error(['message' => 'No leads found in CRM. Import contacts first (Lead Generation → Upload CSV).']);
        }

        // Save draft campaign
        global $wpdb; $campaigns = $wpdb->prefix . 'vmo_email_campaigns';
        $campaign_payload = [
            'profile' => [ 'business_name' => $business_name, 'industry' => $industry, 'location' => $location, 'offer' => $offer ],
            'options' => $options,
            'leads'   => $leads,
        ];
        // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
        $wpdb->insert($campaigns, [
            'user_id' => $user_id,
            'title' => $business_name . ' - Email Campaign Draft',
            'payload' => wp_json_encode($campaign_payload),
            'status' => 'draft',
            'created_at' => current_time('mysql'),
            'updated_at' => current_time('mysql'),
        ]);
        $campaign_id = $wpdb->insert_id;

        wp_send_json_success([
            'campaign_id' => $campaign_id,
            'options' => $options,
            'leads' => $leads,
        ]);
    }

    public function send_campaign() {
        if (!$this->verify_ajax_request()) {
            wp_send_json_error(['message' => 'Security check failed', 'status' => 'invalid_nonce']);
        }
        if (!is_user_logged_in()) {
            wp_send_json_error(['message' => 'Not logged in'], 401);
        }

        $user_id = get_current_user_id();
        $campaign_id = intval($_POST['campaign_id'] ?? 0);
        $selected_index = intval($_POST['selected_index'] ?? -1);
        if ($campaign_id <= 0 || $selected_index < 0) {
            wp_send_json_error(['message' => 'Missing campaign or selection']);
        }

        global $wpdb;
        $campaigns = $wpdb->prefix . 'vmo_email_campaigns';
        $sends = $wpdb->prefix . 'vmo_email_sends';

        $row = $wpdb->get_row($wpdb->prepare("SELECT * FROM $campaigns WHERE id = %d AND user_id = %d", $campaign_id, $user_id));
        if (!$row) {
            wp_send_json_error(['message' => 'Campaign not found']);
        }

        $payload = json_decode($row->payload ?? '', true);
        $options = is_array($payload) ? ($payload['options'] ?? []) : [];
        $leads = is_array($payload) ? ($payload['leads'] ?? []) : [];
        if (!is_array($options) || !isset($options[$selected_index]) || !is_array($options[$selected_index])) {
            wp_send_json_error(['message' => 'Invalid selection']);
        }

        $option = $options[$selected_index];
        $subject = sanitize_text_field($option['subject'] ?? 'Email Campaign');
        $html = (string) ($option['html'] ?? ($option['text'] ?? ''));
        if (!$html) {
            wp_send_json_error(['message' => 'Campaign content is empty']);
        }

        $sender_role = isset($_POST['sender_role']) ? sanitize_key(wp_unslash($_POST['sender_role'])) : 'marketing';
        $sender_context = $this->identity_manager->get_sender_for_campaign($user_id, $sender_role);
        if (!empty($sender_context['signature']['html'])) {
            $html = $this->identity_manager->append_signature_to_html($html, $sender_context['signature']['html']);
        }

        $recipients = [];
        if (is_array($leads)) {
            foreach ($leads as $lead) {
                if (!is_array($lead)) {
                    continue;
                }
                $email = sanitize_email($lead['email'] ?? '');
                if ($email) {
                    $recipients[] = $email;
                }
            }
        }
        $recipients = array_values(array_unique($recipients));
        if (empty($recipients)) {
            wp_send_json_error(['message' => 'No recipients found for this campaign']);
        }

        $router = VMO_Email_Router::get_instance();
        $from_email = sanitize_email($sender_context['email'] ?? '');
        $from_name = sanitize_text_field($sender_context['name'] ?? '');
        $reply_to = sanitize_email($sender_context['reply_to'] ?? '');

        $sent = 0;
        $failed_list = [];
        $invalid_list = [];

        foreach ($recipients as $to) {
            $to = sanitize_email($to);
            if (!$to || !is_email($to)) {
                $invalid_list[] = $to;
                continue;
            }

            $headers = ['Content-Type: text/html; charset=UTF-8'];
            if ($reply_to) {
                $headers[] = 'Reply-To: ' . $reply_to;
            }

            $args = [
                'headers' => $headers,
                'charge_tokens' => true,
            ];
            if ($from_email) {
                $args['from_email'] = $from_email;
            }
            if ($from_name) {
                $args['from_name'] = $from_name;
            }

            $res = $router->send_email($to, $subject, $html, 'marketing', $args);
            $was_sent = (is_array($res) && !empty($res['success']));
            if (!$was_sent) {
                $failed_list[] = $to;
            } else {
                $sent++;
            }

            // Track each recipient
            // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
            $wpdb->insert($sends, [
                'campaign_id' => $campaign_id,
                'user_id' => $user_id,
                'lead_email' => $to,
                'lead_name' => '',
                'subject' => $subject,
                'status' => $was_sent ? 'sent' : 'failed',
                'error' => $was_sent ? null : (in_array($to, $invalid_list, true) ? 'invalid_email' : 'send_failed'),
                'created_at' => current_time('mysql'),
                'sent_at' => $was_sent ? current_time('mysql') : null,
            ]);
        }

        $errors = array_values(array_unique(array_merge($failed_list, $invalid_list)));
        $failed = count($errors);

        // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
        $wpdb->update(
            $campaigns,
            [
                'status' => ($sent > 0 && $failed === 0) ? 'sent' : 'partial',
                'updated_at' => current_time('mysql'),
            ],
            ['id' => $campaign_id]
        );

        wp_send_json_success([
            'sent' => $sent,
            'failed' => $failed,
            'failed_list' => $errors,
        ]);
    }

    public function get_overview() {
        if (!$this->verify_ajax_request()) {
            wp_send_json_error(['message' => 'Security check failed', 'status' => 'invalid_nonce']);
        }
        if (!is_user_logged_in()) {
            wp_send_json_error(['message' => 'Not logged in'], 401);
        }
        $user_id = get_current_user_id();

        global $wpdb; 
        $campaigns = $wpdb->prefix . 'vmo_email_campaigns';
        $sends     = $wpdb->prefix . 'vmo_email_sends';

        // Drafts count
        $drafts_count = intval($wpdb->get_var($wpdb->prepare("SELECT COUNT(*) FROM $campaigns WHERE user_id = %d AND status = 'draft'", $user_id)));

        // Last 30 days sends series
        $rows = $wpdb->get_results($wpdb->prepare(
            "SELECT DATE(created_at) as d, COUNT(*) as c FROM $sends WHERE user_id = %d AND status = 'sent' AND created_at >= DATE_SUB(UTC_TIMESTAMP(), INTERVAL 30 DAY) GROUP BY DATE(created_at) ORDER BY d",
            $user_id
        ), ARRAY_A);
        $byDay = [];
        foreach ($rows as $r) { $byDay[$r['d']] = intval($r['c']); }
        // Build continuous 30-day series ending today
        $series_sent = [];
        $today = new DateTime('now', new DateTimeZone('UTC'));
        for ($i = 29; $i >= 0; $i--) {
            $d = clone $today; $d->modify("-$i day");
            $key = $d->format('Y-m-d');
            $series_sent[] = isset($byDay[$key]) ? $byDay[$key] : 0;
        }
        $sent_30 = array_sum($series_sent);

        // Opens and clicks not tracked yet; return zero arrays of same length for truthful data
        $series_open = array_fill(0, count($series_sent), 0);
        $series_click = array_fill(0, count($series_sent), 0);

        // Recent campaigns with basic stats
        $recent = $wpdb->get_results($wpdb->prepare("SELECT id, title, status, created_at FROM $campaigns WHERE user_id = %d ORDER BY created_at DESC LIMIT 25", $user_id), ARRAY_A);
        $campaigns_list = [];
        if ($recent) {
            // Preload send counts per campaign in one query
            $ids = array_map(function($r){ return intval($r['id']); }, $recent);
            if (!empty($ids)) {
                $in = implode(',', array_fill(0, count($ids), '%d'));
                $sql = $wpdb->prepare("SELECT campaign_id, SUM(status='sent') as sent FROM $sends WHERE campaign_id IN ($in) GROUP BY campaign_id", ...$ids);
                $sendCounts = [];
                // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared, WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
                foreach ($wpdb->get_results($sql, ARRAY_A) as $row) { $sendCounts[intval($row['campaign_id'])] = intval($row['sent']); }
            } else { $sendCounts = []; }
            foreach ($recent as $r) {
                $cid = intval($r['id']);
                $campaigns_list[] = [
                    'id' => $cid,
                    'title' => $r['title'] ?: 'Campaign',
                    'status' => $r['status'] ?: 'draft',
                    'created_at' => $r['created_at'],
                    'sent' => isset($sendCounts[$cid]) ? $sendCounts[$cid] : 0,
                    'open' => 0,
                    'click' => 0,
                ];
            }
        }

        wp_send_json_success([
            'drafts_count' => $drafts_count,
            'sent_30' => $sent_30,
            'opened_30' => 0,
            'clicked_30' => 0,
            'sent_series' => $series_sent,
            'open_series' => $series_open,
            'click_series' => $series_click,
            'campaigns' => $campaigns_list,
        ]);
    }
}

// Initialize
// Instantiation is handled in the main plugin file via plugins_loaded hook.
// This prevents premature loading issues.
