<?php

namespace Tests\Feature;

use App\Master\SiteManager;
use Database\Seeders\Global\GlobalRoleSeed;
use Mtc\MercuryDataModels\Role;
use Mtc\MercuryDataModels\Tenant;
use Mtc\MercuryDataModels\User;
use Tests\DatabaseTestCase;

class SiteManagerTest extends DatabaseTestCase
{
    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);

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

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

        $user1 = User::factory()->create(['name' => 'John Doe', 'email' => 'john@example.com']);
        $user2 = User::factory()->create(['name' => 'Jane Smith', 'email' => 'jane@example.com']);
        $user3 = User::factory()->create(['name' => 'Bob Wilson', 'email' => 'bob@example.com']);
        $tenant->users()->attach([$user1->id, $user2->id, $user3->id]);

        $result = $this->siteManager()->getSiteUsers($tenant->id, 'John');
        $this->assertEquals(1, $result->total());
        $this->assertEquals('John Doe', $result->first()->name);

        $result = $this->siteManager()->getSiteUsers($tenant->id, 'example.com');
        $this->assertEquals(3, $result->total());
    }

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

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

        $result = $this->siteManager()->getSiteUsers($tenant->id, null, 2, 1);
        $this->assertEquals(5, $result->total());
        $this->assertEquals(2, $result->count());
        $this->assertEquals(3, $result->lastPage());
    }

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