<?php

declare(strict_types=1);

namespace FeatureTests\Entity;

use apexl\Io\TestInfrastructure\FeatureTest;
use Apexl\Tests\Core\Infrastructure\TestEntity;
use Apexl\Tests\Core\Infrastructure\TestRelatedEntity;
use Apexl\Tests\Core\Infrastructure\UsesTestEntities;
use PHPUnit\Framework\Attributes\Test;

class FindTest extends FeatureTest
{
    use UsesTestEntities;

    #[Test]
    public function notFound(): void
    {
        TestEntity::factory()->create([
            'id' => 1,
        ]);

        TestEntity::factory()->create([
            'id' => 2,
        ]);

        TestEntity::factory()->create([
            'id' => 3,
        ]);

        $found = TestEntity::find(4);

        $this->assertNull($found);
    }

    #[Test]
    public function find(): void
    {
        [, , $wanted] = TestEntity::factory()->createMany(5);

        $found = TestEntity::find($wanted->id);

        $this->assertSame($wanted->id, $found->id);
    }

    #[Test]
    public function findWhere(): void
    {
        TestEntity::factory()->create([
            'name' => $this->faker->unique()->name(),
        ]);

        $wantedName = $this->faker->unique()->name();
        $wanted = TestEntity::factory()->create([
            'name' => $wantedName,
        ]);

        TestEntity::factory()->create([
            'name' => $this->faker->unique()->name(),
        ]);

        $found = TestEntity::findWhere('name', $wantedName);

        $this->assertSame($wanted->id, $found->id);
    }

    #[Test]
    public function findWithVirtualField(): void
    {
        $name = $this->faker->unique()->name();
        $wanted = TestEntity::factory()->create([
            'name' => $name,
        ]);

        $found = TestEntity::find($wanted->id, ['name_twice']);
        $this->assertSame("$name$name", $found->name_twice);
    }

    #[Test]
    public function findWithRelationFields(): void
    {
        $entity = TestEntity::factory()->create();
        $relatedName = $this->faker->name();

        $related = TestRelatedEntity::factory()->create([
            'name' => $relatedName,
            'test_entity_id' => $entity->id,
        ]);

        $found = TestEntity::find($entity->id, [
            'belongs_to.name',
            'belongs_to.name_twice'
        ]);

        $this->assertSame($related->id, $found->belongs_to->id);
        $this->assertSame($relatedName, $found->belongs_to->name);
        $this->assertSame("$relatedName$relatedName", $found->belongs_to->name_twice);
    }

    protected function setUp(): void
    {
        parent::setUp();

        $this->createTestEntityTables();
    }


    protected function tearDown(): void
    {
        parent::tearDown();
        $this->dropTestEntityTables();
    }
}