<?php

namespace Tests\Unit;

use App\Master\SiteManager;
use App\Tier;
use Database\Seeders\Global\GlobalRoleSeed;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Illuminate\Support\Facades\Queue;
use Mtc\MercuryDataModels\Role;
use Mtc\MercuryDataModels\Tenant;
use Mtc\MercuryDataModels\User;
use Tests\TestCase;

class SiteManagerTest extends TestCase
{
    use RefreshDatabase;

    protected bool $tenancy_make_databases = false;
    
    public function testAbleToAddSiteRecord()
    {
        $site = $this->siteManager()->addSiteRecord('foo', 'bar');

        $exists = Tenant::query()
            ->where('name', 'foo')
            ->whereHas('domains', fn($query) => $query->where('domain', 'bar'))
            ->exists();

        $this->assertTrue($exists);

        $this->assertEquals('foo', $site->name);
    }

    public function testAddExistingUser()
    {
        /** @var User $user */
        $user = User::factory()->create();
        $siteManager = $this->siteManager();
        $site = $siteManager->addSiteRecord('foo', 'baz');
        Role::query()->create(['name' => 'administrator']);

        $siteManager->addUser($user->email, $site->id, 'administrator');

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

    public function testAddNewUser()
    {
        $siteManager = $this->siteManager();
        $site = $siteManager->addSiteRecord('foo', 'baz');
        Role::query()->create(['name' => 'administrator']);

        $email = 'foo@example.com';
        User::query()->where('email', $email)->delete();
        $this->assertFalse($site->users()->where('email', $email)->exists());

        $siteManager->addUser($email, $site->id, 'administrator');

        $this->assertTrue($site->users()->where('email', $email)->exists());
    }

    public function testRemoveUser()
    {
        /** @var User $user */
        $user = User::factory()->create();
        $siteManager = $this->siteManager();
        $site = $siteManager->addSiteRecord('foo', 'baz');
        Role::query()->create(['name' => 'administrator']);

        $siteManager->addUser($user->email, $site->id, 'administrator');
        $this->assertTrue($site->users()->where('user_id', $user->id)->exists());

        $siteManager->removeUser($user->id, $site->id);
        $this->assertFalse($site->users()->where('user_id', $user->id)->exists());
    }

    public function testChangeUserRole()
    {
        $this->seed(GlobalRoleSeed::class);
        /** @var User $user */
        $user = User::factory()->create();
        $siteManager = $this->siteManager();
        $site = $siteManager->addSiteRecord('foo', 'baz');

        $siteManager->addUser($user->email, $site->id, 'Administrator');
        $this->assertTrue($site->users()->where('user_id', $user->id)->where('role', 'Administrator')->exists());

        $siteManager->changeUserRole($site->id, $user->id, 'Manager');
        $this->assertFalse($site->users()->where('user_id', $user->id)->where('role', 'Administrator')->exists());
        $this->assertTrue($site->users()->where('user_id', $user->id)->where('role', 'Manager')->exists());
    }

    public function testSuspendSite()
    {
        $siteManager = $this->siteManager();
        /** @var User $user */
        $user = User::factory()->create();
        $site = $siteManager->addSiteRecord('foo', 'baz');
        $siteManager->suspendSite($site, $user, 'Lorem ipsum');

        $this->assertTrue($site->isSuspended);
        $this->assertEquals($user->id, $site->suspended_by);
        $this->assertEquals('Lorem ipsum', $site->suspended_message);
    }

    public function testUnsuspendSite()
    {
        $siteManager = $this->siteManager();
        /** @var User $user */
        $user = User::factory()->create();
        $site = $siteManager->addSiteRecord('foo', 'baz');
        $siteManager->suspendSite($site, $user, 'Lorem ipsum');

        $this->assertTrue($site->isSuspended);

        $siteManager->unsuspendSite($site);

        $this->assertFalse($site->isSuspended);
        $this->assertNull($site->suspended_at);
        $this->assertNull($site->suspended_by);
        $this->assertNull($site->suspended_message);
    }

    public function testGetSiteUsers()
    {
        $tenant = Tenant::factory()->create();

        $users = User::factory(3)->create();
        $tenant->users()->attach($users);

        $users = $this->siteManager()->getSiteUsers($tenant->id);
        $this->assertEquals(3, $users->count());
    }

    private function siteManager(): SiteManager
    {
        /** @var SiteManager $manager */
        return app(SiteManager::class);
    }
}
