<?php

declare(strict_types=1);

require dirname(__DIR__) . '/app/bootstrap.php';

use App\Core\BranchReadiness;
use App\Repositories\BranchComparisonRepository;
use App\Services\FairYearComparisonPolicy;

$year = (int)($argv[1] ?? date('Y'));
$compareYear = (int)($argv[2] ?? ($year - 1));
$policy = (new FairYearComparisonPolicy())->resolve($year, $compareYear);
$lastMonth = (int)($policy['last_complete_month'] ?? 12);

$currentFrom = (string)($policy['from_date'] ?? sprintf('%04d-01-01', $year));
$currentTo = (string)($policy['to_date'] ?? sprintf('%04d-12-31', $year));

function shiftYear(string $date, int $year): string
{
    $source = new DateTimeImmutable($date);
    $month = (int)$source->format('n');
    $day = (int)$source->format('j');
    $lastDay = (int)(new DateTimeImmutable(sprintf('%04d-%02d-01', $year, $month)))
        ->modify('last day of this month')
        ->format('j');

    return sprintf('%04d-%02d-%02d', $year, $month, min($day, $lastDay));
}

$compareFrom = shiftYear($currentFrom, $compareYear);
$compareTo = shiftYear($currentTo, $compareYear);
$branches = BranchReadiness::liveCodes();
$repo = new BranchComparisonRepository();
$metricsExpected = BranchComparisonRepository::metricKeys();
$results = [];
$checks = [
    'ready_branches_exact' => $branches === ['njch', 'mnh'],
    'fair_contract' => !empty($policy['fair_current_year_comparison']),
    'last_complete_month_is_6' => $lastMonth === 6,
    'current_period_exact' => $currentFrom === '2026-01-01' && $currentTo === '2026-06-30',
    'compare_period_exact' => $compareFrom === '2025-01-01' && $compareTo === '2025-06-30',
];

foreach ($branches as $branch) {
    try {
        $currentRows = $repo->periodRows($branch, $currentFrom, $currentTo);
        $compareRows = $repo->periodRows($branch, $compareFrom, $compareTo);
    } catch (\Throwable $error) {
        $message = preg_replace('/password=[^;\s]+/i', 'password=[redacted]', $error->getMessage()) ?? $error->getMessage();
        $message = preg_replace('/\s+/', ' ', $message) ?? $message;
        $errorCode = 'ORACLE_SOURCE_UNAVAILABLE';
        if (preg_match('/ORA-\d{5}/i', $message, $matches) === 1) {
            $errorCode = strtoupper((string)$matches[0]);
        }

        $checks[$branch . '_oracle_query'] = false;
        $results[$branch] = [
            'status' => 'FAIL',
            'error_code' => $errorCode,
            'error' => trim($message),
            'current_totals' => [],
            'compare_totals' => [],
            'checks' => [
                'oracle_query' => false,
            ],
        ];
        continue;
    }

    $checks[$branch . '_oracle_query'] = true;
    $currentMetricMonths = [];
    $compareMetricMonths = [];
    $currentTotals = [];
    $compareTotals = [];

    foreach ($currentRows as $row) {
        $metric = strtolower((string)($row['metric_key'] ?? ''));
        $month = (int)($row['month_id'] ?? 0);
        if ($month >= 1 && $month <= $lastMonth) {
            $currentMetricMonths[$metric][$month] = true;
            $currentTotals[$metric] = ($currentTotals[$metric] ?? 0.0) + (float)($row['value'] ?? 0);
        }
    }
    foreach ($compareRows as $row) {
        $metric = strtolower((string)($row['metric_key'] ?? ''));
        $month = (int)($row['month_id'] ?? 0);
        if ($month >= 1 && $month <= $lastMonth) {
            $compareMetricMonths[$metric][$month] = true;
            $compareTotals[$metric] = ($compareTotals[$metric] ?? 0.0) + (float)($row['value'] ?? 0);
        }
    }

    $branchChecks = [
        'current_row_count_72' => count($currentRows) === 72,
        'compare_row_count_72' => count($compareRows) === 72,
        'all_metrics_current' => array_values(array_intersect($metricsExpected, array_keys($currentMetricMonths))) === $metricsExpected,
        'all_metrics_compare' => array_values(array_intersect($metricsExpected, array_keys($compareMetricMonths))) === $metricsExpected,
        'six_visible_months_per_current_metric' => count(array_filter($metricsExpected, static function (string $metric) use ($currentMetricMonths): bool {
            return count($currentMetricMonths[$metric] ?? []) === 6;
        })) === 6,
        'six_visible_months_per_compare_metric' => count(array_filter($metricsExpected, static function (string $metric) use ($compareMetricMonths): bool {
            return count($compareMetricMonths[$metric] ?? []) === 6;
        })) === 6,
        'current_activity_present' => array_sum($currentTotals) > 0,
        'compare_activity_present' => array_sum($compareTotals) > 0,
    ];

    foreach ($branchChecks as $name => $passed) {
        $checks[$branch . '_' . $name] = $passed;
    }

    $results[$branch] = [
        'status' => 'PASS',
        'current_totals' => $currentTotals,
        'compare_totals' => $compareTotals,
        'checks' => $branchChecks,
    ];
}

$failed = [];
foreach ($checks as $name => $passed) {
    if (!$passed) $failed[] = $name;
}

$result = [
    'schema' => 'DDB_BRANCH_COMPARISON_R45_P11_2_LIVE_ACCEPTANCE_V1',
    'captured_at' => date(DATE_ATOM),
    'periods' => [
        'current_from' => $currentFrom,
        'current_to' => $currentTo,
        'compare_from' => $compareFrom,
        'compare_to' => $compareTo,
    ],
    'branches' => $branches,
    'metrics_expected' => $metricsExpected,
    'results' => $results,
    'access_paths' => $repo->accessPaths(),
    'connectivity' => $repo->connectivityDiagnostics(),
    'checks' => $checks,
    'status' => $failed === [] ? 'PASS' : 'FAIL',
    'failed' => $failed,
    'oracle_writes' => 'NONE',
];

$dir = dirname(__DIR__) . '/storage/evidence/branch_comparison';
if (!is_dir($dir) && !mkdir($dir, 0775, true) && !is_dir($dir)) {
    throw new RuntimeException('Cannot create Branch Comparison evidence directory.');
}
$file = $dir . '/BRANCH_COMPARISON_R45_P11_2_LIVE_ACCEPTANCE_' . date('Ymd_His') . '.json';
file_put_contents(
    $file,
    json_encode($result, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES),
    LOCK_EX
);

echo json_encode(
    $result + ['evidence_file' => $file],
    JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES
), PHP_EOL;

exit($failed === [] ? 0 : 1);
