<?php


namespace AIO\Docker;

use GuzzleHttp\Client;

readonly class GitHubContainerRegistryManager
{
    private Client $guzzleClient;

    public function __construct()
    {
        $this->guzzleClient = new Client();
    }

    public function GetLatestDigestOfTag(string $name, string $tag): ?string
    {
        $cacheKey = 'ghcr-manifest-' . $name . $tag;

        $cachedVersion = apcu_fetch($cacheKey);
        if ($cachedVersion !== false && is_string($cachedVersion)) {
            return $cachedVersion;
        }

        // If one of the links below should ever become outdated, we can still upgrade the mastercontainer via the webinterface manually by opening '/api/docker/getwatchtower'

        try {
            $authTokenRequest = $this->guzzleClient->request(
                'GET',
                'https://ghcr.io/token?scope=repository:' . $name . ':pull'
            );
            $body = $authTokenRequest->getBody()->getContents();
            $decodedBody = json_decode($body, true);
            if (isset($decodedBody['token'])) {
                $authToken = $decodedBody['token'];
                $manifestRequest = $this->guzzleClient->request(
                    'HEAD',
                    'https://ghcr.io/v2/' . $name . '/manifests/' . $tag,
                    [
                        'headers' => [
                            'Accept' => 'application/vnd.oci.image.index.v1+json,application/vnd.docker.distribution.manifest.list.v2+json,application/vnd.docker.distribution.manifest.v2+json',
                            'Authorization' => 'Bearer ' . $authToken,
                        ],
                    ]
                );
                $responseHeaders = $manifestRequest->getHeader('docker-content-digest');
                if (count($responseHeaders) === 1) {
                    $latestVersion = $responseHeaders[0];
                    apcu_add($cacheKey, $latestVersion, 600);
                    return $latestVersion;
                }
            }

            error_log('Could not get digest of container ' . $name . ':' . $tag);
            return null;
        } catch (\Exception $e) {
            error_log('Could not get digest of container ' . $name . ':' . $tag . ' ' . $e->getMessage());
            return null;
        }
    }
}
