<?php

declare(strict_types=1);

namespace App\Services\SupportCenter;

use Throwable;

final class NativeHostSystemUpdateOpcache implements HostSystemUpdateOpcache
{
    private ?string $lastFailureReason = null;

    public function shouldReset(): bool
    {
        return PHP_SAPI !== 'cli'
            && filter_var(ini_get('opcache.enable'), FILTER_VALIDATE_BOOLEAN);
    }

    public function reset(): bool
    {
        $this->lastFailureReason = null;

        if (! function_exists('opcache_reset')) {
            $this->lastFailureReason = 'opcache_reset_unavailable';

            return false;
        }

        $warning = null;
        set_error_handler(static function (int $severity, string $message) use (&$warning): bool {
            $warning = $message;

            return true;
        });

        try {
            $reset = opcache_reset();
        } catch (Throwable $throwable) {
            $this->lastFailureReason = 'opcache_reset_exception:'.$throwable::class;

            return false;
        } finally {
            restore_error_handler();
        }

        if ($reset) {
            return true;
        }

        $this->lastFailureReason = $this->classifyFailure($warning);

        return false;
    }

    public function failureReason(): ?string
    {
        return $this->lastFailureReason;
    }

    /** @return array<string, bool|int|string> */
    public function diagnosticContext(): array
    {
        return [
            'sapi' => PHP_SAPI,
            'opcache_enabled' => filter_var(ini_get('opcache.enable'), FILTER_VALIDATE_BOOLEAN),
            'opcache_reset_available' => function_exists('opcache_reset'),
            'opcache_restrict_api_configured' => trim((string) ini_get('opcache.restrict_api')) !== '',
            'opcache_validate_timestamps' => filter_var(ini_get('opcache.validate_timestamps'), FILTER_VALIDATE_BOOLEAN),
            'opcache_revalidate_freq' => max(0, (int) ini_get('opcache.revalidate_freq')),
            'failure_reason' => $this->lastFailureReason ?? 'none',
        ];
    }

    private function classifyFailure(?string $warning): string
    {
        $normalized = strtolower((string) $warning);

        if (str_contains($normalized, 'restrict') || str_contains($normalized, 'not allowed')) {
            return 'opcache_api_restricted';
        }

        if (str_contains($normalized, 'disabled')) {
            return 'opcache_disabled_during_reset';
        }

        return 'opcache_reset_returned_false';
    }
}
