<?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 App\Models\Page;
use App\Models\User;

class PageTreeTest extends DuskTestCase
{
    use WithFaker;

    public function test_the_page_tree_can_be_expanded()
    {
        $this->browse(function ($browser) {
            $parent_page = Page::factory()->create();
            $page = Page::factory()->create();
            $version = $page->versions->first();
            $version->parent_page_id = $parent_page->id;
            $version->sort_order = 1;
            $version->save();
            $page_name = $page->getDraftVersion()->name;
            $this->assertNotNull($page_name);

            $user = User::factory()->create();
            $user->createPermission('update', $page);

            $browser->visit(new Login())
                ->loginAndEdit($user)
                ->mouseover('@page-side-menu-header')
                ->waitFor('@page-tree', 20)
                ->with('@page-tree', function ($browser) use ($page, $page_name, $parent_page) {
                    $browser->assertDontSee($page_name)
                        ->waitFor('@page-list-expander-'.$parent_page->id, 20)
                        ->pause(500)
                        ->click('@page-list-expander-'.$parent_page->id)
                        ->pause(500)
                        ->with('@page-list-'.$parent_page->id, function ($browser) use ($page_name) {
                            $browser->assertSee($page_name);
                        })
                        ->click('@page-list-expander-'.$parent_page->id)
                        ->pause(1000)
                        ->with('@page-list-'.$parent_page->id, function ($browser) use ($page_name) {
                            $browser->assertDontSee($page_name);
                        })
                        ->click('@page-list-expander-'.$parent_page->id)
                        ->pause(200)
                        ->click('@page-list-'.$page->id);
                })
                ->waitUntilVue('page.id', $page->id, '@page-editor');
        });
    }

    public function test_a_new_page_can_be_added_to_the_page_tree_below_and_inside()
    {
        $this->browse(function ($browser) {
            $new_page_name = $this->faker->firstName();
            $existing_page = Page::factory()->create();
            $this->assertEquals(1, $existing_page->getDraftVersion()->parent_page_id);
            $user = User::factory()->create();
            //$user->addRole('pages-editor');

            $browser->visit(new Login())
                ->loginAndEdit($user)
                ->mouseover('@page-side-menu-header')
                ->pause(200)
                ->click('@add-page')
                ->with('@page-tree', function ($browser) use ($new_page_name, $existing_page) {
                    $browser->waitFor('@page-list-'.$existing_page->id, 30)
                        ->pause(500)
                        ->mouseover('@page-list-'.$existing_page->id)
                        ->assertMissing('@add-page-below-'.$existing_page->id);
                });

            $user->createPermission('update', Page::find($existing_page->getDraftVersion()->parent_page_id));

            $browser->refresh()
                ->waitFor('@content-elements-editor')
                ->mouseover('@content-elements-editor')
                ->pause(1000)
                ->waitFor('@page-side-menu-header')
                ->click('@page-side-menu-header')
                ->mouseover('@add-page')
                ->pause(250)
                ->click('@add-page')
                ->with('@page-tree', function ($browser) use ($new_page_name, $existing_page) {
                    $browser->waitFor('@page-list-'.$existing_page->id, 30)
                        ->pause(500)
                        ->mouseover('@page-list-'.$existing_page->id)
                        ->click('@add-page-below-'.$existing_page->id)
                        ->whenAvailable('@add-page-form-'.$existing_page->id, function ($browser) use ($new_page_name) {
                            $browser->type('@new-page-name', $new_page_name)
                                ->click('@create-new-page');
                        });
                })
                ->within(new Feedback(), function ($browser) use ($new_page_name) {
                    $browser->assertFeedbackContains($new_page_name.' Saved');
                })
                ->pause(500);

            $new_page = Page::all()->last();

            $browser->waitUntilVue('page.id', $new_page->id, '@page-editor')
                ->assertPathIs('/'.$this->getEditingValue($new_page, 'full_slug'))
                ->pause(500)
                ->mouseover('@page-side-menu-header')
                ->with('@page-tree', function ($browser) use ($new_page_name, $new_page) {
                    $browser->assertMissing('@new-page-name')
                        ->assertMissing('@create-new-page')
                        ->assertMissing('@processing-new-page')
                        ->waitFor('@page-list-'.$new_page->id, 15)
                        ->assertSee($new_page_name);
                })
                ->assertVue('addPage', false, '@page-side-menu');

            $this->assertTrue($user->can('update', $new_page));
            $browser->waitUntilVue('page.id', $new_page->id, '@page-editor');

            $browser->with('@page-tree', function ($browser) use ($new_page_name, $existing_page) {
                $browser->mouseover('@page-list-'.$existing_page->id)
                    ->assertMissing('@add-page-inside-'.$existing_page->id);
            });

            $user->createPermission('update', $existing_page);

            $browser->refresh()
                ->waitFor('@content-elements-editor')
                ->mouseover('@content-elements-editor')
                ->pause(1000)
                ->waitFor('@page-side-menu-header')
                    ->mouseover('@page-side-menu-header')
                    ->pause(200)
                    ->click('@add-page')
                    ->with('@page-tree', function ($browser) use ($new_page_name, $existing_page) {
                        $browser->waitFor('@page-list-'.$existing_page->id, 30)
                            ->pause(500)
                            ->mouseover('@page-list-'.$existing_page->id)
                            ->click('@add-page-inside-'.$existing_page->id)
                            ->whenAvailable('@add-page-form-'.$existing_page->id, function ($browser) use ($new_page_name) {
                                $browser->type('@new-page-name', $new_page_name)
                                    ->click('@create-new-page');
                            });
                    })
                ->within(new Feedback(), function ($browser) use ($new_page_name) {
                    $browser->assertFeedbackContains($new_page_name.' Saved');
                })
                ->pause(500);

            $new_page = Page::all()->last();
            $this->assertTrue($user->can('update', $new_page));
            $browser->waitUntilVue('page.id', $new_page->id, '@page-editor');
        });
    }

    public function test_pages_can_be_searched_for_in_the_page_tree()
    {
        $this->browse(function ($browser) {
            $user = User::factory()->create();
            $page = Page::factory()->create();
            $page2 = Page::factory()->create();

            $parent = Page::factory()->create();
            $parent2 = Page::factory()->create();
            $version = $parent2->versions->first();
            $version->parent_page_id = $parent->id;
            $version->save();

            $page3 = Page::factory()->create();
            $version = $page3->versions->first();
            $version->parent_page_id = $parent2->id;
            $version->save();

            $browser->visit(new Login())
                ->loginAndEdit($user)
                ->mouseover('@page-side-menu-header')
                ->pause(200)
                ->with('@page-tree', function ($browser) use ($page, $page2, $page3) {
                    $browser->waitFor('@page-list-'.$page2->id, 20)
                        ->waitFor('@page-tree-search')
                        ->type('@page-tree-search', $this->getEditingValue($page, 'name'))
                        ->pause(1500)
                        ->assertDontSee($this->getEditingValue($page2, 'name'))
                        ->assertSee($this->getEditingValue($page, 'name'))
                        ->type('@page-tree-search', $this->getEditingValue($page3, 'name'))
                        ->pause(1500)
                        ->assertDontSee($this->getEditingValue($page, 'name'))
                        ->assertDontSee($this->getEditingValue($page2, 'name'))
                        ->assertSee($this->getEditingValue($page3, 'name'));
                });
        });
    }

    public function test_creating_a_new_page_loads_subs_in_other_browsers()
    {
        $this->browse(function ($browser, $editor) {
            $new_page_name = $this->faker->firstName();
            $parent_page = Page::factory()->create();
            $existing_page = Page::factory()->create();
            $version = $existing_page->getDraftVersion();
            $version->parent_page_id = $parent_page->id;
            $version->save();
            $existing_page->refresh();
            $parent_page->refresh();

            $user1 = User::factory()->create();
            $user2 = User::factory()->create();
            $user2->createPermission('update', $parent_page);
            $user2->createPermission('update', $existing_page);

            $editor->visit(new Login())
                   ->loginAndEdit($user1)
                    ->mouseover('@page-side-menu-header')
                    ->pause(500)
                   ->waitFor('@page-list-'.$parent_page->id, 30)
                   ->pause(500)
                   ->click('@page-list-expander-'.$parent_page->id)
                   ->waitFor('@page-list-'.$existing_page->id, 30);

            $browser->visit(new Login())
                ->loginAndEdit($user2)
                ->mouseover('@page-side-menu-header')
                ->pause(200)
                ->waitFor('@page-tree')
                ->with('@page-tree', function ($browser) use ($existing_page, $parent_page) {
                    $browser->waitFor('@page-list-'.$parent_page->id, 30)
                        ->pause(500)
                        ->click('@page-list-expander-'.$parent_page->id)
                        ->pause(500)
                        ->waitFor('@page-list-'.$existing_page->id)
                        ->pause(500);
                })
                ->mouseover('@page-side-menu-header')
                ->click('@add-page')
                ->with('@page-tree', function ($browser) use ($new_page_name, $existing_page) {
                    $browser->mouseover('@page-list-hover-'.$existing_page->id)
                        ->click('@add-page-below-'.$existing_page->id)
                        ->whenAvailable('@add-page-form-'.$existing_page->id, function ($browser) use ($new_page_name) {
                            $browser->type('@new-page-name', $new_page_name)
                                ->click('@create-new-page');
                        });
                })
                ->within(new Feedback(), function ($browser) use ($new_page_name) {
                    $browser->assertFeedbackContains($new_page_name.' Saved');
                })
                ->pause(500);

            $new_page = Page::all()->last();

            $editor->mouseover('@page-side-menu-header')
                ->with('@page-tree', function ($editor) use ($new_page, $new_page_name) {
                    $editor->waitFor('@page-list-'.$new_page->id, 10)
                        ->pause(500)
                        ->assertSee($new_page_name);
                });
        });
    }
}
