<?php

/**
 * Copyright 2024-2025 Simply.IN Sp. z o.o.
 *
 * NOTICE OF LICENSE
 *
 * Licensed under the EUPL-1.2 or later.
 * You may not use this work except in compliance with the Licence.
 *
 * Copy of the Licence is available at:
 * https://joinup.ec.europa.eu/software/page/eupl
 * It is bundled with this package in the file LICENSE.txt
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the Licence is distributed on an as is basis,
 * without warranties or conditions of any kind, either express or implied.
 * Check the Licence for the specific language governing permissions
 * and limitations under the License.
 *
 * @author   Simply.IN Sp. z o.o.
 * @copyright 2024-2025 Simply.IN Sp. z o.o.
 * @license   https://joinup.ec.europa.eu/software/page/eupl
 */

declare(strict_types=1);

namespace SimplyIn\Auth;

use PrestaShopLogger;
use SimplyIn\Api\SimplyInApiClient;

if (!defined('_PS_VERSION_')) {
    exit;
}

/**
 * Best-effort counterpart to {@see RsaRegistrar}: tells the backend to drop the RSA public key
 * registration when this shop no longer wants it (uninstall), then always clears the local key
 * material regardless of whether the backend call succeeded.
 *
 * Uses the same RSA-signed request path as every other authenticated call ({@see SimplyInApiClient},
 * which signs via {@see RsaSigner::buildHeaders()}) — there is no separate signing mechanism for
 * this endpoint.
 */
final class RsaRevoker
{
    private const REVOKE_ENDPOINT = 'plugin-sync/revokePluginPublicKeyRegistration';

    public function __construct(
        private readonly RsaSigner $signer,
        private readonly SimplyInApiClient $apiClient,
    ) {
    }

    /**
     * Revoke the backend registration and drop local RSA state. No-op when nothing is registered
     * locally. Never throws: a failed backend call (network, timeout, HTTP 4xx/5xx, or signing
     * failure) is logged and otherwise ignored, and local state is cleared regardless — the caller
     * (uninstall) must complete either way.
     */
    public function revoke(): void
    {
        if (!$this->signer->isRegistered()) {
            return;
        }

        try {
            $response = $this->apiClient->request('POST', self::REVOKE_ENDPOINT);
            if (!$response->isSuccess()) {
                $this->log(sprintf(
                    'SimplyIN RSA: revoke-on-uninstall rejected by backend (HTTP %d)',
                    $response->statusCode,
                ));
            }
        } catch (\Throwable $e) {
            // Catch everything, not just ApiException: an unexpected throwable here must not
            // skip clearing local state below or escape to the uninstall caller.
            $this->log('SimplyIN RSA: revoke-on-uninstall request failed — ' . $e->getMessage());
        } finally {
            $this->signer->clear();
        }
    }

    private function log(string $message): void
    {
        if (class_exists('PrestaShopLogger')) {
            PrestaShopLogger::addLog($message, 2, null, 'SimplyIn', null, true);
        }
    }
}
