#!/usr/bin/env php
<?php
/**
 * Process AI Monitor Email Queue
 * Runs every minute via cron. Sends queued notification emails with 15-minute
 * batching window per subscription to avoid flooding customers.
 *
 * Max 50 emails per run to prevent long-running cron jobs.
 */

// Prevent concurrent runs
$lockFile = fopen('/tmp/whp-email-queue.lock', 'c');
if (!$lockFile || !flock($lockFile, LOCK_EX | LOCK_NB)) {
    // Another instance is running
    exit(0);
}

// Determine the correct web directory
if (file_exists('/docker/whp/web/libs/smtp_mailer.php')) {
    $webDir = '/docker/whp/web';
} else {
    $webDir = dirname(__DIR__) . '/web-files';
}

try {
    // Load SMTP mailer
    require_once($webDir . '/libs/smtp_mailer.php');

    // Load email templates
    require_once($webDir . '/includes/email-templates/issue-digest.php');

    // Panel-URL builder (shared with process-log-review.php)
    require_once(__DIR__ . '/whp_panel_url.php');

    // Check if SMTP is configured and enabled
    $smtpConfig = SmtpMailer::loadConfig();
    if ($smtpConfig === null) {
        // SMTP not configured or disabled — exit silently
        flock($lockFile, LOCK_UN);
        fclose($lockFile);
        exit(0);
    }

    // Connect to database (use same extraction method as config.php)
    $password = trim(shell_exec('cat /root/.my.cnf | grep password | cut -f2- -d='));
    $db = new PDO('mysql:host=127.0.0.1;dbname=whp;charset=utf8mb4', 'root', $password);
    $db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);

    // Fetch all queued emails that haven't exhausted attempts, ordered for grouping
    $stmt = $db->query("
        SELECT *
        FROM whp.ai_monitor_email_queue
        WHERE status = 'queued'
          AND attempts < max_attempts
        ORDER BY subscription_id, created_at
        LIMIT 200
    ");
    $allQueued = $stmt->fetchAll(PDO::FETCH_ASSOC);

    if (empty($allQueued)) {
        flock($lockFile, LOCK_UN);
        fclose($lockFile);
        exit(0);
    }

    // Group by subscription_id
    $grouped = [];
    foreach ($allQueued as $row) {
        $subId = $row['subscription_id'];
        $grouped[$subId][] = $row;
    }

    // Check the 15-minute batching window: only process a subscription group
    // if its earliest queued email is at least 15 minutes old (giving time for
    // more to arrive), OR if there's only one email for the subscription.
    $fifteenMinutesAgo = date('Y-m-d H:i:s', strtotime('-15 minutes'));

    $emailsSent = 0;
    $emailsFailed = 0;
    $maxPerRun = 50;

    foreach ($grouped as $subscriptionId => $emails) {
        if ($emailsSent >= $maxPerRun) {
            break;
        }

        // For single emails, send immediately (no batching needed).
        // For multiple emails, wait until the earliest one is 15+ minutes old.
        if (count($emails) > 1) {
            $earliest = $emails[0]['created_at'];
            if ($earliest > $fifteenMinutesAgo) {
                // Window still open — more emails may arrive. Skip for now.
                continue;
            }
        }

        if (count($emails) === 1) {
            // Single email — send directly using pre-rendered content
            $email = $emails[0];
            $sent = sendSingleEmail($db, $email, $smtpConfig);
            if ($sent) {
                $emailsSent++;
            } else {
                $emailsFailed++;
            }
        } else {
            // Multiple emails — combine into a digest
            $sent = sendDigestEmail($db, $emails, $subscriptionId, $smtpConfig);
            if ($sent) {
                $emailsSent += count($emails);
            } else {
                $emailsFailed += count($emails);
            }
        }
    }

    if ($emailsSent > 0 || $emailsFailed > 0) {
        echo date('Y-m-d H:i:s') . " Email queue processed: {$emailsSent} sent, {$emailsFailed} failed\n";
    }

} catch (Exception $e) {
    echo date('Y-m-d H:i:s') . " ERROR: " . $e->getMessage() . "\n";
} finally {
    flock($lockFile, LOCK_UN);
    fclose($lockFile);
}

/**
 * Send a single queued email using its pre-rendered body content.
 */
function sendSingleEmail(PDO $db, array $email, array $smtpConfig): bool {
    $id = $email['id'];

    try {
        // Mark as sending
        $db->prepare("UPDATE whp.ai_monitor_email_queue SET status = 'sending' WHERE id = ?")
           ->execute([$id]);

        $mailer = new SmtpMailer($smtpConfig);
        $result = $mailer->send(
            $email['recipient_email'],
            $email['subject'],
            $email['body_html'],
            $email['body_text'] ?? ''
        );

        if ($result['success']) {
            $db->prepare("
                UPDATE whp.ai_monitor_email_queue
                SET status = 'sent', sent_at = NOW()
                WHERE id = ?
            ")->execute([$id]);
            return true;
        } else {
            $db->prepare("
                UPDATE whp.ai_monitor_email_queue
                SET status = 'queued',
                    attempts = attempts + 1,
                    last_attempt_at = NOW(),
                    error_message = ?
                WHERE id = ?
            ")->execute([$result['error'] ?? 'Unknown error', $id]);
            echo date('Y-m-d H:i:s') . " Failed to send email #{$id}: " . ($result['error'] ?? 'Unknown') . "\n";
            return false;
        }
    } catch (Exception $e) {
        $db->prepare("
            UPDATE whp.ai_monitor_email_queue
            SET status = 'queued',
                attempts = attempts + 1,
                last_attempt_at = NOW(),
                error_message = ?
            WHERE id = ?
        ")->execute([$e->getMessage(), $id]);
        echo date('Y-m-d H:i:s') . " Exception sending email #{$id}: " . $e->getMessage() . "\n";
        return false;
    }
}

/**
 * Combine multiple queued emails for a subscription into a single digest email.
 */
function sendDigestEmail(PDO $db, array $emails, int $subscriptionId, array $smtpConfig): bool {
    $ids = array_column($emails, 'id');
    $placeholders = implode(',', array_fill(0, count($ids), '?'));

    try {
        // Mark all as sending
        $db->prepare("UPDATE whp.ai_monitor_email_queue SET status = 'sending' WHERE id IN ({$placeholders})")
           ->execute($ids);

        // Get subscription and site info for the digest template
        $subStmt = $db->prepare("
            SELECT sub.id, sub.notification_email, s.site_name, d.domain_name as primary_domain
            FROM whp.ai_monitor_subscriptions sub
            JOIN whp.sites s ON sub.site_id = s.id
            JOIN whp.domains d ON s.primary_domain_id = d.id
            WHERE sub.id = ?
        ");
        $subStmt->execute([$subscriptionId]);
        $subInfo = $subStmt->fetch(PDO::FETCH_ASSOC);

        if (!$subInfo) {
            // Subscription not found — mark all as failed
            $db->prepare("
                UPDATE whp.ai_monitor_email_queue
                SET status = 'queued',
                    attempts = attempts + 1,
                    last_attempt_at = NOW(),
                    error_message = 'Subscription not found for digest'
                WHERE id IN ({$placeholders})
            ")->execute($ids);
            return false;
        }

        // Collect issue details from the queued emails' associated issues
        $issueIds = [];
        foreach ($emails as $email) {
            if (!empty($email['issue_id'])) {
                $issueIds[] = $email['issue_id'];
            }
        }

        $issues = [];
        if (!empty($issueIds)) {
            $issuePlaceholders = implode(',', array_fill(0, count($issueIds), '?'));
            $issueStmt = $db->prepare("
                SELECT severity, title, diagnosis, recommendation
                FROM whp.ai_monitor_issues
                WHERE id IN ({$issuePlaceholders})
            ");
            $issueStmt->execute($issueIds);
            $issues = $issueStmt->fetchAll(PDO::FETCH_ASSOC);
        }

        // If we couldn't load issues from the database, extract from original email subjects
        if (empty($issues)) {
            foreach ($emails as $email) {
                $issues[] = [
                    'severity' => 'info',
                    'title'    => $email['subject'] ?? 'Monitoring Alert',
                    'diagnosis' => '',
                    'recommendation' => '',
                ];
            }
        }

        // Deep-link URL for the "View Full Report" button. Digest emails
        // cover the whole subscription (multiple issues), so link to the
        // site-scoped list rather than a specific issue.
        $siteId = (int)($subInfo['site_id'] ?? 0);
        $query = 'page=ai-monitor-customer' . ($siteId ? '&site_id=' . $siteId : '');
        $dashboardUrl = whp_panel_url($query);

        // Render digest email
        $bodyHtml = render_issue_digest([
            'site_name'     => $subInfo['site_name'] ?? $subInfo['primary_domain'],
            'issues'        => $issues,
            'issue_count'   => count($issues),
            'dashboard_url' => $dashboardUrl,
        ]);

        $siteName = $subInfo['site_name'] ?? $subInfo['primary_domain'];
        $subject = "AI Monitor: " . count($issues) . " issues detected for {$siteName}";
        $bodyText = "AI Monitor Digest for {$siteName}\n\n"
            . count($issues) . " issues were detected. View your dashboard for details.\n";

        $recipient = $emails[0]['recipient_email'];

        $mailer = new SmtpMailer($smtpConfig);
        $result = $mailer->send($recipient, $subject, $bodyHtml, $bodyText);

        if ($result['success']) {
            $db->prepare("
                UPDATE whp.ai_monitor_email_queue
                SET status = 'sent', sent_at = NOW()
                WHERE id IN ({$placeholders})
            ")->execute($ids);
            echo date('Y-m-d H:i:s') . " Sent digest ({$subscriptionId}): " . count($emails) . " emails combined\n";
            return true;
        } else {
            $db->prepare("
                UPDATE whp.ai_monitor_email_queue
                SET status = 'queued',
                    attempts = attempts + 1,
                    last_attempt_at = NOW(),
                    error_message = ?
                WHERE id IN ({$placeholders})
            ")->execute(array_merge([$result['error'] ?? 'Unknown error'], $ids));
            echo date('Y-m-d H:i:s') . " Failed to send digest ({$subscriptionId}): " . ($result['error'] ?? 'Unknown') . "\n";
            return false;
        }
    } catch (Exception $e) {
        $db->prepare("
            UPDATE whp.ai_monitor_email_queue
            SET status = 'queued',
                attempts = attempts + 1,
                last_attempt_at = NOW(),
                error_message = ?
            WHERE id IN ({$placeholders})
        ")->execute(array_merge([$e->getMessage()], $ids));
        echo date('Y-m-d H:i:s') . " Exception sending digest ({$subscriptionId}): " . $e->getMessage() . "\n";
        return false;
    }
}
