<?php

namespace Tests\Feature;

use App\Notifications\AddedToSiteNotification;
use App\Tier;
use Carbon\Carbon;
use Database\Seeders\Global\GlobalRoleSeed;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Illuminate\Foundation\Testing\WithFaker;
use Illuminate\Support\Facades\Notification;
use Mtc\MercuryDataModels\Tenant;
use Mtc\MercuryDataModels\User;
use Tests\TestCase;
use Tests\UserForTenant;

class SiteControllerTest extends TestCase
{
    use RefreshDatabase;
    use UserForTenant;

    /**
     * A basic feature test example.
     *
     * @return void
     */
    public function testIndex()
    {
        Tenant::factory(5)->create();

        $response = $this->actingAs($this->getUser())
            ->getJson(route('sites.index'));

        $response->assertStatus(200);
        $this->assertIsArray($response->json('data'));
        $this->assertCount(5, $response->json('data'));
    }

    public function testGetUserRoles()
    {
        $this->seed(GlobalRoleSeed::class);
        $response = $this->actingAs($this->getUser())
            ->getJson(route('sites.roles'));

        $response->assertStatus(200);
        $this->assertIsArray($response->json());
        $this->assertCount(5, $response->json());
    }

    public function testCreateSite()
    {
        $response = $this->actingAs($this->getUser())
            ->postJson(route('sites.store'), [
                'name' => 'foo baz',
                'tier' => Tier::LITE->value,
            ]);

        $response->assertStatus(200);
        $this->assertTrue(Tenant::query()->where('name', 'foo baz')->exists());
    }

    public function testInviteUser()
    {
        Notification::fake();
        $this->seed(GlobalRoleSeed::class);

        $tenant = Tenant::factory()->create();
        $response = $this->actingAs($this->getUser())
            ->postJson(route('sites.invite-user', $tenant), [
                'email' => 'jdoe@example.com',
                'role' => 'Administrator',
            ]);

        $response->assertStatus(200);

        $user = User::query()->where('email', 'jdoe@example.com')->first();
        $this->assertInstanceOf(User::class, $user);
        Notification::assertSentTo($user, AddedToSiteNotification::class);
    }

    public function testUpdateUser()
    {
        $tenant = Tenant::factory()->create();
        $user = User::factory()->create();
        $tenant->users()->attach($user, ['role' => 'Administrator']);

        $user_data = $tenant->users()->where('user_id', $user->id)->first();
        $this->assertEquals('Administrator', $user_data->pivot->role);

        $response = $this->actingAs($this->getUser())
            ->postJson(route('sites.update-user', $tenant), [
                'userId' => $user->id,
                'role' => 'Editor',
            ]);

        $response->assertStatus(200);
        $user_data = $tenant->users()->where('user_id', $user->id)->first();
        $this->assertEquals('Editor', $user_data->pivot->role);
    }

    public function testRemoveUser()
    {
        $tenant = Tenant::factory()->create();
        $user = User::factory()->create();
        $tenant->users()->attach($user);

        $this->assertTrue($tenant->users()->where('user_id', $user->id)->exists());

        $response = $this->actingAs($this->getUser())
            ->postJson(route('sites.remove-user', $tenant), [
                'userId' => $user->id
            ]);

        $response->assertStatus(200);
        $this->assertFalse($tenant->users()->where('user_id', $user->id)->exists());
    }

    public function testSuspend()
    {
        $tenant = Tenant::factory()->create([
            'suspended_at' => null,
            'suspended_by' => null,
        ]);

        $response = $this->actingAs($this->getUser())
            ->postJson(route('sites.suspend', $tenant));

        $response->assertStatus(200);
        $tenant->refresh();
        $this->assertTrue($tenant->is_suspended);
        $this->assertEquals($this->getUser()->id, $tenant->suspended_by);
    }

    public function testUnsuspend()
    {
        $tenant = Tenant::factory()->create([
            'suspended_at' => Carbon::now(),
            'suspended_by' => $this->getUser()->id,
        ]);

        $response = $this->actingAs($this->getUser())
            ->postJson(route('sites.unsuspend', $tenant));

        $response->assertStatus(200);
        $tenant->refresh();
        $this->assertFalse($tenant->is_suspended);
        $this->assertNull($tenant->suspended_by);
    }
}
