<?php

namespace Tests\Browser;

use Illuminate\Foundation\Testing\DatabaseMigrations;
use Illuminate\Foundation\Testing\WithFaker;
use Laravel\Dusk\Browser;
use Tests\DuskTestCase;

use Tests\Browser\Pages\Login;
use Tests\Browser\Components\Feedback;
use Tests\Browser\Components\Editor;
use Tests\Browser\Components\AddContentElement;
use Tests\Browser\Components\Autocomplete;

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

class CourseListTest extends DuskTestCase
{
    use WithFaker;

    public function test_a_course_list_can_be_viewed_with_courses_and_staff_profiles()
    {
        $this->browse(function ($browser) {
            $page = Page::factory()->create();
            $user = User::factory()->create();
            $user->createPermission('publish', $page);

            $browser->visit(new Login())
                ->loginAndEditPage($page, $user)
                ->waitFor('@content-elements-editor')
                ->with(new AddContentElement(), function ($browser) {
                    $browser->create('course-list');
                });

            $content_element = ContentElement::all()->last();
            $header = $this->faker->sentence(3);
            $body = $this->faker->paragraph();
            $tag = Tag::where('name', 'Dance')->firstOrFail();
            $title = $this->faker->word();

            $courses = Course::whereHas('tags', function ($query) {
                $query->where('name', 'Dance');
            })->get();
            $this->assertTrue($courses->count() > 0);
            $courses->each(function ($course) {
                $course->publish();
            });

            $browser->with('@content-element-'.$content_element->id, function ($browser) use ($header, $body, $content_element, $tag, $title) {
                $browser->waitFor('@header')
                        ->with(new Autocomplete('tags'), function ($browser) use ($tag) {
                            $browser->searchAndSelectMultiple($tag, strlen($tag->search_label));
                        })
                        ->type('@header', $header)
                        ->click('@checkbox-toggle-show-profiles')
                        ->type('@profiles-title', $title)
                        ->click('@select-descriptions')
                        ->pause(2500)
                        ->within(new Editor('body', $content_element->id), function ($browser) use ($body) {
                            $browser->typeInEditor($body);
                        });
            })
            ->pause(2500) // so that the debounce triggers
            ->within(new Feedback(), function ($browser) {
                $browser->assertFeedbackContains('Course List Saved');
            });

            $content_element->refresh();

            $this->assertEquals($header, $content_element->content->header);
            $this->assertEquals('<p>'.$body.'</p>', $content_element->content->body);
            $this->assertTrue($content_element->content->show_profiles);
            $this->assertEquals($title, $content_element->content->profiles_title);
            $this->assertTrue($content_element->content->tags->contains('id', $tag->id));
            $this->assertEquals('descriptions', $content_element->content->layout);

            $browser->waitFor('@publish-page')
                ->pause(2500)
                ->click('@publish-page')
                ->acceptDialog()
                ->within(new Feedback(), function ($browser) {
                    $browser->assertFeedbackContains('Page Published');
                })
                ->pause(2500);

            $content_element->refresh();
            $this->assertTrue($content_element->content->courses->count() > 0);
            $this->assertTrue($content_element->content->staff_profiles->count() > 0);

            foreach ($content_element->content->courses as $course) {
                $course->publish();
            }
            $course = $content_element->content->courses->random();
            $staff_profile = $content_element->content->staff_profiles->random();
            $this->assertNotNull($course->name);
            $this->assertNotNull($course->anchor);
            $this->assertNotNull($course->course_description);
            $course_description = $course->course_description->content;
            $this->assertInstanceOf(CourseDescription::class, $course_description);
            $this->assertNotNull($staff_profile->full_name);

            $browser->clickAndWaitForReload('@editing-button')
                ->assertNotPresent('@page-editor')
                ->waitFor('@content-element-'.$content_element->id)
                ->with('@content-element-'.$content_element->id, function ($browser) use ($content_element, $course, $staff_profile, $header, $body, $title) {
                    $browser->waitFor('@course-'.$course->id)
                            ->assertSee($header)
                            ->assertSee($body)
                            ->assertSee($course->name)
                            ->assertSee($title)
                            ->assertSee($staff_profile->full_name)
                            ->clickLink($course->name);
                })
                ->pause(500)
                ->assertFragmentIs($course->anchor)
                ->with('@modal', function ($browser) use ($course_description) {
                    $browser->waitFor('@course-description-'.$course_description->id)
                            ->pause(500)
                            ->with('@course-description-'.$course_description->id, function ($browser) use ($course_description) {
                                $browser->assertSee($course_description->header)
                                    ->assertSourceHas($course_description->body);
                            })
                            ->click('@close-modal');
                })
                ->pause(500)
                ->with('@content-element-'.$content_element->id, function ($browser) use ($staff_profile) {
                    $browser->clickLink($staff_profile->full_name);
                })
                ->pause(500)
                ->assertFragmentIs($staff_profile->anchor)
                ->with('@modal', function ($browser) use ($staff_profile) {
                    $browser->waitFor('@staff-profile-'.$staff_profile->id)
                            ->with('@staff-profile-'.$staff_profile->id, function ($browser) use ($staff_profile) {
                                $browser->assertSee($staff_profile->full_name)
                                    ->assertSourceHas($staff_profile->bio);
                            })
                            ->click('@close-modal');
                });
        });
    }
}
