<?php
/**
 * Wave 3e full regression sweep — journal.php's Right Now page
 * (?workspace=active&zone=now), every real prop-firm account (all 84 from
 * the same population verify_prop_firm_rule_engine.php golden-value-
 * checked), every real lifecycle state and challenge type this page
 * renders for. Confirms:
 *   (a) zero PHP errors on every render,
 *   (b) the rendered "Current Balance" figure (Funded card or Active
 *       Coaching section, whichever is present) matches
 *       PropFirmRuleEngine::compute()'s canonical phase_balance exactly,
 *       for every account where the fix actually engages (current segment),
 *   (c) zero new "[rnBuildJourney] ... diverges" log lines — the
 *       function's own built-in safety net that would fire if the
 *       "mathematically proven identical" claim were ever wrong for a
 *       real account.
 * Full, persistent log written to
 * docs/architecture/golden_value_logs/ alongside the original
 * PropFirmRuleEngine regression log.
 */
require_once __DIR__ . '/../config/config.php';
require_once __DIR__ . '/../src/JourneySegmentation.php';
require_once __DIR__ . '/../src/PropFirmRuleEngine.php';

$pdo = new PDO(
    "mysql:host=" . DB_HOST . ";port=" . DB_PORT . ";dbname=" . DB_NAME . ";charset=utf8mb4",
    DB_USER, DB_PASS,
    [PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION, PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC]
);

$logDir = __DIR__ . '/../docs/architecture/golden_value_logs';
$logPath = $logDir . '/journal_rn_wave3e_sweep_' . date('Y-m-d_His') . '.log';
$logFh = fopen($logPath, 'w');
function logLine(string $s = ''): void { global $logFh; fwrite($logFh, $s . "\n"); echo $s . "\n"; }

$errorLogPath = '/c/xampp/apache/logs/error.log';
$errorLogBefore = file_exists($errorLogPath) ? count(file($errorLogPath)) : 0;

$accounts = $pdo->query("
    SELECT ca.account_id, ca.challenge_type, ta.lifecycle_state, ta.user_id, ta.label
    FROM challenge_accounts ca
    JOIN trading_accounts ta ON ca.account_id = ta.id
    ORDER BY ta.lifecycle_state, ca.challenge_type, ca.account_id
")->fetchAll();

logLine("journal.php Right Now — Wave 3e full regression sweep");
logLine("Run at: " . date('Y-m-d H:i:s'));
logLine("Total real prop-firm accounts: " . count($accounts));
logLine(str_repeat('=', 100));

$base = 'http://localhost:8080/traderalign';
$cookieJar = tempnam(sys_get_temp_dir(), 'zzcookiesweep');
$loggedInAs = null;

$matched = 0; $skippedNoCurrentBalanceShown = 0; $errored = 0; $mismatched = 0;
$mismatchDetails = [];

foreach ($accounts as $acc) {
    $accountId = $acc['account_id'];
    $userId = $acc['user_id'];

    if ($loggedInAs !== $userId) {
        $ch = curl_init("{$base}/public/_zz_test_autologin.php?uid=" . urlencode($userId));
        curl_setopt_array($ch, [CURLOPT_RETURNTRANSFER => true, CURLOPT_COOKIEJAR => $cookieJar, CURLOPT_COOKIEFILE => $cookieJar]);
        curl_exec($ch);
        curl_close($ch);
        $loggedInAs = $userId;
    }

    $url = "{$base}/journal?workspace=active&zone=now&rn_type=prop&rn_challenge={$acc['challenge_type']}&rn_account=" . urlencode($accountId);
    $ch = curl_init($url);
    curl_setopt_array($ch, [CURLOPT_RETURNTRANSFER => true, CURLOPT_COOKIEJAR => $cookieJar, CURLOPT_COOKIEFILE => $cookieJar]);
    $resp = curl_exec($ch);
    $code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
    curl_close($ch);

    $hasError = (stripos($resp, 'Warning:') !== false || stripos($resp, 'Fatal error') !== false
        || stripos($resp, 'Notice:') !== false || stripos($resp, 'Deprecated:') !== false || stripos($resp, 'Parse error') !== false);

    if ($code !== 200 || $hasError) {
        $errored++;
        logLine("ERROR: {$accountId} ({$acc['label']}) lifecycle={$acc['lifecycle_state']} type={$acc['challenge_type']} — HTTP {$code}, PHP error: " . ($hasError ? 'YES' : 'no'));
        continue;
    }

    // Extract the rendered "Current Balance" — either the Funded card
    // (rn-metric-value right after a "Current Balance" rn-metric-label)
    // or the Active Coaching section's rn-coaching-stat-value. Try both.
    $renderedBalance = null;
    if (preg_match('/rn-coaching-stat-label">Current Balance<\/div>\s*<div class="rn-coaching-stat-value">\$([\d,\.]+)/', $resp, $m)) {
        $renderedBalance = $m[1];
    } elseif (preg_match('/rn-metric-value">\$([\d,\.]+)<\/div><div class="rn-metric-label">Current Balance/', $resp, $m)) {
        $renderedBalance = $m[1];
    }

    $pfr = PropFirmRuleEngine::compute($accountId);
    $expectedBalance = !isset($pfr['error']) ? number_format((float)$pfr['phase_balance'], 2) : null;

    if ($renderedBalance === null) {
        // Breached/closed accounts or accounts with no current-segment
        // card rendered at all don't show this stat — not a failure,
        // just nothing to compare for this account.
        $skippedNoCurrentBalanceShown++;
        continue;
    }

    if ($renderedBalance === $expectedBalance) {
        $matched++;
    } else {
        $mismatched++;
        $mismatchDetails[] = "{$accountId} ({$acc['label']}) lifecycle={$acc['lifecycle_state']} type={$acc['challenge_type']} — rendered={$renderedBalance} expected={$expectedBalance}";
    }
}

@unlink($cookieJar);

logLine();
logLine("RESULTS");
logLine(str_repeat('-', 100));
logLine("Rendered 'Current Balance' matched PropFirmRuleEngine exactly: {$matched}");
logLine("No 'Current Balance' stat shown on page (breached/closed/no current segment — nothing to compare): {$skippedNoCurrentBalanceShown}");
logLine("Mismatched: {$mismatched}");
logLine("HTTP/PHP errors: {$errored}");
logLine("Total accounts checked: " . count($accounts));
logLine();

if (!empty($mismatchDetails)) {
    logLine("MISMATCH DETAIL:");
    foreach ($mismatchDetails as $d) logLine("  {$d}");
    logLine();
}

// Check for new divergence log lines
$errorLogAfter = file_exists($errorLogPath) ? file($errorLogPath) : [];
$newLines = array_slice($errorLogAfter, $errorLogBefore);
$divergenceLines = array_filter($newLines, fn($l) => str_contains($l, '[rnBuildJourney]'));
logLine("New Apache error.log lines during this sweep: " . count($newLines));
logLine("Of which real '[rnBuildJourney] ... diverges' warnings: " . count($divergenceLines));
if (!empty($divergenceLines)) {
    logLine("DIVERGENCE LINES FOUND — the canonical/local calc disagreed for a real account:");
    foreach ($divergenceLines as $l) logLine("  " . trim($l));
} else {
    logLine("Zero divergence — confirms the 'mathematically proven identical' claim held for every real account checked.");
}

logLine(str_repeat('=', 100));
logLine("Log written to: {$logPath}");
fclose($logFh);
echo "\nLog file: {$logPath}\n";
