<?php

namespace Tests\Feature;

use App\Models\AdminUser;
use App\Models\Expertise;
use App\Models\WorkAreaExpertise;
use App\Models\WorkAreas; 
use App\Modules\Admin\Libraries\ExpertiseModule;

use Illuminate\Foundation\Testing\RefreshDatabase;
use Illuminate\Foundation\Testing\WithFaker;

use Laravel\Sanctum\Sanctum;

use Tests\TestCase;

class SystemLibraryExpertiseTest extends TestCase
{
    use RefreshDatabase;

    private Expertise $expertise;
    private WorkAreas $workArea; 

    /**
     * Set Up Test
     * 
     * @return void 
     */
    protected function setUp(): void
    {
        parent::setUp();

        $superAdmin = AdminUser::factory()->create();

        Sanctum::actingAs(
            $superAdmin,
            ['*']
        );

        $this->expertise = Expertise::factory()
            ->state(
                [
                    'name' => "Software Development"
                ]
            )
            ->create();

        $this->workArea = WorkAreas::factory()
            ->state(
                [
                    'name' => "Embedded Programming"
                ]
            )
            ->create();
    }

    /**
     * Test List Items
     * 
     * @return void 
     */
    public function test_list(): void
    {
        Expertise::factory()->count(20)->create();

        $response = (new ExpertiseModule())->getData([]);

        $this->assertTrue($response->status() == 200, "HTTP Status Code is 200");

        $data = $response->getData(true);

        $this->assertIsArray($data);
        $this->assertArrayHasKey('data', $data);
        $this->assertArrayHasKey('links', $data);
        $this->assertArrayHasKey('meta', $data);

        $this->assertTrue(count($data['data']) >= 10);
    }

    /**
     * Test View Item 
     * 
     * @return void 
     */
    public function test_view(): void
    {
        $response = (new ExpertiseModule())->getDetails($this->expertise->id);

        $this->assertTrue($response->status() == 200, "HTTP Status Code is 200");

        $data = $response->getData(true);

        $this->assertTrue(count($data['data']) >= 1);

        $this->assertEquals('Software Development', $data['data'][0]['name'], "Retrieved Item's name must be 'Software Development'");
    }

    /**
     * Test Create Item
     * 
     * @return void 
     */
    public function test_create(): void
    {
        $workAreasId = []; 

        $workAreas = WorkAreas::factory()
            ->count(5)
            ->create();

        foreach($workAreas as $workArea)
        {
            array_push($workAreasId, $workArea['id']);
        }
        
        $response = (new ExpertiseModule())->storeData(
            [
                "expertise"     => "Python",
                "existing_area" => $workAreasId,
                "newAreas"      => 
                [
                    'Machine Learning', 
                    'Data Analytics', 
                ], 
            ]
        );

        $this->assertDatabaseHas(
            Expertise::class,
            [
                'name' => 'Python'
            ]
        );

        $lastInsertedExpertise = Expertise::query()
            ->where('name', '=', 'Python')
            ->firstOrFail(); 

        $this->assertTrue($response->status() == 201, "HTTP Status Code is 201");

        $this->assertDatabaseHas(
            WorkAreas::class,
            [
                'name' => 'Machine Learning'
            ]
        );

        $this->assertDatabaseHas(
            WorkAreas::class,
            [
                'name' => 'Data Analytics'
            ]
        );

        foreach($workAreas as $workArea)
        {
            $this->assertDatabaseHas(
                WorkAreaExpertise::class,
                [
                    "work_area_id" => $workArea['id'],
                    "expertise_id" => $lastInsertedExpertise->id
                ]
            );
        }
    }

    /**
     * Test Update Item
     * 
     * @return void 
     */
    public function test_update(): void
    {
        $response = (new ExpertiseModule())->updateData(
            [
                "name"        => "Software Engineering",
                "areasOfWork" => 
                [
                    $this->workArea->id 
                ]
            ],
            $this->expertise->id
        );

        $this->assertTrue($response->status() == 200, "HTTP Status Code is 200");

        $this->assertDatabaseHas(
            Expertise::class,
            [
                "id"   => $this->expertise->id,
                "name" => "Software Engineering"
            ]
        );

        $this->assertDatabaseHas(
            WorkAreaExpertise::class,
            [
                "work_area_id" => $this->workArea->id,
                "expertise_id" => $this->expertise->id
            ]
        );
    }

    /**
     * Test Delete Item
     * 
     * @return void 
     */
    public function test_delete(): void
    {
        $currentTableCount = Expertise::count();

        $response = (new ExpertiseModule())->deleteData(
            $this->expertise->id
        );

        $this->assertTrue($response->status() == 200, "HTTP Status Code is 200");

        $this->assertDatabaseCount('expertises', ($currentTableCount - 1));
    }
}
