<?php

namespace Tests\Feature;

use Illuminate\Foundation\Testing\RefreshDatabase;
use Illuminate\Foundation\Testing\WithFaker;
use Tests\TestCase;
use Illuminate\Support\Facades\Storage;
use Illuminate\Http\UploadedFile;
use Illuminate\Support\Str;
use Illuminate\Support\Arr;

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

use App\Models\EmbedVideo;
use App\Models\Photo;
use App\Models\FileUpload;
use App\Models\User;
use App\Models\Page;
use App\Models\ContentElement;
use App\Models\VideoText;

use Illuminate\Support\Facades\Queue;
use App\Jobs\CreateVideoSizes;

class EmbedVideoTest extends TestCase
{
    use WithFaker;
    use ContentElementsTestTrait;
    use ContentElementsSearchTestTrait;

    protected function getClassname()
    {
        return 'embed-video';
    }

    public function test_saving_a_embed_video()
    {
        $input = $this->createContentElement(EmbedVideo::factory())->toArray();

        Storage::fake();
        $file_name = Str::lower(Str::random().'.mp4');
        $file = UploadedFile::fake()->create($file_name, 15360, 'video/mp4');
        $file_upload = (new FileUpload())->saveFile($file, 'videos', true);

        $width = $this->faker->numberBetween(100, 1000);
        $height = $this->faker->numberBetween(100, 1000);
        $photo_file_name = Str::lower(Str::random().'.jpg');
        $photo_file = UploadedFile::fake()->image($photo_file_name, $width, $height);
        $photo_file_upload = (new FileUpload())->saveFile($photo_file, 'photos', true);

        $photo_input = Photo::factory()->raw([
            'file_upload_id' => $photo_file_upload->id,
        ]);

        $input['id'] = 0;
        $input['type'] = 'embed-video';
        $input['content'] = EmbedVideo::factory()->raw();
        $input['content']['photos'] = [$photo_input];
        $input['content']['file_upload_id'] = $file_upload->id;

        $video_text_input = collect(VideoText::factory()->raw(['id' => 0]))->only(['id', 'header', 'body', 'link', 'link_text','start_time', 'length', 'offsetX', 'offsetY', 'header_size'])->toArray();
        $input['content']['video_texts'] = [
            $video_text_input,
        ];

        $page = Page::factory()->create();
        $input['pivot'] = $this->getContentableArray($page);

        $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->enableEditing();

        $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' => 'embed-video', 'pivot' => ['contentable_id' => $page->id, 'contentable_type' => 'page']])
             ->assertStatus(422)
             ->assertJsonValidationErrors([
                'pivot.sort_order',
                'pivot.unlisted',
                //'pivot.expandable',
                'pivot.guest',
                'pivot.no_margin',
                'pivot.randomize',
             ]);


        Queue::fake();
        $this->withoutExceptionHandling();
        $this->json('POST', route('content-elements.store'), $input)
             ->assertSuccessful()
             ->assertJsonFragment([
                'success' => 'Embed Video Saved',
             ]);

        $embed_video = EmbedVideo::all()->last();

        $this->assertNotNull($embed_video->layout);
        $this->assertNotNull($embed_video->header);
        $this->assertNotNull($embed_video->body);
        $this->assertNotNull($embed_video->fill);
        $this->assertNotNull($embed_video->show_text);
        $this->assertNotNull($embed_video->text_style);
        $this->assertNotNull($embed_video->number);

        $this->assertEquals(Arr::get($input, 'content.layout'), $embed_video->layout);
        $this->assertEquals(Arr::get($input, 'content.header'), $embed_video->header);
        $this->assertEquals(Arr::get($input, 'content.body'), $embed_video->body);
        $this->assertEquals(Arr::get($input, 'content.fill'), $embed_video->fill);
        $this->assertEquals(Arr::get($input, 'content.show_text'), $embed_video->show_text);
        $this->assertEquals(Arr::get($input, 'content.text_style'), $embed_video->text_style);
        $this->assertEquals(Arr::get($input, 'content.number'), $embed_video->number);

        $this->assertNotNull($embed_video->fileUpload);
        $this->assertInstanceOf(FileUpload::class, $embed_video->fileUpload);
        $this->assertEquals($file_upload->id, $embed_video->fileUpload->id);

        $this->assertNotNull($embed_video->videoTexts);
        $this->assertEquals(1, $embed_video->videoTexts->count());
        $video_text = $embed_video->videoTexts->first();
        $this->assertEquals(Arr::get($video_text_input, 'header'), $video_text->header);
        $this->assertEquals(Arr::get($video_text_input, 'body'), $video_text->body);
        $this->assertEquals(Arr::get($video_text_input, 'link'), $video_text->link);
        $this->assertEquals(Arr::get($video_text_input, 'link_text'), $video_text->link_text);
        $this->assertEquals(Arr::get($video_text_input, 'start_time'), $video_text->start_time);
        $this->assertEquals(Arr::get($video_text_input, 'length'), $video_text->length);
        $this->assertEquals(Arr::get($video_text_input, 'offsetX'), $video_text->offsetX);
        $this->assertEquals(Arr::get($video_text_input, 'offsetY'), $video_text->offsetY);
        $this->assertEquals(Arr::get($video_text_input, 'header_size'), $video_text->header_size);

        $this->assertNotNull($embed_video->url);
        Storage::disk('public')->assertExists($embed_video->url);

        Queue::assertPushed(function (CreateVideoSizes $event) use ($embed_video) {
            return $event->embed_video->id === $embed_video->id;
        });
    }

    public function test_updating_a_embed_video()
    {
        $content_element = $this->createContentElement(EmbedVideo::factory([
            'file_upload_id' => FileUpload::factory()->mp4(),
        ]));
        $embed_video = $content_element->content;
        $page = $content_element->pages->first();

        $video_text = VideoText::factory()->create([
            'embed_video_id' => $embed_video->id,
        ]);

        $embed_video->refresh();

        $this->assertEquals(1, $embed_video->videoTexts->count());

        $this->assertInstanceOf(ContentElement::class, $content_element);

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

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

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

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

        $this->signInAdmin();

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

        $this->json('POST', route('content-elements.update', ['id' => $content_element->id]), ['type' => 'embed-video', 'pivot' => ['contentable_id' => $page->id, 'contentable_type' => 'page']])
             ->assertStatus(422)
             ->assertJsonValidationErrors([
                'pivot.sort_order',
                'pivot.unlisted',
                //'pivot.expandable',
                'pivot.guest',
                'pivot.no_margin',
                'pivot.randomize',
             ]);

        $input = $content_element->toArray();

        $new_file_upload = FileUpload::factory()->mp4()->create();

        $embed_video_input = EmbedVideo::factory()->raw([
            'file_upload_id' => $new_file_upload->id,
        ]);

        $input['content'] = array_merge($input['content'], $embed_video_input);

        $new_photo = Photo::factory([
                'file_upload_id' => FileUpload::factory()->jpg(),
            ])
            ->for(EmbedVideo::factory(), 'content')
            ->create([
                'content_id' => $embed_video->id
            ]);

        $this->assertInstanceOf(FileUpload::class, $new_photo->fileUpload);

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

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

        $content_element->refresh();
        $embed_video->refresh();
        $this->assertEquals(Arr::get($input, 'content.header'), $embed_video->header);
        $this->assertEquals(Arr::get($input, 'content.body'), $embed_video->body);
        $this->assertEquals(Arr::get($input, 'content.file_upload_id'), $embed_video->file_upload_id);
        $this->assertEquals(Arr::get($input, 'content.file_upload_id'), $embed_video->fileUpload->id);
        $this->assertEquals($new_file_upload->id, $embed_video->fileUpload->id);

        $page->publish();

        $embed_video_input2 = EmbedVideo::factory()->raw();

        $input['content'] = array_merge($input['content'], $embed_video_input2);

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


        $new_content_element = ContentElement::all()->last();
        $this->assertEquals($content_element->id + 1, $new_content_element->id);
        $new_embed_video = $new_content_element->content;

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

        $this->assertEquals(1, $embed_video->videoTexts->count());
        $this->assertEquals(1, $new_embed_video->videoTexts->count());
    }
}
