<?php

namespace Tests\Feature;

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

use Illuminate\Support\Arr;
use Illuminate\Support\Str;
use Illuminate\Support\Facades\Storage;
use Illuminate\Http\UploadedFile;

use App\Models\TimetableContent;
use App\Models\User;
use App\Models\Tag;
use App\Models\FileUpload;
use App\Models\Photo;
use App\Models\Page;
use App\Models\TextBlock;

class TimetableContentTest extends TestCase
{
    public function test_timetable_content_can_be_saved()
    {
        $tag = Tag::factory()->create();
        $input = TimetableContent::factory()->raw();
        $input['tag'] = $tag;

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

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

        $this->json('POST', route('timetable-contents.store'), [])
            ->assertStatus(403);

        $this->signInAdmin();

        $this->json('POST', route('timetable-contents.store'), [])
             ->assertStatus(422)
             ->assertJsonValidationErrors([
                'tag',
             ]);

        $this->json('POST', route('timetable-contents.store'), $input)
             ->assertSuccessful()
             ->assertJsonFragment([
                'success' => $tag->name.' Saved',
             ]);

        $timetable_content = TimetableContent::all()->last();

        $this->assertNotNull($timetable_content->tag);
        $this->assertInstanceOf(Tag::class, $timetable_content->tag);
        $this->assertEquals($tag->id, $timetable_content->tag->id);

        $this->assertNotNull($timetable_content->header);
        $this->assertNotNull($timetable_content->body);
        $this->assertNotNull($timetable_content->style);
        $this->assertNotNull($timetable_content->link);
        $this->assertNotNull($timetable_content->link_text);
        $this->assertNotNull($timetable_content->inline);

        $this->assertEquals(Arr::get($input, 'header'), $timetable_content->header);
        $this->assertEquals(Arr::get($input, 'body'), $timetable_content->body);
        $this->assertEquals(Arr::get($input, 'style'), $timetable_content->style);
        $this->assertEquals(Arr::get($input, 'link'), $timetable_content->link);
        $this->assertEquals(Arr::get($input, 'link_text'), $timetable_content->link_text);
        $this->assertEquals(Arr::get($input, 'inline'), $timetable_content->inline);

        $tag2 = Tag::factory()->create();
        $input = TimetableContent::factory()->raw();
        $input['tag'] = $tag2;

        Storage::fake();
        $file_name = Str::random().'.jpg';
        $file = UploadedFile::fake()->image($file_name);
        $file_upload = (new FileUpload())->saveFile($file, 'photos', true);

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

        $input['photos'] = [$photo_input];

        auth()->logout();

        $this->json('POST', route('timetable-contents.update', ['id' => $timetable_content->id ]), [])
            ->assertStatus(401);

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

        $this->json('POST', route('timetable-contents.update', ['id' => $timetable_content->id ]), [])
            ->assertStatus(403);

        $this->signInAdmin();

        $this->json('POST', route('timetable-contents.update', ['id' => $timetable_content->id ]), [])
             ->assertStatus(422)
             ->assertJsonValidationErrors([
                'tag',
             ]);

        $this->json('POST', route('timetable-contents.update', ['id' => $timetable_content->id ]), $input)
             ->assertSuccessful()
             ->assertJsonFragment([
                'success' => $tag2->name.' Saved',
             ]);

        $timetable_content->refresh();

        $this->assertNotNull($timetable_content->tag);
        $this->assertInstanceOf(Tag::class, $timetable_content->tag);
        $this->assertEquals($tag2->id, $timetable_content->tag->id);

        $this->assertNotNull($timetable_content->header);
        $this->assertNotNull($timetable_content->body);
        $this->assertNotNull($timetable_content->style);
        $this->assertNotNull($timetable_content->link);
        $this->assertNotNull($timetable_content->link_text);
        $this->assertNotNull($timetable_content->inline);

        $this->assertEquals(Arr::get($input, 'header'), $timetable_content->header);
        $this->assertEquals(Arr::get($input, 'body'), $timetable_content->body);
        $this->assertEquals(Arr::get($input, 'style'), $timetable_content->style);
        $this->assertEquals(Arr::get($input, 'link'), $timetable_content->link);
        $this->assertEquals(Arr::get($input, 'link_text'), $timetable_content->link_text);
        $this->assertEquals(Arr::get($input, 'inline'), $timetable_content->inline);

        $this->assertNotNull($timetable_content->photos);
        $this->assertEquals(1, $timetable_content->photos->count());
        $photo = $timetable_content->photos->first();

        $this->assertInstanceOf(Photo::class, $photo);
        $this->assertEquals(Arr::get($photo_input, 'name'), $photo->name);
        $this->assertEquals(Arr::get($photo_input, 'description'), $photo->description);
        $this->assertEquals(Arr::get($photo_input, 'alt'), $photo->alt);
        $this->assertEquals($photo->fileUpload->id, $file_upload->id);
    }

    public function test_timetable_content_can_be_loaded()
    {
        $timetable_content = TimetableContent::factory()->create();

        $this->withoutExceptionHandling();
        $this->json('POST', route('timetable-contents.load'))
             ->assertSuccessful()
             ->assertJsonFragment([
                'header' => $timetable_content->header,
             ]);
    }

    public function test_the_timetable_contents_manage_page_can_be_loaded()
    {
        $this->get(route('timetable-contents.manage'))
            ->assertRedirect('/login');

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

        $this->get(route('timetable-contents.manage'))
            ->assertRedirect('/');

        $this->signInAdmin();

        $this->get(route('timetable-contents.manage'))
             ->assertSuccessful()
             ->assertViewIs('timetable-contents.index');
    }

    public function test_a_timetable_content_has_a_url_attribute()
    {
        $this->signInAdmin();

        $page = Page::factory()->create();
        $content_element = $this->createContentElement(TextBlock::factory(), $page);
        $page->publish();
        $timetable_content = TimetableContent::factory()->create();
        $timetable_content->link = $page->id;
        $timetable_content->save();

        $timetable_content->refresh();

        $this->assertNotNull($page->full_slug);

        $this->assertNotNull($timetable_content->url);
        $this->assertEquals('/'.$page->full_slug, $timetable_content->url);

        $timetable_content->link = $page->id.'#c-'.$content_element->uuid;
        $timetable_content->save();
        $timetable_content->refresh();

        $this->assertEquals('/'.$page->full_slug.'#'.$content_element->anchor, $timetable_content->url);
    }
}
