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

use Configuration;

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

/**
 * Validates the remote address of incoming Simply.IN payment webhooks.
 *
 * IPs are configured via the `SIMPLYIN_WEBHOOK_IPS` configuration key (a JSON
 * or comma-separated list), seeded at install from {@see self::DEFAULT_IPS}.
 * Falls back to the same default if the key is ever unset.
 */
final class WebhookIpValidator
{
    public const CONFIG_KEY = 'SIMPLYIN_WEBHOOK_IPS';

    public const DEFAULT_IPS = ['138.199.153.181'];

    public function __construct(private readonly ?string $configured = null)
    {
    }

    /**
     * @return list<string>
     */
    public function allowedIps(): array
    {
        $raw = $this->configured ?? Configuration::get(self::CONFIG_KEY);
        if (!is_string($raw) || trim($raw) === '') {
            return self::DEFAULT_IPS;
        }

        $decoded = json_decode($raw, true);
        if (is_array($decoded)) {
            return array_values(array_filter(array_map('strval', $decoded), fn (string $ip) => $ip !== ''));
        }

        $parts = array_map('trim', explode(',', $raw));

        return array_values(array_filter($parts, fn (string $ip) => $ip !== ''));
    }

    public function isAllowed(?string $ip): bool
    {
        if ($ip === null || $ip === '') {
            return false;
        }

        return in_array($ip, $this->allowedIps(), true);
    }
}
