<?php
declare(strict_types=1);

/**
 * EasyChair Unified Notification Digest Worker
 *
 * Usage:
 *   php tools/notification_digest_worker.php --dry-run
 *   php tools/notification_digest_worker.php --frequency=daily --limit=50
 *   php tools/notification_digest_worker.php --frequency=weekly --conference_id=1 --limit=50
 *   php tools/notification_digest_worker.php --frequency=daily --conference_id=1 --reset-test-digest --limit=50
 */

if (!defined('BASE_PATH')) {
    define('BASE_PATH', dirname(__DIR__));
}

require BASE_PATH . '/config/bootstrap.php';

use App\Core\Database;
use App\Core\SmtpMailer;

function arg_value(string $name, $default = null) {
    global $argv;
    foreach ($argv as $arg) {
        if ($arg === "--{$name}") return true;
        if (str_starts_with($arg, "--{$name}=")) {
            return substr($arg, strlen("--{$name}="));
        }
    }
    return $default;
}

function out(string $msg): void {
    echo '[' . date('Y-m-d H:i:s') . '] ' . $msg . PHP_EOL;
}

$db = Database::getInstance();

$frequency = (string)arg_value('frequency', 'daily');
if (!in_array($frequency, ['daily','weekly'], true)) {
    $frequency = 'daily';
}

$limit = (int)arg_value('limit', 50);
if ($limit <= 0 || $limit > 500) {
    $limit = 50;
}

$conferenceId = (int)arg_value('conference_id', 0);
$dryRun = (bool)arg_value('dry-run', false);
$resetTestDigest = (bool)arg_value('reset-test-digest', false);

$periodSql = $frequency === 'weekly'
    ? "DATE_SUB(NOW(), INTERVAL 7 DAY)"
    : "DATE_SUB(NOW(), INTERVAL 1 DAY)";

if ($resetTestDigest) {
    $sql = "UPDATE user_notifications SET digest_sent_at=NULL WHERE created_at >= {$periodSql}";
    $params = [];

    if ($conferenceId > 0) {
        $sql .= " AND conference_id=?";
        $params[] = $conferenceId;
    }

    $stmt = $db->prepare($sql);
    $stmt->execute($params);

    out("Reset digest_sent_at for recent notifications. affected=" . $stmt->rowCount());
}

/*
 * Select one row per user/conference where at least one notification type has digest enabled.
 */
$where = "
    WHERE p.digest_enabled=1
      AND p.email_enabled=1
      AND p.digest_frequency=?
      AND (p.muted_until IS NULL OR p.muted_until < NOW())
      AND u.email IS NOT NULL
      AND u.email <> ''
";
$params = [$frequency];

if ($conferenceId > 0) {
    $where .= " AND p.conference_id=? ";
    $params[] = $conferenceId;
}

$stmt = $db->prepare("
    SELECT
        p.user_id,
        p.org_id,
        p.conference_id,
        GROUP_CONCAT(DISTINCT p.notification_type ORDER BY p.notification_type SEPARATOR ',') AS enabled_types,
        u.email,
        CONCAT(COALESCE(u.first_name,''),' ',COALESCE(u.last_name,'')) AS full_name,
        COALESCE(u.preferred_lang,'en') AS preferred_lang,
        c.short_name,
        c.title_en,
        c.title_ar
    FROM user_notification_preferences p
    JOIN users u ON u.id=p.user_id
    LEFT JOIN conferences c ON c.id=p.conference_id
    {$where}
    GROUP BY p.user_id, p.org_id, p.conference_id, u.email, u.first_name, u.last_name, u.preferred_lang, c.short_name, c.title_en, c.title_ar
    ORDER BY p.user_id, p.conference_id
    LIMIT {$limit}
");
$stmt->execute($params);
$groups = $stmt->fetchAll(PDO::FETCH_ASSOC);

out("Unified digest worker started. frequency={$frequency}, conference_id=" . ($conferenceId ?: 'ALL') . ", dry_run=" . ($dryRun ? 'YES' : 'NO'));
out("Eligible user/conference group(s): " . count($groups));

if (!$groups) {
    exit(0);
}

$mailer = new SmtpMailer();

$sent = 0;
$failed = 0;
$skipped = 0;

foreach ($groups as $group) {
    $userId = (int)$group['user_id'];
    $confId = !empty($group['conference_id']) ? (int)$group['conference_id'] : null;
    $orgId = !empty($group['org_id']) ? (int)$group['org_id'] : null;
    $enabledTypes = array_filter(array_map('trim', explode(',', (string)$group['enabled_types'])));

    if (!$enabledTypes) {
        $skipped++;
        continue;
    }

    $typePlaceholders = implode(',', array_fill(0, count($enabledTypes), '?'));

    $nWhere = "
        WHERE n.user_id=?
          AND n.digest_sent_at IS NULL
          AND n.created_at >= {$periodSql}
          AND n.notification_type IN ({$typePlaceholders})
    ";

    $nParams = [$userId, ...$enabledTypes];

    if ($confId) {
        $nWhere .= " AND n.conference_id=? ";
        $nParams[] = $confId;
    }

    /*
     * Re-check muted/type-level email preferences at notification time.
     * This prevents including a type that was enabled by group but muted separately.
     */
    $stmt = $db->prepare("
        SELECT 
            n.*,
            s.submission_no,
            COALESCE(s.title,s.title_en,s.title_ar) AS submission_title
        FROM user_notifications n
        LEFT JOIN submissions s ON s.id=n.submission_id
        {$nWhere}
        ORDER BY n.notification_type, n.id DESC
        LIMIT 200
    ");
    $stmt->execute($nParams);
    $notifications = $stmt->fetchAll(PDO::FETCH_ASSOC);

    if (!$notifications) {
        $skipped++;
        continue;
    }

    $recipient = (string)$group['email'];
    $name = trim((string)$group['full_name']) ?: $recipient;
    $confLabel = (string)($group['short_name'] ?: ($group['title_en'] ?: ('Conference #' . ($confId ?: ''))));

    $subject = "Your conference notification summary";
    if ($confLabel !== '') {
        $subject .= " - {$confLabel}";
    }

    $byType = [];
    foreach ($notifications as $n) {
        $byType[(string)$n['notification_type']][] = $n;
    }

    $bodyLines = [];
    $bodyLines[] = "Dear {$name},";
    $bodyLines[] = "";
    $bodyLines[] = "Here is your {$frequency} notification digest for {$confLabel}.";
    $bodyLines[] = "";
    $bodyLines[] = "Total notifications: " . count($notifications);
    $bodyLines[] = "Included types: " . implode(', ', array_keys($byType));
    $bodyLines[] = "";

    foreach ($byType as $type => $items) {
        $bodyLines[] = "========================================";
        $bodyLines[] = strtoupper($type) . " (" . count($items) . ")";
        $bodyLines[] = "========================================";

        foreach ($items as $n) {
            $bodyLines[] = "- " . (string)$n['title'];

            if (!empty($n['submission_no'])) {
                $bodyLines[] = "  Submission: " . $n['submission_no'] . " - " . (string)($n['submission_title'] ?? '');
            }

            if (!empty($n['body'])) {
                $bodyLines[] = "  " . mb_substr(trim((string)$n['body']), 0, 350);
            }

            $bodyLines[] = "  Date: " . (string)$n['created_at'];
            $bodyLines[] = "";
        }
    }

    $bodyLines[] = "";
    $bodyLines[] = "Please sign in to your conference account to view details." ;

    $body = implode("\n", $bodyLines);

    out("User {$userId} {$recipient}: " . count($notifications) . " total notification(s), types=" . implode(',', array_keys($byType)));

    if ($dryRun) {
        $skipped++;
        continue;
    }

    $result = $mailer->send($recipient, $subject, $body, $name);

    if (!empty($result['ok'])) {
        $stmt = $db->prepare("
            INSERT INTO notification_digest_log
            (org_id, conference_id, user_id, digest_frequency, notifications_count,
             recipient_email, subject, body, status, sent_at)
            VALUES (?, ?, ?, ?, ?, ?, ?, ?, 'sent', NOW())
        ");
        $stmt->execute([
            $orgId,
            $confId,
            $userId,
            $frequency,
            count($notifications),
            $recipient,
            $subject,
            $body
        ]);

        $ids = array_map(fn($n) => (int)$n['id'], $notifications);
        if ($ids) {
            $in = implode(',', array_fill(0, count($ids), '?'));
            $u = $db->prepare("UPDATE user_notifications SET digest_sent_at=NOW() WHERE id IN ({$in})");
            $u->execute($ids);
        }

        $sent++;
    } else {
        $err = trim(($result['error'] ?? 'SMTP failed') . "\n\n" . ($result['debug'] ?? ''));

        $stmt = $db->prepare("
            INSERT INTO notification_digest_log
            (org_id, conference_id, user_id, digest_frequency, notifications_count,
             recipient_email, subject, body, status, error_message)
            VALUES (?, ?, ?, ?, ?, ?, ?, ?, 'failed', ?)
        ");
        $stmt->execute([
            $orgId,
            $confId,
            $userId,
            $frequency,
            count($notifications),
            $recipient,
            $subject,
            $body,
            mb_substr($err, 0, 2000)
        ]);

        $failed++;
        out("FAILED user {$userId}: " . mb_substr($err, 0, 250));
    }
}

out("Unified digest worker done. sent={$sent}, failed={$failed}, skipped={$skipped}");
