<?php

declare(strict_types=1);

namespace App\Framework\Database\Migration;

use ArrayIterator;
use Countable;
use IteratorAggregate;
use Traversable;

/**
 * Collection of MigrationStatus objects
 */
final readonly class MigrationStatusCollection implements Countable, IteratorAggregate
{
    /** @var MigrationStatus[] */
    private array $statuses;

    /**
     * @param MigrationStatus[] $statuses
     */
    public function __construct(array $statuses = [])
    {
        $this->statuses = array_values($statuses);
    }

    /**
     * @param MigrationStatus[] $statuses
     */
    public static function fromArray(array $statuses): self
    {
        return new self($statuses);
    }

    public function add(MigrationStatus $status): self
    {
        $statuses = $this->statuses;
        $statuses[] = $status;

        return new self($statuses);
    }

    public function count(): int
    {
        return count($this->statuses);
    }

    public function isEmpty(): bool
    {
        return count($this->statuses) === 0;
    }

    /**
     * Get only applied migrations
     */
    public function getApplied(): self
    {
        return new self(array_filter($this->statuses, fn (MigrationStatus $status) => $status->isApplied()));
    }

    /**
     * Get only pending migrations
     */
    public function getPending(): self
    {
        return new self(array_filter($this->statuses, fn (MigrationStatus $status) => $status->isPending()));
    }

    /**
     * Count applied migrations
     */
    public function countApplied(): int
    {
        return count(array_filter($this->statuses, fn (MigrationStatus $status) => $status->isApplied()));
    }

    /**
     * Count pending migrations
     */
    public function countPending(): int
    {
        return count(array_filter($this->statuses, fn (MigrationStatus $status) => $status->isPending()));
    }

    /**
     * Convert to array for backward compatibility
     * @return array<int, array<string, string|bool>>
     */
    public function toArray(): array
    {
        return array_map(fn (MigrationStatus $status) => $status->toArray(), $this->statuses);
    }

    /**
     * @return Traversable<int, MigrationStatus>
     */
    public function getIterator(): Traversable
    {
        return new ArrayIterator($this->statuses);
    }
}
