<?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\Api;

use RuntimeException;
use Throwable;

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

final class ApiException extends RuntimeException
{
    public function __construct(
        string $message,
        public readonly string $endpoint = '',
        public readonly string $method = '',
        public readonly ?int $statusCode = null,
        public readonly ?string $responseBody = null,
        ?Throwable $previous = null,
    ) {
        parent::__construct($message, $statusCode ?? 0, $previous);
    }

    public static function transportFailure(string $method, string $endpoint, Throwable $cause): self
    {
        return new self(
            sprintf('Simply.IN API transport failure on %s %s: %s', $method, $endpoint, $cause->getMessage()),
            $endpoint,
            $method,
            null,
            null,
            $cause,
        );
    }

    public static function invalidJson(string $method, string $endpoint, string $raw): self
    {
        return new self(
            sprintf('Simply.IN API returned non-JSON response for %s %s', $method, $endpoint),
            $endpoint,
            $method,
            null,
            $raw,
        );
    }

    public static function missingApiKey(): self
    {
        return new self('Simply.IN API key is empty');
    }

    public static function signingFailed(string $method, string $endpoint): self
    {
        return new self(
            sprintf('Simply.IN RSA signing failed for %s %s (fail-closed, no API-key downgrade)', $method, $endpoint),
            $endpoint,
            $method,
        );
    }
}
