#!/usr/bin/env php
<?php
/**
 * Send a scheduled report to all its subscribers via SMTP.
 *
 * Renders the report HTML, fetches subscriber list, sends one email
 * per subscriber, and logs the result.
 *
 * Usage:
 *   php exploitation/send_report.php --report <key> [options]
 *
 * Options:
 *   -r, --report <key>   Report key (e.g. cnp/ad_anomalies) — required
 *   -q, --quiet          Suppress output
 *   -h, --help           Show this help
 *
 * Known report keys:
 *   cnp/ad_anomalies, cmdb/db_inventory, cnp/cmdb_sync
 */

require_once dirname(__DIR__) . '/shared/cli_bootstrap.php';

$opts  = getopt('r:qh', ['report:', 'quiet', 'help']);
$quiet = isset($opts['q']) || isset($opts['quiet']);

if (isset($opts['h']) || isset($opts['help'])) cli_show_help(__FILE__);

$reportKey = $opts['r'] ?? $opts['report'] ?? '';
if ($reportKey === '' || !isset(ReportRenderer::REPORTS[$reportKey])) {
    echo "ERROR: --report is required. Known keys: " . implode(', ', array_keys(ReportRenderer::REPORTS)) . "\n";
    exit(1);
}

/*
 * Le module dont depend ce rapport est-il actif ?
 *
 * Sans ce controle, un rapport masque de l'administration — parce que son
 * module est desactive — continuait a partir par courriel : la planification
 * reste en base, la tache cron la lit, et ReportRenderer::render() va
 * interroger un module qu'on a justement eteint.
 *
 * On sort en SUCCES : desactiver un module est un geste delibere, ce n'est
 * pas une panne, et une tache planifiee qui rend 1 tous les jours finit par
 * remplir une boite de courriels d'alerte.
 */
$reportModule = ReportRenderer::REPORTS[$reportKey]['module'] ?? '';
if ($reportModule !== '' && !$moduleRegistry->isActive($reportModule)) {
    if (!$quiet) {
        echo date('Y-m-d H:i:s')
           . "  SKIP: module '{$reportModule}' is disabled — report {$reportKey} not sent\n";
    }
    exit(0);
}

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

$startMs = hrtime(true);

/* ── Render ────────────────────────────────────────────────────────────── */
out("Rendering report: {$reportKey}");
$rendered = ReportRenderer::render($reportKey);
if (!$rendered['ok']) {
    out("ERROR: Render failed — {$rendered['error']}");
    $db->execute(
        "INSERT INTO report_send_log (report_key, recipient_count, status, details, duration_ms) VALUES (?, 0, 'error', ?, ?)",
        [$reportKey, $rendered['error'], (int)((hrtime(true) - $startMs) / 1e6)]
    );
    exit(1);
}

/* ── Subscribers ──────────────────────────────────────────────────────── */
$recipients = $db->fetchAll(
    "SELECT u.email, u.username FROM report_subscribers rs
     JOIN users u ON u.id = rs.user_id
     WHERE rs.report_key = ? AND u.active = 1 AND u.email IS NOT NULL AND u.email != ''",
    [$reportKey]
);

if (empty($recipients)) {
    out("No subscribers for {$reportKey}. Nothing to send.");
    exit(0);
}

out(count($recipients) . " subscriber(s) found.");

/* ── Send ──────────────────────────────────────────────────────────────── */
$logoPath = Smtp::resolveLogoPath();
$okCount  = 0;
$errCount = 0;
$errors   = [];

foreach ($recipients as $rcpt) {
    $email = $rcpt['email'];
    out("  Sending to {$email}...");
    $result = Smtp::send($email, $rendered['subject'], $rendered['html'], $logoPath);
    if ($result['ok']) {
        $okCount++;
        out("    OK");
    } else {
        $errCount++;
        $errors[] = "{$email}: {$result['msg']}";
        out("    FAILED: {$result['msg']}");
    }
}

/* ── Log ───────────────────────────────────────────────────────────────── */
$durationMs = (int)((hrtime(true) - $startMs) / 1e6);
$status  = $errCount === 0 ? 'ok' : ($okCount > 0 ? 'partial' : 'error');
$details = $errCount > 0 ? implode('; ', array_slice($errors, 0, 5)) : null;

$db->execute(
    "INSERT INTO report_send_log (report_key, recipient_count, status, details, duration_ms) VALUES (?, ?, ?, ?, ?)",
    [$reportKey, $okCount + $errCount, $status, $details, $durationMs]
);

out("Done: {$okCount} sent, {$errCount} failed ({$durationMs}ms).");
exit($errCount > 0 ? 1 : 0);
