<?php
declare(strict_types=1);

namespace PpPhp\Core\Designer\Build\Contracts;

final class BuildManifest
{
    /** @param array<int, BuildArtifact> $artifacts */
    public function __construct(
        private readonly string $applicationId,
        private readonly string $version = '1.0.0',
        private readonly array $artifacts = [],
        private readonly array $routes = [],
        private readonly array $assets = [],
        private readonly array $meta = []
    ) {}

    public static function create(string $applicationId, array $artifacts, array $routes = [], array $assets = [], array $meta = []): self
    {
        return new self($applicationId, '1.0.0', $artifacts, $routes, $assets, $meta);
    }

    public function applicationId(): string { return $this->applicationId; }
    public function artifacts(): array { return $this->artifacts; }
    public function routes(): array { return $this->routes; }
    public function assets(): array { return $this->assets; }

    public function summary(): array
    {
        return [
            'applicationId' => $this->applicationId,
            'version' => $this->version,
            'generatedAt' => date('c'),
            'artifacts' => count($this->artifacts),
            'pages' => count(array_filter($this->artifacts, static fn (BuildArtifact $artifact): bool => $artifact->type() === 'page')),
            'routes' => count($this->routes),
            'assets' => count((array) ($this->assets['manifest']['assets'] ?? $this->assets['assets'] ?? [])),
            'bytes' => array_sum(array_map(static fn (BuildArtifact $artifact): int => $artifact->bytes(), $this->artifacts)),
        ];
    }

    public function manifestArtifact(): BuildArtifact
    {
        return BuildArtifact::create(
            'manifest_json',
            'manifest',
            'manifest.json',
            json_encode($this->toArray(), JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES)
        );
    }

    public function withManifestArtifact(): self
    {
        return new self(
            $this->applicationId,
            $this->version,
            array_merge($this->artifacts, [$this->manifestArtifact()]),
            $this->routes,
            $this->assets,
            $this->meta
        );
    }

    public function toArray(): array
    {
        return [
            'applicationId' => $this->applicationId,
            'version' => $this->version,
            'generatedAt' => date('c'),
            'routes' => $this->routes,
            'assets' => $this->assets,
            'artifacts' => array_map(static fn (BuildArtifact $artifact): array => [
                'id' => $artifact->id(),
                'type' => $artifact->type(),
                'path' => $artifact->path(),
                'checksum' => $artifact->checksum(),
                'bytes' => $artifact->bytes(),
            ], $this->artifacts),
            'summary' => $this->summary(),
            'meta' => $this->meta,
        ];
    }
}
