<?php

declare(strict_types=1);

namespace App\Framework\Quality\PHPStan\Rules;

use PhpParser\Node;
use PhpParser\Node\Expr\FuncCall;
use PHPStan\Analyser\Scope;
use PHPStan\Rules\Rule;
use PHPStan\Rules\RuleErrorBuilder;

/**
 * @implements Rule<FuncCall>
 */
final class UseClockAbstractionRule implements Rule
{
    /** @var array<string, string> */
    private array $forbiddenTimeFunctions = [
        'time' => 'Use Clock::time() instead for testable time handling',
        'microtime' => 'Use Clock::microtime() instead for testable time handling',
        'date' => 'Use Clock::now()->format() or DateTimeFormatter instead',
        'gmdate' => 'Use Clock::now()->setTimezone() and format() instead',
        'strtotime' => 'Use Clock::fromString() instead for better error handling',
        'mktime' => 'Use Clock::fromString() with proper format instead',
        'gmmktime' => 'Use Clock::fromString() with UTC timezone instead',
    ];

    public function getNodeType(): string
    {
        return FuncCall::class;
    }

    public function processNode(Node $node, Scope $scope): array
    {
        if (! $node instanceof FuncCall) {
            return [];
        }

        if (! $node->name instanceof Node\Name) {
            return [];
        }

        $functionName = $node->name->toString();

        // Skip if we're already in Framework DateTime layer (allow direct usage there)
        $currentClass = $scope->getClassReflection()?->getName() ?? '';
        if (str_starts_with($currentClass, 'App\\Framework\\DateTime\\')) {
            return [];
        }

        if (! isset($this->forbiddenTimeFunctions[$functionName])) {
            return [];
        }

        return [
            RuleErrorBuilder::message(sprintf(
                'Function %s() is forbidden: %s',
                $functionName,
                $this->forbiddenTimeFunctions[$functionName]
            ))
            ->tip('Inject Clock interface via dependency injection for testable time handling')
            ->build(),
        ];
    }
}
