<?php

declare(strict_types=1);

namespace Psl\Tests\Unit\Type;

use Iterator;
use Psl\Collection\CollectionInterface;
use Psl\Collection\IndexAccessInterface;
use Psl\Type;

final class IntersectionTypeTest extends TypeTest
{
    public function testIntersectionLeft(): void
    {
        $intersection = Type\intersection(Type\array_key(), Type\int(), Type\positive_int());

        static::assertSame(1, $intersection->coerce('1'));
    }

    #[\Override]
    public function getType(): Type\TypeInterface
    {
        return Type\intersection(Type\int(), Type\array_key());
    }

    #[\Override]
    public function getValidCoercions(): iterable
    {
        yield [1, 1];
        yield ['1', 1];
        yield ['123', 123];
        yield [$this->stringable('123'), 123];
        yield [$this->stringable('000'), 0];
        yield [$this->stringable('0007'), 7];
    }

    #[\Override]
    public function getInvalidCoercions(): iterable
    {
        yield [null];
        yield [STDIN];
        yield ['hello'];
        yield [$this->stringable('foo')];
        yield [new class {}];
    }

    #[\Override]
    public function getToStringExamples(): iterable
    {
        yield [
            Type\intersection(
                Type\instance_of(IndexAccessInterface::class),
                Type\instance_of(CollectionInterface::class),
            ),
            'Psl\Collection\IndexAccessInterface&Psl\Collection\CollectionInterface',
        ];

        yield [
            Type\intersection(
                Type\instance_of(IndexAccessInterface::class),
                Type\union(Type\instance_of(CollectionInterface::class), Type\instance_of(Iterator::class)),
            ),
            'Psl\Collection\IndexAccessInterface&(Psl\Collection\CollectionInterface|Iterator)',
        ];

        yield [
            Type\intersection(
                Type\union(Type\instance_of(CollectionInterface::class), Type\instance_of(Iterator::class)),
                Type\instance_of(IndexAccessInterface::class),
            ),
            '(Psl\Collection\CollectionInterface|Iterator)&Psl\Collection\IndexAccessInterface',
        ];

        yield [
            Type\intersection(
                Type\instance_of(IndexAccessInterface::class),
                Type\instance_of(CollectionInterface::class),
                Type\instance_of(Iterator::class),
                Type\shape(['id' => Type\string()]),
            ),
            'Psl\Collection\IndexAccessInterface&Psl\Collection\CollectionInterface&Iterator&array{\'id\': string}',
        ];
    }
}
