<?php

namespace Tests\Feature;

use App\User;
use App\Setting;
use Tests\TestCase;
use Illuminate\Support\Facades\Session;
use Illuminate\Foundation\Testing\WithFaker;
use Illuminate\Foundation\Testing\DatabaseTransactions;

class SettingTest 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 settings.
     *
     * @return void
     */
    public function testUserCanAccessSettingPage() :void
    {
        // setting gallery route which visit by user
        $response = $this->get(route('settings.index'));

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

    /**
     * Method to ensure that the user can read all settings.
     *
     * @return void
     */
    public function testUserCanReadAllSettings() :void
    {
        $dataToSave = [];
        //Given we have settings in the database

        foreach ($this->settingArray() as $setting) {
            $dataToSave[$setting['key']] = $setting['value'];
        }

        //When user visit the settings category
        $response = $this->get(route('settings.index'));
        // status should be 200
        $response->assertStatus(200);

        //He should be able to read the settings category
        foreach ($dataToSave as $key => $value) {
            $response->assertSee(__('settings.'.$key));
        }

    }

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

    public function testUserCanCreateSetting() :void
    {
        $dataToSave = [];
        //Given we have settings in the database

        foreach ($this->settingArray() as $setting) {
            $dataToSave[$setting['key']] = $setting['value'];
        }

        //When user visit the settings category
        $response = $this->get(route('settings.index'));
        // status should be 200
        $response->assertStatus(200);

        //He should be able to read the settings category
        foreach ($dataToSave as $key => $value) {
            $response->assertSee(__('settings.'.$key));
        }

    }

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

    public function testUserCanEditSetting() :void
    {

        $dataToSave = [];
        //Given we have settings in the database

        foreach ($this->settingArray() as $setting) {
            $dataToSave[$setting['key']] = $setting['value'];
        }

        //When user visit the settings category
        $response = $this->get(route('settings.index'));
        // status should be 200
        $response->assertStatus(200);

        //He should be able to read the settings category
        foreach ($dataToSave as $key => $value) {
            $response->assertSee(__('settings.'.$key));
        }
    }

    /**
     * Method to ensure that the user can add settings.
     *
     * @return void
     */
    public function testUserCanAddSetting() :void
    {
        $dataToSave = [];
        //Given we have settings in the database

        foreach ($this->settingArray() as $setting) {
            $dataToSave[$setting['key']] = $setting['value'];
        }

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

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

        // The response redirect to videos
        $response->assertRedirect('admin/settings');


        //He should be able to read the settings category
        foreach ($dataToSave as $key => $value) {
            $this->assertDatabaseHas('settings', [
                'key' => $key,
                'value' => $value,
            ]);
        }

    }

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

        $dataToSave = ['update' => 'true'];
        //Given we have settings in the database

        foreach ($this->settingArray() as $key => $setting) {
            factory(Setting::class)->create([
                'key' => $setting['key'],
                'value' => $setting['value'],
            ]);
            $dataToSave[$setting['key']] = $setting['value'];
        }

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

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

        // The response redirect to videos
        $response->assertRedirect('admin/settings');


        //He should be able to read the settings category
        foreach ($dataToSave as $key => $value) {
            if ($key == 'update') continue;
            $this->assertDatabaseHas('settings', [
                'key' => $key,
                'value' => $value,
            ]);
        }
    }

    /**
     * Return settings array values
     * @return array
     */
    public function settingArray():array
    {
        return [
            ['key' => 'website_name', 'value' => $this->faker->sentence],
            ['key' => 'keywords', 'value' => $this->faker->sentence],
            ['key' => 'meta_description', 'value' => $this->faker->sentence],
            ['key' => 'site_email', 'value' => $this->faker->safeEmail],
            ['key' => 'site_address', 'value' => $this->faker->address],
            ['key' => 'site_phone', 'value' => $this->faker->e164PhoneNumber],
            ['key' => 'mail_driver', 'value' => 'smtp'],
            ['key' => 'mail_host', 'value' =>'smtp.mailtrap.io'],
            ['key' => 'mail_port', 'value' => 2525],
            ['key' => 'mail_username', 'value' => $this->faker->userName],
            ['key' => 'mail_password', 'value' => $this->faker->password],
            ['key' => 'mail_from_address', 'value' => $this->faker->safeEmail],
            ['key' => 'mail_encryption', 'value' => 'tls'],
            ['key' => 'mail_from_name', 'value' => $this->faker->sentence],
            ['key' => 'website_logo', 'value' => 'logo.png'],
        ];
    }
}
