<?php

namespace Tests\Browser;

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

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

use App\Utilities\PageLink;
use App\Models\ContentElement;
use App\Models\TextBlock;
use App\Models\PhotoBlock;
use App\Models\Page;
use App\Models\User;

class LinkMenuTest extends DuskTestCase
{
    use WithFaker;

    public function test_a_link_can_be_crud()
    {
        $this->browse(function ($browser) {
            $page = Page::factory()->create();
            $content_element_link = $this->createContentElement(TextBlock::factory(), $page);
            $user = User::factory()->create();
            $user->createPermission('update', $page);

            $browser->visit(new Login())
                ->loginAndEditPage(null, $user)
                ->with(new AddContentElement(), function ($browser) {
                    $browser->create('photo-block');
                });

            $content_element = ContentElement::all()->last();
            $link_text = $this->faker->sentence(3);

            $browser->with('@content-element-'.$content_element->id, function ($browser) use ($link_text, $content_element) {
                $browser->waitFor('@toggle-text')
                        ->click('@toggle-text')
                        ->waitFor('@body-editor-'.$content_element->id)
                        ->within(new Editor('body', $content_element->id), function ($browser) use ($link_text) {
                            $browser->typeInEditor($link_text)
                                ->keys('@editor', ['{command}', 'a'])
                                ->click('@link-button');
                        });
            })

            ->with('@modal', function ($browser) use ($page) {
                $browser->with('@link-menu', function ($browser) use ($page) {
                    $browser->waitFor('@page-list-'.$page->id, 20)
                            ->pause(500)
                            ->click('@page-list-'.$page->id);
                });
            })

            ->assertVue('modelValue', '<p><a class="" href="'.$page->id.'">'.$link_text.'</a></p>', '@body-editor-'.$content_element->id)

            ->pause(1000)
            ->within(new Feedback(), function ($browser) {
                $browser->assertFeedbackContains('Photo Block Saved');
            })

            ->refresh()
            ->waitFor('@body-editor-'.$content_element->id)
            ->pause(200)
            ->assertVue('modelValue', '<p><a class="" href="'.$page->id.'">'.$link_text.'</a></p>', '@body-editor-'.$content_element->id);

            $body_value = $this->getEditingValue($content_element->content, 'body');

            $this->assertTrue(Str::contains($body_value, $page->id));

            $full_slug = $this->getEditingValue($page, 'full_slug');

            $browser->pause(1000)
                ->with('@content-element-'.$content_element->id, function ($browser) use ($content_element) {
                    $browser->waitFor('@body-editor-'.$content_element->id)
                        ->within(new Editor('body', $content_element->id), function ($browser) {
                            $browser->keys('@editor', ['{command}', 'a'])
                                ->click('@link-button');
                        });
                })

            ->with('@modal', function ($browser) use ($full_slug) {
                $browser->with('@link-menu', function ($browser) use ($full_slug) {
                    $browser->waitFor('@url')
                            ->assertValue('@url', $full_slug)
                            ->waitFor('@checkbox-is-button')
                            ->click('@checkbox-is-button')
                            ->click('@checkbox-new-window')
                            ->click('@checkbox-float-right')
                            ->click('@apply-link');
                });
            })
            ->pause(1500)
            ->within(new Feedback(), function ($browser) {
                $browser->assertFeedbackContains('Photo Block Saved');
            })
            ->pause(1500)
            ->assertVue('modelValue', '<p><a target="_blank" class="button float-right" rel="noopener noreferrer nofollow" href="'.$page->id.'">'.$link_text.'</a></p>', '@body-editor-'.$content_element->id)

            ->with('@content-element-'.$content_element->id, function ($browser) use ($content_element) {
                $browser->waitFor('@body-editor-'.$content_element->id)
                    ->within(new Editor('body', $content_element->id), function ($browser) {
                        $browser->keys('@editor', ['{command}', 'a'])
                            ->click('@link-button');
                    });
            })

            ->with('@modal', function ($browser) use ($full_slug) {
                $browser->with('@link-menu', function ($browser) use ($full_slug) {
                    $browser->waitFor('@url')
                            ->assertValue('@url', $full_slug)
                            ->waitFor('@clear-url')
                            ->click('@clear-url')
                            ->assertValue('@url', '')
                            ->click('@remove-link');
                });
            })
            ->pause(1000)
            ->within(new Feedback(), function ($browser) {
                $browser->assertFeedbackContains('Photo Block Saved');
            })
            ->assertVue('modelValue', '<p>'.$link_text.'</p>', '@body-editor-'.$content_element->id);
        });
    }

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


            $browser->visit(new Login())
                ->loginAndEditPage($link_page, $user)
                ->with(new AddContentElement(), function ($browser) {
                    $browser->create('photo-block');
                })
                ->pause(1500);

            $content_element_link = ContentElement::all()->last();
            $text = $this->faker->paragraph();
            $header = Str::random(10);

            $browser->with(new AddContentElement(), function ($browser) {
                $browser->create('photo-block');
            })
                ->pause(1500);

            $content_element_modal = ContentElement::all()->last();
            $text2 = $this->faker->paragraph();
            $header2 = $this->faker->sentence(3);

            $browser->with('@content-element-'.$content_element_link->id, function ($browser) use ($text, $content_element_link, $header) {
                $browser->waitFor('@toggle-text')
                        ->click('@toggle-text')
                        ->waitFor('@body-editor-'.$content_element_link->id)
                        ->type('@header', $header)
                        ->within(new Editor('body', $content_element_link->id), function ($browser) use ($text) {
                            $browser->typeInEditor($text);
                        })
                        ->click('@toggle-expandable');
            })
            ->pause(1500)

            ->with('@content-element-'.$content_element_modal->id, function ($browser) use ($text2, $content_element_modal, $header2) {
                $browser->waitFor('@toggle-text')
                        ->click('@toggle-text')
                        ->waitFor('@body-editor-'.$content_element_modal->id)
                        ->type('@header', $header2)
                        ->within(new Editor('body', $content_element_modal->id), function ($browser) use ($text2) {
                            $browser->typeInEditor($text2);
                        })
                        ->click('@toggle-modal');
            })

            ->pause(1500) // let the page save
            ->click('@publish-page')
            ->acceptDialog()
            ->within(new Feedback(), function ($browser) {
                $browser->assertFeedbackContains('Page Published');
            });

            // link to the expandable content element
            $browser->visit($this->getEditingValue($page, 'full_slug'))
                ->waitFor('@add-content-element-last', 10)
                ->with(new AddContentElement(), function ($browser) {
                    $browser->create('photo-block');
                });

            $content_element = ContentElement::all()->last();
            $link_text = $this->faker->sentence(3);

            $browser->with('@content-element-'.$content_element->id, function ($browser) use ($link_text, $content_element) {
                $browser->waitFor('@toggle-text')
                        ->click('@toggle-text')
                        ->waitFor('@body-editor-'.$content_element->id)
                        ->within(new Editor('body', $content_element->id), function ($browser) use ($link_text) {
                            $browser->typeInEditor($link_text)
                                ->keys('@editor', ['{command}', 'a'])
                                ->click('@link-button');
                        });
            })

            ->with('@modal', function ($browser) use ($link_page, $content_element_link) {
                $browser->with('@link-menu', function ($browser) use ($link_page, $content_element_link) {
                    $browser->waitFor('@page-list-'.$link_page->id, 20)
                            ->pause(500)
                            ->click('@page-list-'.$link_page->id.'-toggle-content-elements')
                            ->pause(250)
                            ->waitFor('@content-element-'.$content_element_link->id)
                            ->click('@content-element-'.$content_element_link->id);
                });
            })

            ->assertVue('modelValue', '<p><a class="" href="'.$link_page->id.'#c-'.$content_element_link->uuid.'">'.$link_text.'</a></p>', '@body-editor-'.$content_element->id)

            ->with(new AddContentElement(), function ($browser) {
                $browser->create('photo-block');
            });

            $content_element2 = ContentElement::all()->last();
            $link_text2 = $this->faker->sentence(3);

            $browser->with('@content-element-'.$content_element2->id, function ($browser) use ($link_text2, $content_element2) {
                $browser->waitFor('@toggle-text')
                        ->click('@toggle-text')
                        ->waitFor('@body-editor-'.$content_element2->id)
                        ->within(new Editor('body', $content_element2->id), function ($browser) use ($link_text2) {
                            $browser->typeInEditor($link_text2)
                                ->keys('@editor', ['{command}', 'a'])
                                ->click('@link-button');
                        });
            })

                ->with('@modal', function ($browser) use ($link_page, $content_element_modal) {
                    $browser->with('@link-menu', function ($browser) use ($link_page, $content_element_modal) {
                        $browser->waitFor('@page-list-'.$link_page->id, 20)
                                ->pause(500)
                                ->click('@page-list-'.$link_page->id.'-toggle-content-elements')
                                ->pause(250)
                                ->waitFor('@content-element-'.$content_element_modal->id)
                                ->click('@content-element-'.$content_element_modal->id);
                    });
                })

                ->assertVue('modelValue', '<p><a class="" href="'.$link_page->id.'#c-'.$content_element_modal->uuid.'">'.$link_text2.'</a></p>', '@body-editor-'.$content_element2->id)

                ->pause(1500) // let the page save
                ->click('@publish-page')
                ->acceptDialog()
                ->within(new Feedback(), function ($browser) {
                    $browser->assertFeedbackContains('Page Published');
                })
                ->clickAndWaitForReload('@editing-button')
                ->pause(500)
                ->assertVue('editing', false, '@editing-button')
                ->assertMissing('@page-editor')
                ->refresh();

            $link_page->refresh();

            $browser->with('@content-element-'.$content_element->id, function ($browser) use ($link_text, $link_page, $header) {
                $browser->assertSourceHas('href="/'.$link_page->full_slug.'#'.PageLink::convertAnchorText($header).'"')
                    ->clickLink($link_text);
            })
                ->waitForLocation('/'.$link_page->full_slug)
                ->assertFragmentIs(PageLink::convertAnchorText($header))
                ->assertSee($text)
                ->pause(500)
                ->back()
                ->refresh()
                ->waitFor('@editing-button')
                ->pause(500)
                ->assertVue('editing', false, '@editing-button')
                ->assertMissing('@page-editor')
                ->waitFor('@content-element-'.$content_element2->id)
                ->assertVue('editing', false, '@editing-button')
                ->assertMissing('@page-editor')
                ->with('@content-element-'.$content_element2->id, function ($browser) use ($link_text2, $link_page, $header2) {
                    $browser->assertSourceHas('href="/'.$link_page->full_slug.'#'.PageLink::convertAnchorText($header2).'"')
                        ->clickLink($link_text2);
                })
                ->waitForLocation('/'.$link_page->full_slug)
                ->assertFragmentIs(PageLink::convertAnchorText($header2))
                ->pause(500)
                ->assertVue('editing', false, '@editing-button')
                ->assertMissing('@page-editor')
                ->waitFor('@modal')
                ->with('@modal', function ($browser) use ($text2) {
                    $browser->assertSee($text2);
                });

            $browser->visit('/search')
                ->waitFor('@global-search')
                ->with('@global-search', function ($browser) use ($header, $link_page) {
                    $browser->type('@search-input', $header)
                            ->waitFor('@search-result-page-'.$link_page->id, 20)
                            ->assertSourceHas('href="/'.$link_page->full_slug.'#'.PageLink::convertAnchorText($header).'"')
                            ->clickLink($header);
                });
        });
    }
}
