<?php

namespace Tests\Feature;

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

use Illuminate\Support\Arr;
use Laravel\Sanctum\Sanctum;

use Tiptap\Editor;

use App\Models\Page;
use App\Models\TextBlock;
use App\Models\User;
use App\Models\Tag;
use App\Models\ContentElement;
use App\Models\Role;
use App\Models\Version;

class ContentElementTest extends TestCase
{
    use WithFaker;

    public function test_a_content_element_can_be_published_directly()
    {
        $page = Page::factory()->create();
        $content_element1 = $this->createContentElement(TextBlock::factory(), $page);
        $content_element2 = $this->createContentElement(TextBlock::factory(), $page);
        $content_element3 = $this->createContentElement(TextBlock::factory(), $page);
        $content_element3->publish_at = now()->subHours(1);
        $content_element3->save();

        $this->json('POST', route('content-elements.publish', ['id' => $content_element1->id]))
            ->assertStatus(401);

        $this->signIn(User::factory()->create());

        $this->json('POST', route('content-elements.publish', ['id' => $content_element1->id]))
             ->assertStatus(403);

        $this->signInAdmin();

        $this->json('POST', route('content-elements.publish', ['id' => $content_element1->id]), ['pivot.contentable_type' => $page->type])
             ->assertStatus(404);

        $this->withoutExceptionHandling();
        $this->json('POST', route('content-elements.publish', ['id' => $content_element1->id]), ['pivot' => ['contentable_id' => $page->id, 'contentable_type' => 'page']])
             ->assertSuccessful()
             ->assertJsonFragment([
                 'success' => 'Text Block Published'
             ]);

        $content_element1->refresh();
        $content_element2->refresh();
        $content_element3->refresh();

        $this->assertNotNull($content_element1->getPageVersion($page)->published_at);
        $this->assertNull($content_element2->getPageVersion($page)->published_at);
        $this->assertNull($content_element3->getPageVersion($page)->published_at);
    }

    public function test_a_content_element_loads_its_latest_version_from_its_uuid()
    {
        $content_element = $this->createContentElement(TextBlock::factory());
        $uuid = $content_element->uuid;
        $page = $content_element->pages()->first();

        $page->publish();

        $content_element->refresh();

        $this->assertNotNull($content_element->getPageVersion($page)->published_at);

        $this->signInAdmin();

        $input = $content_element->toArray();

        $this->assertEquals(1, $page->contentElements()->count());

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

        // Create a contentable factory
        $input['pivot'] = $this->getContentableArray($new_page);

        $paragraph = $this->faker->paragraph;

        $input['content']['body'] = $paragraph;

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

        $page->refresh();
        $this->assertEquals(2, $page->contentElements()->count());

        $new_content_element = $page->contentElements()->get()->last();

        $this->assertEquals($uuid, $new_content_element->uuid);

        $this->assertNotEquals($content_element->id, $new_content_element->id);

        $this->withoutExceptionHandling();

        $this->json('POST', route('content-elements.load', ['id' => $content_element->id]), ['pivot' => ['contentable_id' => $page->id, 'contentable_type' => $page->type]])
             ->assertSuccessful()
             ->assertJsonFragment([
                 'uuid' => $uuid,
                 'id' => $new_content_element->id,
                 'contentable_id' => $page->id,
                 'body' => $paragraph,
             ]);
    }

    public function test_a_content_element_can_save_tags()
    {
        $tag = Tag::factory()->create();

        $input = [];
        $input['id'] = '0.0';
        $input['type'] = 'text-block';
        $input['content'] = TextBlock::factory()->raw();
        $input['content']['id'] = 0;

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

        /*
        $input['pivot'] = [
            'contentable_id' => $page->id,
            'contentable_type' => get_class($page),
            'sort_order' => 1,
            'unlisted' => false,
            'expandable' => false,
            'guest' => false,
        ];
         */

        $input['pivot'] = $this->getContentableArray($page);

        $input['tags'] = [
            $tag->toArray(),
        ];

        $this->signInAdmin();

        $this->withoutExceptionHandling();

        $this->json('POST', route('content-elements.store'), $input)
             ->assertSuccessful()
             ->assertJsonFragment([
                'success' => 'Text Block Saved',
                'contentable_id' => $page->id,
                'sort_order' => 1,
                'unlisted' => 0,
                'expandable' => null,
                'guest' => 0,
                'no_margin' => 0,
                'randomize' => 0,
                'filter' => 0,
                'hide_print' => 0,
             ]);

        $page->refresh();
        $content_element = ContentElement::all()->last();

        $this->assertEquals(1, $page->contentElements()->count());
        $this->assertEquals($content_element->id, $page->contentElements()->first()->id);

        $this->assertNotNull($content_element->tags);
        $this->assertEquals(1, $content_element->tags->count());
        $this->assertTrue($content_element->tags->contains('id', $tag->id));

        // make sure that json encoding includes the tags
        $data = ContentElement::find($content_element->id)->load((new ContentElement())->loadWith())->toArray();

        $this->assertNotNull(Arr::get($data, 'tags'));
        $this->assertTrue(collect(Arr::get($data, 'tags'))->contains('id', $tag->id));
    }

    public function test_a_content_element_with_view_permissions_should_only_show_for_those_with_access()
    {
        $page = Page::factory()->create();
        $content_element = $this->createContentElement(TextBlock::factory(), $page);
        $body = $content_element->content->body;
        $page->publish();

        $user1 = User::factory()->create();
        $user2 = User::factory()->create();

        $this->withoutExceptionHandling();
        $this->get($page->full_slug)
             ->assertSuccessful()
             ->assertSee($body);

        $content_element->createPermission('view', $user1);
        $page->refresh();
        cache()->tags([cache_name($page)])->flush();

        $this->get($page->full_slug)
             ->assertSuccessful()
             ->assertDontSee($body);

        $this->signIn($user1);

        $this->get($page->full_slug)
             ->assertSuccessful()
             ->assertSee($body);

        $this->signIn($user2);

        $this->get($page->full_slug)
             ->assertSuccessful()
             ->assertDontSee($body);

        $content_element->createPermission('update', $user2);

        $this->get($page->full_slug)
             ->assertSuccessful()
             ->assertSee($body);
    }

    public function test_saving_an_instance_only_doesnt_change_the_sort_order_expandable_or_unlisted_on_other_pages()
    {
        $page = Page::factory()->create();
        $content_element = $this->createContentElement(TextBlock::factory(), $page);

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

        $new_page->contentElements()->attach($content_element, [
            'version_id' => $page->getDraftVersion()->id,
            'sort_order' => 2,
            'unlisted' => true,
            'expandable' => 'expand',
            'guest' => false,
            'filter' => false,
            'hide_print' => false,
            'randomize' => false,
        ]);

        $page->refresh();
        $new_page->refresh();

        $this->assertEquals(2, $content_element->contentables()->count());

        $page_contentable = $content_element->contentables()->where('contentable_id', $page->id)->where('contentable_type', get_class($page))->first();
        $new_page_contentable = $content_element->contentables()->where('contentable_id', $new_page->id)->where('contentable_type', get_class($new_page))->first();

        $this->assertEquals(0, $page_contentable->unlisted);
        $this->assertNull($page_contentable->expandable);

        $sort_order = $page_contentable->sort_order;

        $input = $content_element->toArray();
        $input['pivot'] = $this->getContentableArray($new_page, [
            'sort_order' => 3,
            'unlisted' => true,
            'expandable' => 'expand',
        ]);

        /*
        $input['pivot'] = [
            'contentable_id' => $new_page->id,
            'contentable_type' => get_class($new_page),
            'sort_order' => 3,
            'unlisted' => true,
            'expandable' => true,
            'guest' => false,
        ];
         */

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

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

        $page_contentable->refresh();
        $new_page_contentable->refresh();

        $this->assertEquals($sort_order, $page_contentable->sort_order);
        $this->assertEquals(3, $new_page_contentable->sort_order);
        $this->assertEquals(0, $page_contentable->unlisted);
        $this->assertEquals(1, $new_page_contentable->unlisted);
        $this->assertNull($page_contentable->expandable);
        $this->assertEquals('expand', $new_page_contentable->expandable);
    }

    public function test_a_content_element_can_be_moved_to_another_page()
    {
        $page = Page::factory()->create();
        $content_element = $this->createContentElement(TextBlock::factory(), $page);
        $body = $content_element->content->body;
        $page->publish();

        $new_page = Page::factory()->create();
        $new_page->publish();

        $this->signInAdmin();

        $input = $content_element->toArray();
        $input['pivot'] = $this->getContentableArray($new_page, [
            //'contentable_id' => $new_page->id,
            //'contentable_type' => get_class($new_page),
            'old_contentable_id' => $page->id,
            'old_contentable_type' => get_class($page),
        ]);

        $this->assertNotNull(Arr::get($input, 'content.body'));

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

        $new_content_element = ContentElement::all()->last();
        $new_page->refresh();

        $this->assertEquals($body, $new_content_element->content->body);
        $this->assertNotEquals($content_element->id, $new_content_element->id);

        $this->assertEquals(1, $new_page->contentElements()->count());

        $this->assertEquals(2, $new_content_element->contentables()->count());

        $this->assertTrue($new_content_element->contentables()->get()->contains(function ($contentable) use ($new_page) {
            return $new_page->id === $contentable->contentable_id && get_class($new_page) === $contentable->contentable_type;
        }));

        $this->assertTrue($new_content_element->contentables()->get()->contains(function ($contentable) use ($page) {
            return $page->id === $contentable->contentable_id && get_class($page) === $contentable->contentable_type && $contentable->deleted_at;
        }));

        $input['pivot']['sort_order'] = 2;

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

        $contentable = $new_content_element->contentables()->where('contentable_id', $new_page->id)->where('contentable_type', get_class($new_page))->first();
        $this->assertEquals(2, $contentable->sort_order);

        auth()->logout();

        $this->get($page->full_slug)
            ->assertSee($body);

        $this->get($new_page->full_slug)
            ->assertDontSee($body);

        $page->publish();
        $new_page->publish();

        $page->publish();
        $new_page->publish();

        $this->get($page->full_slug)
            ->assertDontSee($body);

        $this->get($new_page->full_slug)
            ->assertSee($body);
    }

    public function test_a_content_element_can_load_its_fields_for_editing_in_tiptap()
    {
        $page = Page::factory()->create();
        $content_element = $this->createContentElement(TextBlock::factory(), $page);
        $version = $page->versions()->first();
        $this->assertInstanceOf(Version::class, $version);

        $this->assertTrue($page->id > 1);

        $content = $content_element->content;
        $body = '<p>'.$this->faker->sentence.' <a href="'.$page->id.'" >'.$version->name.'</a></p>';
        $content->body = $body;
        $content->save();

        $content->refresh();

        $this->json('POST', route('content-elements.load-field'), ['id' => $content_element->id, 'field' => 'body'])
            ->assertStatus(401);

        Sanctum::actingAs(
            User::factory()->create(),
            ['*']
        );

        $this->json('POST', route('content-elements.load-field'), [])
             ->assertStatus(422)
             ->assertJsonValidationErrors([
                'id',
                'field',
             ]);

        $this->json('POST', route('content-elements.load-field'), ['id' => $content_element->id, 'field' => 'body'])
             ->assertStatus(403);

        Sanctum::actingAs(
            User::find(1),
            ['*']
        );

        $content = (new Editor())->setContent($body)->getDocument();

        $this->json('POST', route('content-elements.load-field'), ['id' => $content_element->id, 'field' => 'body'])
             ->assertSuccessful()
             ->assertJsonFragment([
                'content' => $content,
             ]);
    }

    public function test_a_new_content_element_loading_into_tiptap_should_always_return_at_least_a_p_tag()
    {
        $page = Page::factory()->create();
        $content_element = $this->createContentElement(TextBlock::factory(), $page);
        $content = $content_element->content;
        $content->body = '';
        $content->save();

        Sanctum::actingAs(
            User::find(1),
            ['*']
        );

        $json = (new Editor())->setContent('<p></p>')->getDocument();

        $this->json('POST', route('content-elements.load-field'), ['id' => $content_element->id, 'field' => 'body'])
             ->assertSuccessful()
             ->assertJsonFragment([
                'content' => $json,
             ]);
    }

    public function test_a_content_element_can_be_removed_from_a_page_by_a_user_with_update_access_to_a_page()
    {
        $page = Page::factory()->create();
        $content_element = $this->createContentElement(TextBlock::factory(), $page);

        $user = User::factory()->create();
        $role = Role::factory()->create();

        $user->addRole($role);
        $page->createPermission('update', $role);

        $user->refresh();
        $page->refresh();
        $content_element->refresh();

        $this->assertTrue($user->can('update', $page));
        $this->assertTrue($user->can('update', $content_element));

        $this->assertTrue($user->can('delete', $content_element));

        $this->signIn($user);
        $this->enableEditing();

        $input = [
            'pivot' => [
                'contentable_id' => $page->id,
                'contentable_type' => get_class($page),
            ]
        ];

        $this->json('POST', route('content-elements.remove', ['id' => $content_element->id]), $input)
             ->assertSuccessful()
             ->assertJsonFragment([
                'success' => 'Text Block Version Removed',
             ]);
    }

    public function test_a_content_element_can_load_its_previous_version()
    {
        $page = Page::factory()->create();
        $content_element1 = $this->createContentElement(TextBlock::factory(), $page, $page->publishedVersion);
        $page->publish();
        $page->refresh();

        $content_element1 = $page->contentElements()->get()->firstWhere('id', $content_element1->id);

        $this->assertNotNull($content_element1->pivot);
        $sort_order = $content_element1->pivot->sort_order;
        $this->assertNotNull($sort_order);

        $this->assertNotNull($content_element1->contentables()->first()->version->published_at);

        $content_element2 = ContentElement::factory()->for(TextBlock::factory(), 'content')->create([
            'uuid' => $content_element1->uuid,
        ]);

        $content_element2->pages()->detach();
        $content_element2->pages()->attach($page, [
            'sort_order' => $this->faker->randomNumber(1),
            'unlisted' => false,
            'guest' => false,
            'expandable' => null,
            'no_margin' => false,
            'randomize' => false,
            'version_id' => $page->draft_version_id
        ]);

        $this->assertInstanceOf(ContentElement::class, $content_element2->getPreviousVersion($page));
        $this->assertEquals($content_element1->id, $content_element2->getPreviousVersion($page)->id);
        $this->assertEquals($content_element1->uuid, $content_element2->uuid);

        $this->json('POST', route('content-elements.previous-version', ['id' => $content_element2->id]))
            ->assertStatus(401);

        $user = User::factory()->create();
        $this->signIn($user);
        $this->enableEditing();

        $input = ['contentable_id' => $page->id, 'contentable_type' => $page->type];

        $this->json('POST', route('content-elements.previous-version', ['id' => $content_element2->id]), $input)
            ->assertStatus(403);

        $role = Role::factory()->create();

        $user->addRole($role);
        $page->createPermission('update', $role);

        $page->refresh();
        $user->refresh();
        $content_element2->refresh();

        $this->assertTrue($user->can('update', $page));
        $this->assertTrue($user->can('update', $content_element2));

        $this->json('POST', route('content-elements.previous-version', ['id' => $content_element2->id]))
             ->assertStatus(422)
             ->assertJsonValidationErrors(['contentable_id', 'contentable_type']);

        $this->json('POST', route('content-elements.previous-version', ['id' => $content_element2->id]), $input)
             ->assertSuccessful()
             ->assertJsonFragment([
                'body' => $content_element1->content->body,
                'sort_order' => $sort_order,
             ]);
    }

    public function test_trying_to_get_a_previous_version_of_a_first_content_element_returns_null()
    {
        $page = Page::factory()->create();
        $content_element = $this->createContentElement(TextBlock::factory(), $page);

        $this->signInAdmin();

        $input = ['contentable_id' => $page->id, 'contentable_type' => $page->type];

        $this->json('POST', route('content-elements.previous-version', ['id' => $content_element->id]), $input)
             ->assertSuccessful();
    }

    public function test_a_content_element_can_be_visible_only_to_guests()
    {
        $page = Page::factory()->create();
        $content_element = $this->createContentElement(TextBlock::factory(), $page);
        $page->publish();

        $this->get($page->full_slug)
            ->assertSee($content_element->content->body);

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

        $input = $content_element->toArray();
        $input['pivot'] = $this->getContentableArray($page, [
            'guest' => true,
        ]);

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

        $page->refresh();
        $this->assertEquals(1, $page->all_content_elements->count());
        $content_element = $page->all_content_elements->first();
        $this->assertEquals(1, $content_element->contentables->last()->guest);

        $page->publish();

        $this->post('/logout');

        $this->assertFalse(auth()->check());

        $this->get($page->full_slug)
            ->assertSee($content_element->content->body);

        $this->signIn(User::factory()->create());

        $this->get($page->full_slug)
            ->assertDontSee($content_element->content->body);

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

        $this->assertTrue($page->content->contains('id', $content_element->id));
    }

    public function test_a_content_element_can_be_hidden_until_a_filter_tag_is_selected()
    {
        $this->signInAdmin();
        $this->enableEditing();
        $page = Page::factory()->create();
        $content_element = $this->createContentElement(TextBlock::factory(), $page);

        $input = $content_element->toArray();
        $input['pivot'] = $this->getContentableArray($page, [
            'filter' => true,
        ]);

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

        $page->publish();

        $content_element->refresh();

        $this->assertEquals(1, $content_element->contentables->last()->filter);
    }

    public function test_contentable_settings_are_not_updated_on_other_pages_when_saving_a_content_element_that_is_on_two_pages()
    {
        $this->signInAdmin();
        $this->enableEditing();

        $page = Page::factory()->create();
        $content_element = $this->createContentElement(TextBlock::factory(), $page);

        $pivot = $content_element->pages()->where('pages.id', $page->id)->first()->pivot;
        $base_settings = collect([
            'sort_order' => 1,
            'unlisted' => 0,
            'expandable' => null,
            'guest' => 0,
            'no_margin' => 0,
            'filter' => 0,
            'hide_print' => 0,
            'randomize' => 0,
        ]);
        $this->assertEquals(collect($pivot->toArray())->only($base_settings->keys()), $base_settings);

        $page2 = Page::factory()->create();
        $input = $content_element->toArray();
        $input['instance'] = true;
        $input['pivot'] = $this->getContentableArray($page2);

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

        $pivot2 = $content_element->pages()->where('pages.id', $page2->id)->first()->pivot;
        $this->assertEquals(collect($pivot2->toArray())->only($base_settings->keys()), $base_settings);

        $input = $content_element->toArray();
        $input['pivot'] = $this->getContentableArray($page2);
        $input['pivot']['sort_order'] = 2;
        $input['pivot']['unlisted'] = true;
        $input['pivot']['expandable'] = 'expand';
        $input['pivot']['guest'] = true;
        $input['pivot']['no_margin'] = true;
        $input['pivot']['filter'] = true;
        $input['pivot']['hide_print'] = true;
        $input['pivot']['randomize'] = true;

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

        $page->refresh();
        $pivot = $content_element->pages()->where('pages.id', $page->id)->first()->pivot;
        $this->assertEquals(collect($pivot->toArray())->only($base_settings->keys()), $base_settings);

        $page2->refresh();
        $this->assertEquals(1, $page2->contentElements()->count());
        $pivot = $content_element->pages()->where('pages.id', $page2->id)->first()->pivot;

        $this->assertEquals(2, $pivot->sort_order);
        $this->assertEquals(1, $pivot->unlisted);
        $this->assertEquals('expand', $pivot->expandable);
        $this->assertEquals(1, $pivot->guest);
        $this->assertEquals(1, $pivot->no_margin);
        $this->assertEquals(1, $pivot->filter);
        $this->assertEquals(1, $pivot->hide_print);
        $this->assertEquals(1, $pivot->randomize);
    }


    public function test_when_creating_a_new_version_of_a_content_element_on_two_pages_attributes_stick()
    {
        $this->signInAdmin();
        $this->enableEditing();

        $page1 = Page::factory()->create();
        $page2 = Page::factory()->create();

        $content_element = $this->createContentElement(TextBlock::factory(), $page1);
        $pivot1 = $content_element->pages()->where('pages.id', $page1->id)->first()->pivot;

        $this->assertEquals(1, $pivot1->sort_order);

        $input = $content_element->toArray();
        $input['instance'] = true;
        $input['pivot'] = $this->getContentableArray($page2);
        $input['pivot']['sort_order'] = 2;

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

        $pivot2 = $content_element->pages()->where('pages.id', $page2->id)->first()->pivot;
        $this->assertEquals(2, $pivot2->sort_order);

        $page1->publish();
        $page2->publish();

        $input = $content_element->toArray();
        $input['pivot'] = $this->getContentableArray($page2);
        $input['pivot']['sort_order'] = 3;

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


        $new_content_element = ContentElement::all()->last();
        // make sure that we've made a new version
        $this->assertNotEquals($content_element->id, $new_content_element->id);

        $this->assertNotNull($content_element->content->body);
        $this->assertEquals($content_element->content->body, $new_content_element->content->body);

        $new_pivot1 = $new_content_element->pages()->where('pages.id', $page1->id)->first()->pivot;
        $new_pivot2 = $new_content_element->pages()->where('pages.id', $page2->id)->first()->pivot;

        $this->assertEquals(3, $new_pivot2->sort_order);
        $this->assertEquals(1, $new_pivot1->sort_order);
    }

    public function test_removing_a_content_element_thats_on_two_pages(): void
    {
        $this->signInAdmin();
        $this->enableEditing();

        $page1 = Page::factory()->create();
        $page2 = Page::factory()->create();

        $content_element = $this->createContentElement(TextBlock::factory(), $page1);
        $pivot1 = $content_element->pages()->where('pages.id', $page1->id)->first()->pivot;

        $input = $content_element->toArray();
        $input['instance'] = true;
        $input['pivot'] = $this->getContentableArray($page2);

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

        $pivot2 = $content_element->pages()->where('pages.id', $page2->id)->first()->pivot;

        $page1->publish();
        $page2->publish();

        $this->assertTrue($page1->all_content_elements->contains('id', $content_element->id));
        $this->assertTrue($page2->all_content_elements->contains('id', $content_element->id));

        $page1->getDraftVersion();
        $page2->getDraftVersion();
        $page1->refresh();
        $page2->refresh();

        $remove_input = [
            'pivot' => [
                'contentable_id' => $page1->id,
                'contentable_type' => $page1->type,
            ],
            'remove_all' => true,
        ];

        $this->json('POST', route('content-elements.remove', ['id' => $content_element->id]), $remove_input)
             ->assertSuccessful();

        $uuid = $content_element->uuid;
        $all_content_elements = ContentElement::where('uuid', $uuid)->get();

        $this->assertEquals(2, $all_content_elements->count());

        $content_element2 = $all_content_elements->last();
        $this->assertEquals(1, ContentElement::findPagesByUuid($uuid)->count());

        $page1->refresh();
        $page2->refresh();
        $content_element->refresh();
        $this->assertFalse($page1->all_content_elements->contains('id', $content_element->id));
        $this->assertFalse($page1->all_content_elements->contains('id', $content_element2->id));
        $this->assertTrue($page2->all_content_elements->contains('id', $content_element2->id));

        $page1->publish();

        $remove_input = [
            'pivot' => [
                'contentable_id' => $page2->id,
                'contentable_type' => $page2->type,
            ],
            'remove_all' => true,
        ];

        $this->json('POST', route('content-elements.remove', ['id' => $content_element->id]), $remove_input)
             ->assertSuccessful();

        $all_content_elements = ContentElement::where('uuid', $uuid)->get();

        $content_element3 = $all_content_elements->last();
        $this->assertEquals(0, ContentElement::findPagesByUuid($uuid)->count());

        $page1->refresh();
        $page2->refresh();
        $content_element->refresh();
        cache()->tags([cache_name($page1)])->flush();
        cache()->tags([cache_name($page2)])->flush();

        $this->assertFalse($page2->all_content_elements->contains('id', $content_element3->id));
        $this->assertFalse($page1->all_content_elements->contains('id', $content_element3->id));
    }
}
