<?php

namespace Ignite\Core\Tests\Unit\Repositories;

use Illuminate\Database\Eloquent\ModelNotFoundException;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Ignite\Core\Entities\Block;
use Ignite\Core\Tests\TestCase;
use Ignite\Core\Repositories\BlockRepository;

class BlockRepositoryTest extends TestCase
{
    use RefreshDatabase;

    /** @var BlockRepository */
    protected $repo;

    /**
     * Set up the test.
     *
     * @return void
     */
    public function setUp(): void
    {
        parent::setUp();

        $this->repo = new BlockRepository();
    }

    /**
     * @test
     * @group Cms
     */
    public function it_returns_the_expected_raw_query_builder()
    {
        $this->assertInstanceOf(
            \Illuminate\Database\Eloquent\Builder::class,
            $this->repo->findRaw(),
            'findRaw should return a Builder object'
        );
    }

    /**
     * @test
     * @group Cms
     */
    public function it_can_get_all_blocks()
    {
        factory(Block::class, 6)->create();

        $blocks = $this->repo->findAll(null);

        $this->assertCount(Block::count(), $blocks);
    }

    /**
     * @test
     * @group Cms
     */
    public function it_can_get_a_paginated_list_of_blocks()
    {
        factory(Block::class, 6)->create();

        /** @var \Illuminate\Pagination\LengthAwarePaginator $blocks */
        $blocks = $this->repo->findAll(2);

        $this->assertInstanceOf(
            \Illuminate\Pagination\LengthAwarePaginator::class,
            $blocks,
            'findAll with a limit should return a paginator'
        );

        $this->assertCount(2, $blocks);
    }

    /**
     * @test
     * @group Cms
     */
    public function it_can_find_one_block_by_id()
    {
        $mock = factory(Block::class)->create();

        $block = $this->repo->find($mock->id);

        $this->assertInstanceOf(
            Block::class,
            $block
        );
        $this->assertEquals($mock->id, $block->getAttribute('id'));
    }

    /**
     * @test
     * @group Cms
     */
    public function it_will_throw_a_model_not_found_exception_when_it_cannot_find_a_block_by_id()
    {
        $this->expectException(ModelNotFoundException::class);

        $this->repo->find(100);
    }

    /**
     * @test
     * @group Cms
     */
    public function it_will_find_only_active_published_blocks_using_find_by_code()
    {
        $code = 'my_claim_instructions';

        factory(Block::class)->create([
            'code' => $code,
            'status' => Block::ACTIVE,
            'published_at' => \Carbon\Carbon::now()->subDay(1)
        ]);

        $block = $this->repo->findByCode($code);

        $this->assertEquals($code, $block->getAttribute('code'));
    }

    /**
     * @test
     * @group Cms
     */
    public function it_will_return_an_empty_block_model_when_it_cannot_find_a_block_by_code()
    {
        $code = 'my_claim_instructions';
        /** @var Block $test */
        factory(Block::class, 1)->create([
            'code' => $code,
            'status' => 'inactive',
            'published_at' => \Carbon\Carbon::now()->addMonth(1)
        ]);

        $block = $this->repo->findByCode($code);

        $this->assertEquals(0, $block->getKey());
    }

    /**
     * @test
     * @group Cms
     */
    public function it_can_create_a_new_block()
    {
        $dummy = factory(Block::class)->make([
            'name' => 'Test',
            'code' => 'Test code!'
        ]);

        $block = $this->repo->create($dummy->toArray());

        $this->assertEquals('test_code', $block->getAttribute('code'));
    }

    /**
     * @test
     * @group Cms
     */
    public function it_can_update_an_existing_block()
    {
        $dummy = factory(Block::class)->create([
            'name' => 'Test',
            'code' => 'test_code'
        ]);

        $this->repo->update($dummy->getAttribute('id'), [
            'code' => 'test_slug'
        ]);

        $block = $this->repo->find($dummy->getAttribute('id'));

        $this->assertEquals('test_slug', $block->getAttribute('code'));
    }
}
