<?php

namespace Tests\Feature;

use App\User;
use App\WebsiteCategoryDescription;
use Illuminate\Foundation\Testing\DatabaseTransactions;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Illuminate\Foundation\Testing\WithFaker;
use Illuminate\Support\Facades\Session;
use Illuminate\Support\Str;
use Mcamara\LaravelLocalization\Facades\LaravelLocalization;
use Tests\TestCase;

class WebsiteCategoryTest extends TestCase
{
    // To reset DB to it's status before run test
    use DatabaseTransactions;

    // To create fake sentences to help us test and validation
    use WithFaker;

    private $user;


    protected function setUp() :void
    {
        parent::setUp();

        // to see description
        $this->withoutExceptionHandling();

        // Start session to enables csrf_token()
        Session::start();

        // Authenticate user
        $this->user = factory(User::class)->create(['role'=>'admin']);

        $this->actingAs($this->user);
    }

    /**
     * Method to ensure that the user can access to gallery.
     *
     * @return void
     */
    public function testUserCanAccessGalleryPage() :void
    {

        // Gallery route which visit by user
        $response = $this->get(route('websiteCategories.index'));

        // Should be return status 200
        $response->assertStatus(200);
    }

    /**
     * Method to ensure that the user can read all website galleries.
     *
     * @return void
     */
    public function testUserCanReadAllWebsiteGalleries() :void
    {
        //Given we have gallery in the database
        $gallery = factory(WebsiteCategoryDescription::class)->create();

        //When user visit the gallery
        $response = $this->get(route('websiteCategories.grid'));
        // status should be 200
        $response->assertStatus(200);

        //He should be able to read the gallery
        $response->assertSee($gallery->name);

    }

    /**
     * Method to ensure that the create form route exists.
     *
     * @return void
     */

    public function testUserCanCreateWebsiteGallery()
    {
        //When user visit the new website gallery form route
        $response = $this->get(route('websiteCategories.create'));

        //He should be able to see the fields which enable him to add new category
        $response->assertStatus(200);
        $name = metaFields('websiteCategories', 'name', getCurrentLocale());
        $response->assertSee($name ?? __('websiteCategories.name'));

    }

    /**
     * Method to ensure that the update form route exists.
     *
     * @return void
     */

    public function testUserCanEditWebsiteGallery()
    {
        //Given we have website gallery in the database
        $gallery = factory(WebsiteCategoryDescription::class)->create();

        //When user visit the Website gallery form route
        $response = $this->get(route('websiteCategories.edit', $gallery->website_category_id));

        //He should be able to see the fields which enable him to edit the gallery
        $response->assertStatus(200);
        $name = metaFields('websiteCategories', 'name', getCurrentLocale());
        $response->assertSee($name ?? __('websiteCategories.name'));

        $response->assertSee($gallery['name_'.getCurrentLocale()]);
    }

    /**
     * Method to ensure that the user can add gallery and gallery description.
     *
     * @return void
     */
    public function testUserCanAddWebsiteGallery() :void
    {

        $dataToSave = [
            'image' => '/uploads/images/5eafffbad512e.jpg',

            'images' => [
                '/uploads/images/5eafffbad512e.jpg',
                '/uploads/images/5eafffbad512e.jpg',
                '/uploads/images/5eafffbad512e.jpg',
            ],

            'image_title_'.getCurrentLocale() => [
                $this->faker->sentence,
                $this->faker->sentence,
                $this->faker->sentence
            ],

            'image_url' => [
                $this->faker->url,
                $this->faker->url,
                $this->faker->url
            ],

            'name_'.getCurrentLocale() => $this->faker->sentence,
            'slug_'.getCurrentLocale() => $this->faker->unique()->slug(1),
        ];

        //When user submits post request to create website gallery endpoint
        $response= $this->post(route('websiteCategories.store'), array_merge( $dataToSave, ['_token'=> csrf_token()] ) );

        // The redirect response header status is 302
        $response->assertStatus(302);

        // The response redirect to website galleries
        $response->assertRedirect('admin/websiteCategories');


        //It gets stored in the database
        $this->assertDatabaseHas('website_category_descriptions',
            [
                'name'=> $dataToSave['name_'.getCurrentLocale()],
                'slug'=> $dataToSave['slug_'.getCurrentLocale()],
            ]
        );

        foreach ($dataToSave['images'] as $key => $image) {
            $this->assertDatabaseHas('website_photos', [
                    'image' => $image,
                    'url' => $dataToSave['image_url'][$key],
                ]
            );
        }

        foreach ($dataToSave['image_title_'.getCurrentLocale()] as $title) {
            $this->assertDatabaseHas('website_photo_descriptions', ['title' => $title]);
        }


        // Session success message
        $response->assertSessionHas('message', __('dashboard.saveDone'));

        // Page appears in the Pages panel
        $response = $this->get(route('websiteCategories.grid'));

        //He should be able to read the gallery
        $response->assertSee($dataToSave['name_'.getCurrentLocale()]);

    }

    /**
     * Method to ensure that the user can Edit website gallery.
     *
     * @return void
     */
    public function testUserCanUpdateWebsiteGallery() :void
    {

        //Add a website gallery object
        $gallery = factory(WebsiteCategoryDescription::class)->make(['language_id' => 0]);

        $dataToSave = [
            'image' => '/uploads/images/5eafffbad512e.jpg',

            'images' => [
                '/uploads/images/5eafffbad512e.jpg',
                '/uploads/images/5eafffbad512e.jpg',
                '/uploads/images/5eafffbad512e.jpg',
            ],

            'image_title_'.getCurrentLocale() => [
                $this->faker->sentence,
                $this->faker->sentence,
                $this->faker->sentence
            ],

            'image_url' => [
                $this->faker->url,
                $this->faker->url,
                $this->faker->url
            ],

            'name_'.getCurrentLocale() => $this->faker->sentence,
            'slug_'.getCurrentLocale() => $this->faker->unique()->slug(1),
        ];

        //When user submits post request to edit website gallery endpoint
        $response= $this->put(route('websiteCategories.update', ['websiteCategory' => $gallery->website_category_id]),array_merge( $dataToSave, ['_token'=> csrf_token()] ) );

        // The redirect response header status is 302
        $response->assertStatus(302);

        // The response redirect to website galleries
        $response->assertRedirect('/admin/websiteCategories');;

        //It gets stored in the database
        $this->assertDatabaseHas('website_category_descriptions',
            [
                'name'=> $dataToSave['name_'.getCurrentLocale()],
                'slug'=> $dataToSave['slug_'.getCurrentLocale()],
            ]
        );

        foreach ($dataToSave['images'] as $key => $image) {
            $this->assertDatabaseHas('website_photos', [
                    'image' => $image,
                    'url' => $dataToSave['image_url'][$key],
                ]
            );
        }

        foreach ($dataToSave['image_title_'.getCurrentLocale()] as $title) {
            $this->assertDatabaseHas('website_photo_descriptions', ['title' => $title]);
        }


        // Session success message
        $response->assertSessionHas('message', __('dashboard.saveDone'));

        // Website gallery appears in the website gallery grid
        $response = $this->get(route('websiteCategories.grid'));

        //He should be able to read the website gallery
        $response->assertSee($dataToSave['name_'.getCurrentLocale()]);
    }

    /**
     * Method to ensure that the user can send the gallery to trash.
     *
     * @return void
     */
    public function testWebsiteGalleriesTrash() :void
    {

        //Add a website gallery object
        $gallery = factory(WebsiteCategoryDescription::class)->make();

        //When the user hit's with endpoint to delete the website gallery
        $this->delete(route('websiteCategories.destroy', $gallery->website_category_id), ['_token'=> csrf_token()]);

        //The website gallery should be deleted from the database.
        $this->assertSoftDeleted('website_categories',['id'=> $gallery->website_category_id]);
    }

    /**
     * Method to ensure that the user can delete the website gallery from database.
     *
     * @return void
     */
    public function testWebsiteGalleriesDelete() :void
    {
        //Add a website gallery object
        $gallery =  factory(WebsiteCategoryDescription::class)->make();

        // user sent the website gallery to trash first, as he can not delete it from the first click
        $this->delete(route('websiteCategories.destroy', $gallery->website_category_id), ['_token'=> csrf_token()]);

        //When the user hit's the endpoint to delete the website gallery
        $this->delete(route('websiteCategories.destroy', $gallery->website_category_id), ['_token'=> csrf_token()]);

        //The website gallery should be deleted from the database.

        $this->assertDatabaseMissing('website_categories',['id'=> $gallery->website_category_id]);

        $this->assertDatabaseMissing('website_category_descriptions',['website_category_id'=> $gallery->website_category_id]);
    }

    /**
     * Method to ensure that the user can send multiple website galleries to trash.
     *
     * @return void
     */
    public function testWebsiteGalleriesMultiTrash() :void
    {
        //Add a website gallery object
        $gallery = factory(WebsiteCategoryDescription::class, 3)->make();

        $ids= $gallery->pluck('website_category_id')->toArray();

        //When the user hit's the endpoint to send the website galleries to trash
        $this->delete(route('websiteCategories.destroyAll'), ['_token'=> csrf_token(), 'ids'=> $ids]);
        //The website gallery should be deleted from the database.
        $this->assertSoftDeleted('website_categories',['id'=> $ids]);
    }

    /**
     * Method to ensure that the user can delete multiple website website galleries.
     *
     * @return void
     */
    public function testWebsiteWebsiteGalleriesMultiDelete() :void
    {
        //Add a website gallery object
        $gallery = factory(WebsiteCategoryDescription::class, 3)->make();

        $ids= $gallery->pluck('website_category_id')->toArray();

        //When the user hit's the endpoint to send the website galleries to trash
        $this->delete(route('websiteCategories.destroyAll'), ['_token'=> csrf_token(), 'ids'=> $ids]);

        //When the user hit's the endpoint to delete the website galleries from the db
        $this->delete(route('websiteCategories.destroyAll'), ['_token'=> csrf_token(), 'ids'=> $ids, 'force' => true]);

        //The website gallery should be deleted from the database.
        $this->assertDatabaseMissing('website_categories',['id'=> $ids]);

        $this->assertDatabaseMissing('website_category_descriptions',['website_category_id'=> $ids]);

    }

    /**
     * Method to ensure that the user can restore the website gallery from trash.
     *
     * @return void
     */
    public function testWebsiteGalleriesRestore() :void
    {
        //Add a website gallery object
        $gallery =  factory(WebsiteCategoryDescription::class)->make();

        //the user send the website gallery to trash
        $this->delete(route('websiteCategories.destroy', $gallery->website_category_id), ['_token'=> csrf_token()]);

        $this->assertSoftDeleted('website_categories',['id'=> $gallery->website_category_id]);

        //the user restore the website gallery
        $this->put(route('websiteCategories.restore', $gallery->website_category_id), ['_token'=> csrf_token()]);

        //The gallery should be restored .
        $this->assertDatabaseHas('website_categories',['id'=> $gallery->website_category_id, 'deleted_at'=> null]);
    }

    /**
     * Method to ensure that the user can restore multiple website galleries.
     *
     * @return void
     */
    public function testWebsiteGalleriesMultiRestore() :void
    {
        //Add a website gallery object
        $gallery = factory(WebsiteCategoryDescription::class, 3)->make();

        $ids= $gallery->pluck('website_category_id')->toArray();

        //When the user hit's the endpoint to send the website gallery to trash
        $response = $this->delete(route('websiteCategories.destroyAll'), ['_token' => csrf_token(), 'ids' => $ids]);

        // Test last one to ensure soft deleted process done successfully
        $this->assertSoftDeleted('website_categories', ['id' => $ids]);

        //When the user hit's the endpoint to restore the website galleries from the trash
        $this->put(route('websiteCategories.restoreAll'), ['_token' => csrf_token(), 'ids' => $ids]);

        // Test last one to ensure restore process done successfully
        $this->assertDatabaseHas('website_categories', ['id' => $ids, 'deleted_at' => null]);

    }
}
