<?php

namespace Tests\Unit;

use Illuminate\Foundation\Testing\WithFaker;
use Tests\TestCase;
use Illuminate\Support\Str;

use App\Models\Course;
use App\Models\CourseDescription;
use App\Models\ContentElement;
use App\Models\PhotoBlock;

use Tests\Unit\AppendAttributesTestTrait;
use Tests\Unit\ContentElementsTestTrait;
use Tests\Unit\VersioningTestTrait;
use Tests\Unit\TagsTrait;
use Tests\Unit\PermissionsTestTrait;

use App\Models\Tag;
use App\Utilities\PageLink;

class CourseTest extends TestCase
{
    use WithFaker;
    use AppendAttributesTestTrait;
    use ContentElementsTestTrait;
    use VersioningTestTrait;
    use TagsTrait;
    use PermissionsTestTrait;

    protected function getModel()
    {
        return Course::factory()->create();
    }

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

    public function test_course_can_be_found_via_tags()
    {
        $course1 = Course::factory()->create();
        $course2 = Course::factory()->create();

        $tag = Tag::factory()->create();

        $course1->addTag($tag);

        $course1->publish();
        $course2->publish();

        $courses = (new Course())->getByTags();
        $this->assertTrue($courses->contains('id', $course1->id));
        $this->assertTrue($courses->contains('id', $course2->id));

        $courses = (new Course())->getByTags(['tags' => [$tag]]);
        $this->assertTrue($courses->contains('id', $course1->id));
        $this->assertFalse($courses->contains('id', $course2->id));
    }

    public function test_unlisted_courses_can_be_excluded_by_when_filtering_by_tags(): void
    {
        $course1 = Course::factory()->create();
        $course2 = Course::factory()->create();

        $tag = Tag::factory()->create();

        $course1->addTag($tag);
        $course2->addTag($tag);

        $course1->publish();
        $course2->publish();

        $courses = (new Course())->getByTags();
        $this->assertTrue($courses->contains('id', $course1->id));
        $this->assertTrue($courses->contains('id', $course2->id));

        $courses = (new Course())->getByTags(['tags' => [$tag]]);
        $this->assertTrue($courses->contains('id', $course1->id));
        $this->assertTrue($courses->contains('id', $course2->id));

        $version = $course2->version;
        $version->unlisted = true;
        $version->save();

        $courses = (new Course())->getByTags(['tags' => [$tag]]);
        $this->assertTrue($courses->contains('id', $course1->id));
        $this->assertFalse($courses->contains('id', $course2->id));
    }

    public function test_a_course_has_a_course_description_attribute()
    {
        $course = Course::factory()->create();
        $content_element = $this->createContentElement(CourseDescription::factory(), $course);
        $course_description = $content_element->content;
        $course->publish();

        $this->assertEquals($content_element->id, $course->course_description->id);
        $this->assertInstanceOf(ContentElement::class, $course->course_description);

        $this->assertEquals($course_description->id, $course->course_description->content->id);
        $this->assertInstanceOf(CourseDescription::class, $course->course_description->content);
    }

    public function test_a_course_has_a_full_description()
    {
        $course = Course::factory()->create();
        $this->assertNotNull($course->external_content);
        $this->assertEquals(0, $course->external_content->count());

        $content_element = $this->createContentElement(CourseDescription::factory(), $course);
        $course_description = $content_element->content;
        $course->publish();

        $this->assertEquals(1, $course->external_content->count());
        $this->assertEquals($course_description->id, $course->external_content->first()->content->id);

        $content_element2 = $this->createContentElement(PhotoBlock::factory()->withText(), $course);
        $photo_block = $content_element2->content;
        $course->publish();

        // if we have non course description content use that instead
        $this->assertEquals(1, $course->external_content->count());
        $this->assertEquals($photo_block->id, $course->external_content->first()->content->id);
    }

    public function test_a_course_has_an_anchor()
    {
        $course = Course::factory()->create();
        $content_element = $this->createContentElement(CourseDescription::factory(), $course);
        $course_description = $content_element->content;
        $course->publish();

        $course->refresh();
        $this->assertNotNull($course->anchor);
        $this->assertEquals(PageLink::convertAnchorText($course->course_description->content->header), $course->anchor);
    }

    public function test_a_course_can_get_text_from_a_slug()
    {
        $slug = 'courses/foo-bar-baz';
        $result = (new Course())->getTextFromSlug($slug);
        $this->assertEquals('Foo Bar Baz', $result);
    }
}
