<?php

namespace Tests\Feature;

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

use Tests\Feature\ContentElementsTestTrait;
use Tests\Feature\TagExcludeTestTrait;
use Tests\Feature\ContentElementsSearchTestTrait;

use App\Models\PublicationList;
use App\Models\PublicationLayout;
use App\Models\User;
use App\Models\Page;
use App\Models\Tag;

class PublicationListTest extends TestCase
{
    use ContentElementsTestTrait;
    use WithFaker;
    use TagExcludeTestTrait;
    use ContentElementsSearchTestTrait;

    protected function getClassname()
    {
        return 'publication-list';
    }

    public function test_a_publication_list_can_be_created()
    {
        $tag1 = Tag::factory()->create();
        $tag2 = Tag::factory()->create();

        $input = $this->createContentElement(PublicationList::factory([
            'hide_paginator' => true,
            'type' => 'blog',
        ]))->load('content')->toArray();

        $input['id'] = 0;
        $input['content_id'] = 0;
        $input['content_type'] = null;
        $input['content.id'] = 0;
        $input['content']['tags'] = [
            $tag1->toArray(),
            $tag2->toArray(),
        ];

        $layout = 'preview';
        $number_of_items = 4;

        $input['content']['publication_layouts'] = [
            PublicationLayout::factory([
                'id' => 0,
                'publication_list_id' => null,
                'layout' => $layout,
                'number_of_items' => $number_of_items,
            ])->raw(),
        ];

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

        $this->json('POST', route('content-elements.store'), [])
            ->assertStatus(401);

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

        $this->json('POST', route('content-elements.store'), [])
             ->assertStatus(422)
             ->assertJsonValidationErrors([
                 'pivot.contentable_id',
                 'pivot.contentable_type',
             ]);

        $this->json('POST', route('content-elements.store'), ['pivot' => ['contentable_id' => $page->id, 'contentable_type' => 'page']])
             ->assertStatus(403);

        $this->signInAdmin();

        $this->json('POST', route('content-elements.store'), ['pivot' => ['contentable_id' => $page->id, 'contentable_type' => 'page']])
             ->assertStatus(422)
             ->assertJsonValidationErrors([
                 'type',
             ]);

        $this->json('POST', route('content-elements.store'), [
                'type' => 'publication-list',
                'pivot' => [
                    'contentable_id' => $page->id,
                    'contentable_type' => 'page'
                ],
                'content' => [
                    'publication_layouts' => ['id' => 0]
                ],
            ])
             ->assertStatus(422)
             ->assertJsonValidationErrors([
                'pivot.sort_order',
                'pivot.unlisted',
                //'pivot.expandable',
                'pivot.guest',
                'pivot.no_margin',
                'pivot.randomize',
                'content.publication_layouts.id.name',
                'content.publication_layouts.id.number_of_items',
             ]);

        $this->json('POST', route('content-elements.store'), $input)
             ->assertSuccessful()
             ->assertJsonFragment([
                'success' => 'Publication List Saved',
             ]);

        $publication_list = PublicationList::all()->last();
        $this->assertEquals(Arr::get($input, 'content.header'), $publication_list->header);
        $this->assertEquals(Arr::get($input, 'content.layout'), $publication_list->layout);
        $this->assertEquals(Arr::get($input, 'content.hide_paginator'), $publication_list->hide_paginator);
        $this->assertEquals(Arr::get($input, 'content.type'), $publication_list->type);
        $this->assertTrue($publication_list->tags->contains('id', $tag1->id));
        $this->assertTrue($publication_list->tags->contains('id', $tag2->id));

        $publication_layout = PublicationLayout::all()->last();
        $this->assertEquals($publication_list->id, $publication_layout->publication_list_id);
        $this->assertEquals($publication_list->id, $publication_layout->publicationList->id);
        $this->assertTrue($publication_list->publicationLayouts()->count() === 1);
        $this->assertEquals($publication_list->publicationLayouts()->first()->name, $layout);
    }

    public function test_a_publication_layout_can_be_removed_from_a_publication_list()
    {
        $content_element = $this->createContentElement(PublicationList::factory()->has(PublicationLayout::factory()));
        $publication_list = $content_element->content;
        $publication_layout = $publication_list->publicationLayouts()->first();
        $this->assertNotNull($publication_layout);
        $this->assertInstanceOf(PublicationLayout::class, $publication_layout);

        $layout = $this->faker->firstName;
        $publication_layout2 = PublicationLayout::factory()->create([
            'publication_list_id' => $publication_list->id,
            'name' => $layout,
        ]);

        $this->assertEquals(2, $publication_list->publicationLayouts()->count());

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

        $page = $content_element->pages->first();
        $input = $content_element->toArray();
        $input['pivot'] = $this->getContentableArray($page);
        $input['content']['publication_layouts'] = [$publication_layout->toArray()];

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

        $content_element->refresh();
        $publication_list->refresh();
        $this->assertEquals(1, $publication_list->publicationLayouts()->count());
        $this->assertFalse($publication_list->publicationLayouts()->get()->contains('layout', $layout));
    }

    public function test_saving_a_new_version_of_a_publication_list_maintains_the_old_publication_layouts()
    {
        $page = Page::factory()->create();
        $content_element = $this->createContentElement(PublicationList::factory()->has(PublicationLayout::factory()), $page);
        $publication_list = $content_element->content;

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

        $page->publish();

        $publication_list->refresh();
        $this->assertEquals(1, $publication_list->publicationLayouts()->count());

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

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

        $new_publication_list = PublicationList::all()->last();
        $publication_list->refresh();
        $this->assertNotEquals($publication_list->id, $new_publication_list->id);

        $this->assertEquals(1, $new_publication_list->publicationLayouts()->count());
        $this->assertEquals(1, $publication_list->publicationLayouts()->count());

        $this->assertEquals($publication_list->publicationLayouts()->first()->name, $new_publication_list->publicationLayouts()->first()->name);
    }
}
