<?php
declare(strict_types=1);
// ==================================================
// Nuclear Fancy Pants Edition™ -- NUCLEAR+++
// File: /home/ploi/automarketer-ai.com/public/wp-content/plugins/automarketer-ai/includes/class-review-velocity.php
// Description: Tracks review volume over time and emails the admin on spikes or review-bomb events - NUCLEAR+++
// Last Edited: 2026-05-20
// ==================================================
namespace AutoMarketerAI;
defined('ABSPATH') || exit;

class ReviewVelocity
{
    private const CRON_HOOK       = 'amai_review_velocity_check';
    private const SPIKE_COOLDOWN  = 'amai_rv_spike_alerted';
    private const BOMB_COOLDOWN   = 'amai_rv_bomb_alerted';
    private const COOLDOWN_SECS   = DAY_IN_SECONDS;
    // Minimum daily average before spike detection fires.
    // Avoids false positives on installs with zero history.
    private const MIN_AVG_FOR_SPIKE = 1.0;

    // --------------------------------------------------
    // Register daily cron. WordPress 'daily' interval
    // is built-in -- no cron_schedules filter needed.
    // --------------------------------------------------
    public static function register(): void
    {
        add_action(self::CRON_HOOK, [self::class, 'run']);
        if (!wp_next_scheduled(self::CRON_HOOK)) {
            wp_schedule_event(time(), 'daily', self::CRON_HOOK);
        }
    }

    public static function deregister(): void
    {
        $timestamp = wp_next_scheduled(self::CRON_HOOK);
        if ($timestamp !== false) {
            wp_unschedule_event($timestamp, self::CRON_HOOK);
        }
    }

    // --------------------------------------------------
    // Cron entry point.
    // --------------------------------------------------
    public static function run(): void
    {
        if (get_option('amai_review_velocity_alerts_enabled', '1') !== '1') {
            return;
        }

        global $wpdb;
        $table = $wpdb->prefix . 'amai_reviews';

        if ($wpdb->get_var("SHOW TABLES LIKE '{$table}'") !== $table) {
            return;
        }

        $today_count = (int) $wpdb->get_var(
            $wpdb->prepare(
                "SELECT COUNT(*) FROM `{$table}`
                  WHERE status != 'spam'
                    AND review_date >= %s",
                gmdate('Y-m-d') . ' 00:00:00'
            )
        );

        if ($today_count === 0) {
            return;
        }

        // Daily average over the prior 30 days (excluding today).
        $avg_result = (float) $wpdb->get_var(
            $wpdb->prepare(
                "SELECT COUNT(*) / 30.0 FROM `{$table}`
                  WHERE status != 'spam'
                    AND review_date >= %s
                    AND review_date < %s",
                gmdate('Y-m-d', strtotime('-30 days')) . ' 00:00:00',
                gmdate('Y-m-d') . ' 00:00:00'
            )
        );

        // Spike: today >= 2x the 30-day daily average (minimum avg threshold applies).
        if (
            $avg_result >= self::MIN_AVG_FOR_SPIKE &&
            $today_count >= (int) round($avg_result * 2) &&
            get_transient(self::SPIKE_COOLDOWN) === false
        ) {
            self::sendSpikeAlert($today_count, $avg_result);
            set_transient(self::SPIKE_COOLDOWN, '1', self::COOLDOWN_SECS);
        }

        // Review bomb: 3 or more 1-star reviews today.
        $bomb_count = (int) $wpdb->get_var(
            $wpdb->prepare(
                "SELECT COUNT(*) FROM `{$table}`
                  WHERE status != 'spam'
                    AND rating = 1
                    AND review_date >= %s",
                gmdate('Y-m-d') . ' 00:00:00'
            )
        );

        if ($bomb_count >= 3 && get_transient(self::BOMB_COOLDOWN) === false) {
            self::sendBombAlert($bomb_count);
            set_transient(self::BOMB_COOLDOWN, '1', self::COOLDOWN_SECS);
        }
    }

    // --------------------------------------------------
    // Weekly review counts for the last 12 weeks.
    // Returns array of ['week_start' => 'Y-m-d', 'count' => int].
    // week_start is Monday of each ISO week.
    // --------------------------------------------------
    public static function getWeeklyBuckets(): array
    {
        global $wpdb;
        $table = $wpdb->prefix . 'amai_reviews';

        if ($wpdb->get_var("SHOW TABLES LIKE '{$table}'") !== $table) {
            return [];
        }

        $rows = $wpdb->get_results(
            $wpdb->prepare(
                "SELECT
                    DATE_SUB(DATE(review_date), INTERVAL (DAYOFWEEK(review_date) + 5) %% 7 DAY) AS week_start,
                    COUNT(*) AS cnt
                   FROM `{$table}`
                  WHERE status != 'spam'
                    AND review_date >= %s
                  GROUP BY week_start
                  ORDER BY week_start ASC",
                gmdate('Y-m-d', strtotime('-83 days')) . ' 00:00:00'
            ),
            ARRAY_A
        );

        if (!is_array($rows)) {
            return [];
        }

        // Build a full 12-week scaffold so missing weeks show as 0.
        $buckets = [];
        for ($i = 11; $i >= 0; $i--) {
            $monday = gmdate('Y-m-d', strtotime('monday this week -' . $i . ' weeks'));
            $buckets[$monday] = 0;
        }

        foreach ($rows as $row) {
            $ws = (string) ($row['week_start'] ?? '');
            if (isset($buckets[$ws])) {
                $buckets[$ws] = (int) $row['cnt'];
            }
        }

        $out = [];
        foreach ($buckets as $week_start => $count) {
            $out[] = ['week_start' => $week_start, 'count' => $count];
        }
        return $out;
    }

    // --------------------------------------------------
    // Send spike alert email.
    // --------------------------------------------------
    private static function sendSpikeAlert(int $today_count, float $avg): void
    {
        $admin_email = (string) get_option('admin_email', '');
        if ($admin_email === '') {
            return;
        }
        $site_name = (string) get_bloginfo('name');
        $subject   = $site_name . ': You\'re getting a lot of reviews today - ' . $today_count . ' so far';

        ob_start();
        self::renderSpikeEmail($site_name, $today_count, $avg);
        $body = ob_get_clean();

        add_filter('wp_mail_content_type', static fn() => 'text/html');
        wp_mail($admin_email, $subject, (string) $body);
        remove_all_filters('wp_mail_content_type');
    }

    // --------------------------------------------------
    // Send review-bomb alert email.
    // --------------------------------------------------
    private static function sendBombAlert(int $bomb_count): void
    {
        $admin_email = (string) get_option('admin_email', '');
        if ($admin_email === '') {
            return;
        }
        $site_name = (string) get_bloginfo('name');
        $subject   = $site_name . ': Heads up - ' . $bomb_count . ' one-star reviews today';

        ob_start();
        self::renderBombEmail($site_name, $bomb_count);
        $body = ob_get_clean();

        add_filter('wp_mail_content_type', static fn() => 'text/html');
        wp_mail($admin_email, $subject, (string) $body);
        remove_all_filters('wp_mail_content_type');
    }

    // --------------------------------------------------
    // Spike alert email HTML.
    // --------------------------------------------------
    private static function renderSpikeEmail(string $site_name, int $today_count, float $avg): void
    {
        $inbox_url  = admin_url('admin.php?page=automarketer-ai-reputation');
        $avg_label  = number_format($avg, 1);
        $review_lbl = $today_count . ' review' . ($today_count !== 1 ? 's' : '');
        ?>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Review spike alert</title>
</head>
<body style="margin:0;padding:0;background:#F9FAFB;font-family:'DM Sans',Arial,sans-serif;color:#1C1917;">
<table width="100%" cellpadding="0" cellspacing="0" style="background:#F9FAFB;">
  <tr>
    <td align="center" style="padding:40px 16px;">
      <table width="560" cellpadding="0" cellspacing="0" style="background:#FFFFFF;border-radius:16px;border:1.5px solid #E7DDD5;overflow:hidden;">
        <tr><td style="background:#D97757;height:6px;font-size:0;line-height:0;">&nbsp;</td></tr>
        <tr>
          <td style="padding:32px 40px 8px;">
            <p style="margin:0 0 4px;font-size:12px;font-weight:700;letter-spacing:.08em;text-transform:uppercase;color:#D97757;">Review spike</p>
            <h1 style="margin:0 0 8px;font-size:22px;font-weight:800;color:#1C1917;line-height:1.3;">You're getting a lot of attention today</h1>
            <p style="margin:0 0 24px;font-size:15px;color:#78716C;line-height:1.6;">
              <?php echo esc_html($review_lbl); ?> have come in today - well above your usual pace of <?php echo esc_html($avg_label); ?> per day. Something is resonating. Head to your inbox and respond while it's fresh.
            </p>
            <table cellpadding="0" cellspacing="0" style="margin:0 0 24px;background:#FFF7F4;border-radius:10px;border:1.5px solid #F3D5C8;width:100%;">
              <tr>
                <td style="padding:16px 20px;">
                  <table cellpadding="0" cellspacing="0" width="100%">
                    <tr>
                      <td style="font-size:13px;color:#78716C;padding-bottom:4px;">Reviews today</td>
                      <td align="right" style="font-size:13px;font-weight:600;color:#1C1917;"><?php echo esc_html((string) $today_count); ?></td>
                    </tr>
                    <tr>
                      <td style="font-size:13px;color:#78716C;">Daily average (30 days)</td>
                      <td align="right" style="font-size:13px;font-weight:600;color:#1C1917;"><?php echo esc_html($avg_label); ?></td>
                    </tr>
                  </table>
                </td>
              </tr>
            </table>
            <table cellpadding="0" cellspacing="0">
              <tr>
                <td style="background:#D97757;border-radius:8px;">
                  <a href="<?php echo esc_url($inbox_url); ?>" style="display:inline-block;padding:12px 28px;font-size:14px;font-weight:700;color:#FFFFFF;text-decoration:none;">Open review inbox</a>
                </td>
              </tr>
            </table>
          </td>
        </tr>
        <tr>
          <td style="padding:24px 40px 32px;border-top:1px solid #F5F5F4;margin-top:24px;">
            <p style="margin:0;font-size:12px;color:#A8A29E;line-height:1.6;">You are receiving this because review velocity alerts are enabled in <?php echo esc_html($site_name); ?> Settings.</p>
          </td>
        </tr>
      </table>
    </td>
  </tr>
</table>
</body>
</html>
        <?php
    }

    // --------------------------------------------------
    // Review-bomb alert email HTML.
    // --------------------------------------------------
    private static function renderBombEmail(string $site_name, int $bomb_count): void
    {
        $inbox_url  = admin_url('admin.php?page=automarketer-ai-reputation');
        $review_lbl = $bomb_count . ' one-star review' . ($bomb_count !== 1 ? 's' : '');
        ?>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Review alert</title>
</head>
<body style="margin:0;padding:0;background:#F9FAFB;font-family:'DM Sans',Arial,sans-serif;color:#1C1917;">
<table width="100%" cellpadding="0" cellspacing="0" style="background:#F9FAFB;">
  <tr>
    <td align="center" style="padding:40px 16px;">
      <table width="560" cellpadding="0" cellspacing="0" style="background:#FFFFFF;border-radius:16px;border:1.5px solid #E7DDD5;overflow:hidden;">
        <tr><td style="background:#EF4444;height:6px;font-size:0;line-height:0;">&nbsp;</td></tr>
        <tr>
          <td style="padding:32px 40px 8px;">
            <p style="margin:0 0 4px;font-size:12px;font-weight:700;letter-spacing:.08em;text-transform:uppercase;color:#EF4444;">Heads up</p>
            <h1 style="margin:0 0 8px;font-size:22px;font-weight:800;color:#1C1917;line-height:1.3;"><?php echo esc_html(ucfirst($review_lbl)); ?> today</h1>
            <p style="margin:0 0 24px;font-size:15px;color:#78716C;line-height:1.6;">
              A cluster of low-rated reviews has come in. The best move is a calm, professional reply to each one - it shows everyone reading that you take feedback seriously. AutoMarketer AI has draft replies ready for you.
            </p>
            <table cellpadding="0" cellspacing="0" style="margin:0 0 16px;background:#FEF2F2;border-radius:10px;border:1.5px solid #FECACA;width:100%;">
              <tr>
                <td style="padding:16px 20px;">
                  <p style="margin:0;font-size:13px;color:#7F1D1D;line-height:1.6;"><strong>What to do:</strong> Open your review inbox, read each one, and send a reply. Keep it short, acknowledge the experience, and invite them to reach out directly. One good reply can turn a bad review into a demonstration of your character.</p>
                </td>
              </tr>
            </table>
            <table cellpadding="0" cellspacing="0">
              <tr>
                <td style="background:#D97757;border-radius:8px;">
                  <a href="<?php echo esc_url($inbox_url); ?>" style="display:inline-block;padding:12px 28px;font-size:14px;font-weight:700;color:#FFFFFF;text-decoration:none;">Open review inbox</a>
                </td>
              </tr>
            </table>
          </td>
        </tr>
        <tr>
          <td style="padding:24px 40px 32px;border-top:1px solid #F5F5F4;margin-top:24px;">
            <p style="margin:0;font-size:12px;color:#A8A29E;line-height:1.6;">You are receiving this because review velocity alerts are enabled in <?php echo esc_html($site_name); ?> Settings.</p>
          </td>
        </tr>
      </table>
    </td>
  </tr>
</table>
</body>
</html>
        <?php
    }
}