<?php

/**
 * Vala-IR class declaration emitted as a Vala class container.
 *
 * This models PHP classes structurally for generated Vala readability only;
 * PHP class semantics continue to live in PhpefRuntimeCore's ClassRegistry.
 */
final class ValaIrClassDeclaration
{
    private int $startLine;
    private int $endLine;
    private array $comments;
    private string $name;
    private string $phpName;
    private array $methods;

    /**
     * Create a class container declaration.
     */
    public function __construct(int $startLine, int $endLine, array $comments, string $name, string $phpName, array $methods)
    {
        $this->startLine = $startLine;
        $this->endLine = $endLine;
        $this->comments = $comments;
        $this->name = $name;
        $this->phpName = $phpName;
        $this->methods = $methods;
    }

    /**
     * Convert to a plain array for debugging/export.
     */
    public function toArray(): array
    {
        return [
            'kind' => 'ClassDeclaration',
            'startLine' => $this->startLine,
            'endLine' => $this->endLine,
            'comments' => array_map(static fn (ValaIrComment $comment): array => $comment->toArray(), $this->comments),
            'name' => $this->name,
            'valaContainerName' => $this->name,
            'phpName' => $this->phpName,
            'phpClassName' => $this->phpName,
            'methods' => array_map(
                static fn (object $method): array => method_exists($method, 'toArray') ? $method->toArray() : ['kind' => get_debug_type($method)],
                $this->methods,
            ),
            'methodSummaries' => array_values(array_map(
                static fn (object $method): array => self::methodSummary($method),
                array_filter($this->methods, static function (object $method): bool {
                    if (!$method instanceof ValaIrFunctionDeclaration) {
                        return false;
                    }
                    $methodArray = $method->toArray();
                    return in_array((string) ($methodArray['role'] ?? ''), ['php_static_method', 'php_instance_method'], true);
                }),
            )),
        ];
    }

    /**
     * Return declared Vala methods/functions in this class container.
     *
     * @return object[]
     */
    public function methods(): array
    {
        return $this->methods;
    }

    /**
     * Return a copy with replaced method declarations.
     *
     * @param object[] $methods
     */
    public function withMethods(array $methods): self
    {
        return new self($this->startLine, $this->endLine, $this->comments, $this->name, $this->phpName, $methods);
    }

    private static function methodSummary(object $method): array
    {
        if (!method_exists($method, 'toArray')) {
            return ['kind' => get_debug_type($method)];
        }

        $methodArray = $method->toArray();
        $phpName = (string) ($methodArray['phpName'] ?? '');
        $phpMethodName = $phpName;
        if (str_contains($phpMethodName, '::')) {
            [, $phpMethodName] = explode('::', $phpMethodName, 2);
        }
        $params = is_array($methodArray['params'] ?? null) ? $methodArray['params'] : [];
        $role = (string) ($methodArray['role'] ?? '');

        return [
            'kind' => 'ClassMethodSummary',
            'phpName' => $phpName,
            'phpMethodName' => $phpMethodName,
            'valaName' => (string) ($methodArray['name'] ?? ''),
            'handlerSymbol' => (string) ($methodArray['qualifiedName'] ?? $methodArray['name'] ?? ''),
            'static' => $role === 'php_static_method',
            'instance' => $role === 'php_instance_method',
            'visibility' => (string) ($methodArray['visibility'] ?? 'public'),
            'minArgs' => count($params),
            'maxArgs' => count($params),
        ];
    }
}
