<?php

namespace App\Config\Service;

use App\Config\Repository\SiteConfigRepository;
use Psr\Log\LoggerInterface;
use Symfony\Contracts\Cache\CacheInterface;
use Symfony\Contracts\Cache\ItemInterface;

/**
 * منبع واحد تصمیم برای حالت تعمیرات.
 *
 * روی هر درخواست خوانده می‌شود، پس مقدار کش می‌شود. هر خطای کش/دیتابیس باعث
 * برگشت وضعیت «غیرفعال» می‌شود (fail-open) — این لایه نباید خودش عامل قطعی سایت شود.
 */
class MaintenanceService
{
    private const CACHE_KEY = 'maintenance_state';
    private const TTL       = 30;

    /** @var array{enabled:bool,title:string,message:string,retryAfter:int,allowedIps:string[]} */
    private const DISABLED = [
        'enabled'    => false,
        'title'      => '',
        'message'    => '',
        'retryAfter' => 600,
        'allowedIps' => [],
    ];

    public function __construct(
        private readonly SiteConfigRepository $configRepo,
        private readonly CacheInterface       $cache,
        private readonly LoggerInterface      $logger,
    ) {}

    /** @return array{enabled:bool,title:string,message:string,retryAfter:int,allowedIps:string[]} */
    public function getState(): array
    {
        try {
            return $this->cache->get(self::CACHE_KEY, function (ItemInterface $item): array {
                $item->expiresAfter(self::TTL);

                return $this->readFromDatabase();
            });
        } catch (\Throwable $e) {
            $this->logger->warning('Maintenance state cache read failed', ['exception' => $e]);

            try {
                return $this->readFromDatabase();
            } catch (\Throwable $dbError) {
                $this->logger->error('Maintenance state database read failed', ['exception' => $dbError]);

                return self::DISABLED;
            }
        }
    }

    public function isEnabled(): bool
    {
        return $this->getState()['enabled'];
    }

    public function invalidate(): void
    {
        try {
            $this->cache->delete(self::CACHE_KEY);
        } catch (\Throwable $e) {
            $this->logger->warning('Maintenance state cache invalidation failed', ['exception' => $e]);
        }
    }

    public function enable(): void
    {
        $this->configRepo->set('maintenance_enabled', '1');
    }

    public function disable(): void
    {
        $this->configRepo->set('maintenance_enabled', '0');
    }

    /** @return array{enabled:bool,title:string,message:string,retryAfter:int,allowedIps:string[]} */
    private function readFromDatabase(): array
    {
        $allowedIps = array_values(array_filter(array_map(
            'trim',
            explode(',', (string) $this->configRepo->get('maintenance_allowed_ips')),
        )));

        return [
            'enabled'    => self::isTruthy($this->configRepo->get('maintenance_enabled')),
            'title'      => (string) $this->configRepo->get('maintenance_title'),
            'message'    => (string) $this->configRepo->get('maintenance_message'),
            'retryAfter' => max(1, (int) $this->configRepo->get('maintenance_retry_after')),
            'allowedIps' => $allowedIps,
        ];
    }

    /** پنل ممکن است boolean بفرستد و در ستون متنی به '1' یا 'true' تبدیل شود. */
    private static function isTruthy(?string $value): bool
    {
        return in_array(strtolower((string) $value), ['1', 'true', 'on', 'yes'], true);
    }
}
