<?php

/**
 * PHP-IR user function declaration.
 */
final class PhpIrFunction
{
    private int $startLine;
    private int $endLine;
    private array $comments;
    private string $name;
    private array $params;
    private array $paramTypes;
    private array $stmts;
    private string $visibility;
    private bool $isStatic;
    private string $returnType;

    /**
     * Create a user function declaration.
     */
    public function __construct(int $startLine, int $endLine, array $comments, string $name, array $params, array $stmts, string $visibility = 'public', bool $isStatic = false, string $returnType = '', array $paramTypes = [])
    {
        $this->startLine = $startLine;
        $this->endLine = $endLine;
        $this->comments = $comments;
        $this->name = $name;
        $this->params = $params;
        $this->paramTypes = self::normalizeParamTypes($params, $paramTypes);
        $this->stmts = $stmts;
        $this->visibility = self::normalizeVisibility($visibility);
        $this->isStatic = $isStatic;
        $this->returnType = self::normalizeReturnType($returnType);
    }

    /**
     * Convert to a plain array for debugging/export.
     */
    public function toArray(): array
    {
        return [
            'kind' => 'Function',
            'startLine' => $this->startLine,
            'endLine' => $this->endLine,
            'comments' => array_map(static fn (PhpIrComment $comment): array => $comment->toArray(), $this->comments),
            'name' => $this->name,
            'params' => $this->params,
            'paramTypes' => $this->paramTypes,
            'visibility' => $this->visibility,
            'static' => $this->isStatic,
            'returnType' => $this->returnType,
            'stmts' => array_map(
                static fn (object $stmt): array => method_exists($stmt, 'toArray') ? $stmt->toArray() : ['kind' => get_debug_type($stmt)],
                $this->stmts,
            ),
        ];
    }

    private static function normalizeParamTypes(array $params, array $paramTypes): array
    {
        $out = [];
        foreach ($params as $param) {
            if (!is_string($param) || $param === '') {
                continue;
            }
            $type = strtolower(ltrim((string) ($paramTypes[$param] ?? ''), '\\'));
            $normalized = match ($type) {
                'int', 'integer' => 'int',
                'float', 'double' => 'float',
                default => '',
            };
            if ($normalized !== '') {
                $out[$param] = $normalized;
            }
        }
        return $out;
    }

    private static function normalizeReturnType(string $returnType): string
    {
        $normalized = strtolower(ltrim($returnType, '\\'));
        return match ($normalized) {
            '', 'void', 'int', 'integer', 'float', 'double' => $normalized,
            default => '',
        };
    }

    private static function normalizeVisibility(string $visibility): string
    {
        $normalized = strtolower($visibility);
        if (!in_array($normalized, ['public', 'protected', 'private'], true)) {
            return 'public';
        }
        return $normalized;
    }
}
