<?php

declare(strict_types=1);

use ReleaseInsights\{Beta, Bugzilla, Json, Request, Utils, URL};

$waiting_page = false;
$lock_file = CACHE_PATH . 'beta_lock.cache';
if (! file_exists($lock_file) OR time()-filemtime($lock_file) > 900) {
    $waiting_page = true;
    Request::waitingPage('load');
}

$beta = new Beta();

$uplift_counter = 0;
$bug_list_details = [];

foreach ($beta->uplifts() as $version => $details) {
    // We count all uplifts, including backouts
    $uplifts = count($details['total']);
    $uplift_counter += $uplifts;

    // We Query Bugzilla for bug details
    $bz_fields = ['id', 'summary', 'priority', 'severity', 'product', 'component', 'type'];
    $bug_list_details[$version] = [];
    if ($uplifts > 0) {
        $bug_list_details[$version] = Json::load(
            URL::Bugzilla->value
            . 'rest/bug?include_fields='
            . implode(',', $bz_fields)
            . '&bug_id='
            . implode('%2C', $details['total']),
            3600*24
        )['bugs'] ?? [];
    }

    /*
        The Bugzilla API does not send all bug results without auth
        and we don't want auth on this app. That's why we make a
        diff between the bugs mentionned in the logs and the ones
        that the Bugzilla API answers to.
    */
    $hidden_bugs = array_values(
        array_diff(
            $details['total'],
            array_column($bug_list_details[$version], 'id')
        )
    );

    // Create a blank template for bugs not populated by Bugzilla
    $bug_template = function () use ($bz_fields) {
        $bug = array_flip($bz_fields);
        foreach ($bug as $key => $value) {
            $bug[$key] = 'N/A';
        }
        return $bug;
    };

    foreach ($hidden_bugs as $key => $value) {
        $hidden_bugs[$key] = $bug_template();
        $hidden_bugs[$key]['id'] = $value;
    }

    $bug_list_details[$version] = [...$bug_list_details[$version], ...$hidden_bugs];
}

$stats = [];
foreach ($bug_list_details as $bugs) {
    foreach($bugs as $fields) {
        if (! isset($stats[$fields['product']])) {
            $stats[$fields['product']] = [];
        }
        $stats[$fields['product']]['bugs'][] = $fields['id'];
    }
}

arsort($stats);

foreach ($stats as $product => $bugs) {
    $stats[$product]['bugzilla'] = Bugzilla::getBugListLink($stats[$product]['bugs']);
}

$known_top_crashes = [
    'IPCError-browser | ShutDownKill | mozilla::ipc::MessagePump::Run',
    'IPCError-browser | ShutDownKill | NtYieldExecution',
    'IPCError-browser | ShutDownKill | EMPTY: no crashing thread identified; ERROR_NO_MINIDUMP_HEADER',
    'IPCError-browser | ShutDownKill',
    'OOM | small',
];

$top_sigs_worth_a_bug = [];

foreach ($beta->crashes() as $k => $values) {
    if ($k == 'summary') {
        continue;
    }
    foreach ($values['signatures'] as $target) {
        if (in_array($target['term'], $known_top_crashes)) {
            continue;
        }
        if (isset($top_sigs_worth_a_bug[$target['term']])){
            $top_sigs_worth_a_bug[$target['term']] += $target['count'];
        } else {
            $top_sigs_worth_a_bug[$target['term']] = $target['count'];
        }
    }
}
// We take 10 crashes for a day as a treshold
$top_sigs_worth_a_bug = array_filter($top_sigs_worth_a_bug, fn($n) => $n > 10);

// We escape weird crash signature characters for url use
$top_sigs_worth_a_bug = array_keys($top_sigs_worth_a_bug);
$top_sigs_worth_a_bug = array_map('urlencode', $top_sigs_worth_a_bug);

// Query bugs for signatures
$crash_bugs = [];
if (! empty($top_sigs_worth_a_bug)) {
    foreach ($top_sigs_worth_a_bug as $sig) {
        $bugs_for_top_sigs = Utils::getBugsforCrashSignature($sig)['hits'] ?? [];
        $tmp = array_column($bugs_for_top_sigs, 'id');
        if (!empty($tmp)) {
            $crash_bugs[urldecode($sig)] = max(
                array_unique(
                    array_column($bugs_for_top_sigs, 'id')
                )
            );
        }
    }
}

// Write a lock file for the page to keep track of its age
file_put_contents($lock_file, '');

// Generate Bugzilla links per beta of all the bugs fixed/backedout
$bugzilla_links = [];
foreach ($bug_list_details as $version => $details) {
    $bugzilla_links[$version] =
    Bugzilla::getBugListLink(array_column($details, 'id'))
    . '&title=' . $version . '%20:%20Uplifts%20and%20backouts';
}

if ($waiting_page) {
    Request::waitingPage('leave');
}

return [
    $beta, // this is the whole Beta object
    $bug_list_details,
    $uplift_counter,
    $stats,
    $known_top_crashes,
    $crash_bugs,
    $bugzilla_links,
];