<?php

namespace Tests\Feature;

use Tests\TestCase;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Spatie\Permission\Models\Permission;
use Spatie\Permission\Models\Role;
use Spatie\Permission\PermissionRegistrar;

use App\User;

class UserControllerTest extends TestCase
{
    use RefreshDatabase;

    protected $adminToken;
    protected $factory;

    /**
    * A basic test example.
    *
    * @return void
    */
    public function setUp(): void
    {
        parent::setUp();

        $this->setupPermissions();

        $admin = factory(User::class)->create();
        $this->app->make(\Spatie\Permission\PermissionRegistrar::class)->registerPermissions();
        $admin->assignRole('Admin');
        $this->adminToken = \JWTAuth::fromUser($admin);
        $this->factory = factory(User::class)->make()->toArray();
    }

    public function testGETAll()
    {
        $this->withHeaders([
                'Authorization' => 'Bearer '.$this->adminToken,
            ])
            ->json(
                'GET',
                '/api/users'
            )
            ->assertStatus(200)
            ->assertHeader('Content-Type', 'application/json');
    }

    public function testPOST()
    {
        $factory = $this->factory;
        $factory['password'] = 'secret';

        $response = $this->withHeaders([
                'Authorization' => 'Bearer '.$this->adminToken,
            ])
            ->json(
                'POST',
                '/api/users',
                $factory
            )
            ->assertStatus(201)
            ->assertHeader('Content-Type', 'application/json');

        $json = json_decode($response->getContent());
        $factory['id'] = $json->id;

        unset($factory['password']);
        unset($factory['password_confirmation']);

        $response->assertJson($factory);

        $this->assertDatabaseHas('users', [
            'name' => $factory['name'],
            'email' => $factory['email'],
        ]);
    }

    public function testPUT()
    {
        $factory = $this->factory;
        $user = factory(User::class)->create();
        $factory['id'] = $user->id;

        $response = $this->withHeaders([
                'Authorization' => 'Bearer '.$this->adminToken,
            ])
            ->json(
                'PUT',
                '/api/users/'.$user->id,
                $factory
            )
            ->assertStatus(200)
            ->assertHeader('Content-Type', 'application/json')
            ->assertJson($factory);

        $this->assertDatabaseHas('users', [
            'name' => $factory['name'],
            'email' => $factory['email'],
        ]);
    }

    public function testDELETE()
    {
        $user = factory(User::class)->create();

        $this->withHeaders([
                'Authorization' => 'Bearer '.$this->adminToken,
            ])
            ->json(
                'DELETE',
                '/api/users/'.$user->id
            )
            ->assertStatus(204);

        $this->assertDatabaseMissing('users', [ 'id' => $user->id ]);
    }


    public function testDisallowAccessToGuestUser()
    {
        $this->json(
            'GET',
            '/api/users'
        )
            ->assertStatus(401)
            ->assertHeader('Content-Type', 'application/json')
            ->assertJson([
                'message' => __('errors.unauthorized'),
                'message' => 'Token not provided',
            ]);
    }

    public function testACTIVED()
    {
        $user = factory(User::class)->create([
          'deleted_at' => '2019-01-11 12:17:28'
        ]);

        $response = $this->withHeaders([
          'Authorization' => 'Bearer '.$this->adminToken,
        ])
        ->json(
            'PUT',
            '/api/users/'.$user->id.'/actived'
        )
        ->assertStatus(200)
        ->assertHeader('Content-Type', 'application/json');

        $this->assertDatabaseHas('users', [
            'name' => $user->name,
            'email' => $user->email,
        ]);
    }

    public function testINACTIVED()
    {
        $user = factory(User::class)->create();

        $response = $this->withHeaders([
          'Authorization' => 'Bearer '.$this->adminToken,
        ])
        ->json(
            'PUT',
            '/api/users/'.$user->id.'/inactived'
        )
        ->assertStatus(200)
        ->assertHeader('Content-Type', 'application/json');

        $this->assertSoftDeleted('users', [ 'name' => $user->name ]);
    }

    public function testACTIVEDFAIL()
    {
        $user = factory(User::class)->create();

        $response = $this->withHeaders([
          'Authorization' => 'Bearer '.$this->adminToken,
        ])
        ->json(
            'PUT',
            '/api/users/'.$user->id.'/actived'
        )
        ->assertStatus(400)
        ->assertHeader('Content-Type', 'application/json');
    }

    public function testINACTIVEDFAIL()
    {
        $user = factory(User::class)->create([
          'deleted_at' => '2019-01-11 12:17:28'
        ]);

        $response = $this->withHeaders([
          'Authorization' => 'Bearer '.$this->adminToken,
        ])
        ->json(
            'PUT',
            '/api/users/'.$user->id.'/inactived'
        )
        ->assertStatus(400)
        ->assertHeader('Content-Type', 'application/json');

    }

    protected function setupPermissions()
    {
        Permission::create(['name' => 'users.index']);
        Permission::create(['name' => 'users.store']);
        Permission::create(['name' => 'users.update']);
        Permission::create(['name' => 'users.destroy']);

        Role::create(['name' => 'Admin'])->givePermissionTo(Permission::all());

        $this->app->make(PermissionRegistrar::class)->registerPermissions();
    }
}
