<?php

namespace Tests\Feature;

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

use Illuminate\Support\Str;
use Illuminate\Support\Arr;

use Tests\Feature\ContentElementsTestTrait;
use Tests\Feature\TagExcludeTestTrait;
use Tests\Feature\ContentElementsSearchTestTrait;

use App\Models\CourseList;
use App\Models\Tag;
use App\Models\Page;
use App\Models\ContentElement;
use App\Models\Course;
use App\Models\CourseDescription;

class CourseListTest extends TestCase
{
    use ContentElementsTestTrait;
    use WithFaker;
    use TagExcludeTestTrait;
    use ContentElementsSearchTestTrait;

    protected function getClassname()
    {
        return 'course-list';
    }

    public function test_a_course_list_can_be_created()
    {
        $tag1 = Tag::factory()->create();
        $tag2 = Tag::factory()->create();

        $page = Page::factory()->create();

        $course_list_input = CourseList::factory()->raw();

        $input = [
            'pivot' => $this->getContentableArray($page),
            'type' => Str::kebab(class_basename(CourseList::class)),
            'content' => array_merge($course_list_input, [
                'tags' => [
                    [ 'id' => $tag1->id, 'pivot' => ['exclude' => false ]],
                    [ 'id' => $tag2->id, 'pivot' => ['exclude' => true ]],
                ]
            ]),
        ];

        $this->signInAdmin();
        $this->enableEditing();

        $this->json('POST', route('content-elements.store'), $input)
             ->assertSuccessful()
             ->assertJsonFragment([
                 'success' => 'Course List Saved',
             ]);

        $content_element = ContentElement::all()->last();
        $this->assertInstanceOf(ContentElement::class, $content_element);

        $course_list = $content_element->content;

        $this->assertNotNull($course_list->header);
        $this->assertNotNull($course_list->body);
        $this->assertNotNull($course_list->layout);
        $this->assertNotNull($course_list->show_profiles);
        $this->assertNotNull($course_list->profiles_title);

        $this->assertEquals(Arr::get($input, 'content.header'), $course_list->header);
        $this->assertEquals(Arr::get($input, 'content.body'), $course_list->body);
        $this->assertEquals(Arr::get($input, 'content.layout'), $course_list->layout);
        $this->assertEquals(Arr::get($input, 'content.show_profiles'), $course_list->show_profiles);
        $this->assertEquals(Arr::get($input, 'content.profiles_title'), $course_list->profiles_title);

        $this->assertEquals($tag1->id, $course_list->tags->first()->id);
        $this->assertNotNull($course_list->tags->first()->pivot);
        $this->assertEquals(0, $course_list->tags->first()->pivot->exclude);

        $this->assertEquals($tag2->id, $course_list->tags->last()->id);
        $this->assertNotNull($course_list->tags->last()->pivot);
        $this->assertEquals(1, $course_list->tags->last()->pivot->exclude);
    }

    public function test_a_course_list_can_be_updated()
    {
        $tag1 = Tag::factory()->create();
        $tag2 = Tag::factory()->create();

        $page = Page::factory()->create();
        $content_element = $this->createContentElement(CourseList::factory(), $page);
        $course_list = $content_element->content;
        $course_list->addTag($tag2);

        $old_header = $course_list->header;
        $old_body = $course_list->body;
        $old_layout = $course_list->layout;
        $old_show_profiles = $course_list->show_profiles;
        $old_profiles_title = $course_list->profiles_title;

        $input = $content_element->toArray();
        $input['content'] = array_merge($course_list->toArray(), CourseList::factory()->raw());
        $input['pivot'] = $this->getContentableArray($page);

        $input['content']['tags'] = [
            [ 'id' => $tag1->id, 'pivot' => ['exclude' => false ]],
            [ 'id' => $tag2->id, 'pivot' => ['exclude' => true ]],
        ];

        $this->signInAdmin();
        $this->enableEditing();

        $this->json('POST', route('content-elements.update', ['id' => $content_element->id]), $input)
             ->assertSuccessful()
             ->assertJsonFragment([
                 'success' => 'Course List Saved',
             ]);

        $course_list->refresh();

        $this->assertEquals($content_element->id, ContentElement::all()->last()->id);
        $this->assertEquals($course_list->id, CourseList::all()->last()->id);

        $this->assertNotEquals($old_header, $course_list->header);
        $this->assertNotEquals($old_body, $course_list->body);
        $this->assertNotEquals($old_layout, $course_list->layout);
        $this->assertEquals(Arr::get($input, 'content.header'), $course_list->header);
        $this->assertEquals(Arr::get($input, 'content.body'), $course_list->body);
        $this->assertEquals(Arr::get($input, 'content.layout'), $course_list->layout);
        $this->assertEquals(Arr::get($input, 'content.show_profiles'), $course_list->show_profiles);
        $this->assertEquals(Arr::get($input, 'content.profiles_title'), $course_list->profiles_title);

        $this->assertEquals($tag1->id, $course_list->tags->first()->id);
        $this->assertNotNull($course_list->tags->first()->pivot);
        $this->assertEquals(0, $course_list->tags->first()->pivot->exclude);

        $this->assertEquals($tag2->id, $course_list->tags->last()->id);
        $this->assertNotNull($course_list->tags->last()->pivot);
        $this->assertEquals(1, $course_list->tags->last()->pivot->exclude);
    }

    public function test_courses_can_be_loaded_for_a_course_list()
    {
        $tag = Tag::factory()->create();
        $course = Course::factory()->create();
        $course_content_element = $this->createContentElement(CourseDescription::factory(), $course);
        $course_description = $course_content_element->content;
        $course->addTag($tag);
        $course->publish();

        $page = Page::factory()->create();
        $content_element = $this->createContentElement(CourseList::factory(), $page);
        $course_list = $content_element->content;
        $course_list->addTag($tag);

        $page->publish();

        $course_list->refresh();

        $this->assertTrue($course_list->courses->contains('id', $course->id));
        $this->assertNotNull($course->course_description->uuid);

        $this->json('GET', route('course-lists.courses', ['id' => $course_list->id]))
            ->assertSuccessful()
            ->assertJsonFragment([
                'id' => $course->id,
                'name' => $course->version->name,
                'uuid' => $course->course_description->uuid,
                'id' => $course->course_description->id,
                'type' => 'course-description',
            ]);
    }
}
