<?php

namespace Tests\Tenant;

use Carbon\Carbon;
use Illuminate\Support\Facades\Queue;
use Mtc\MercuryDataModels\GlobalContent;
use Mtc\MercuryDataModels\Jobs\TrackResourceView;
use Mtc\MercuryDataModels\Page;
use Mtc\MercuryDataModels\ResourceView;
use Mtc\MercuryDataModels\Seo404;
use Tests\TenantTestCase;

class PageControllerTest extends TenantTestCase
{
    protected function setUp(): void
    {
        parent::setUp();
        Queue::fake();
    }

    public function testShowPageEndpoint()
    {
        Page::factory()->create(['title' => 'foo baz bar', 'slug' => 'home', 'status' => 'published']);

        $response = $this
            ->getJson(route('pages.show', 'home'));
        $response->assertStatus(200);

        $this->assertEquals('home', $response->json('slug'));
        $this->assertEquals('foo baz bar', $response->json('title'));
    }

    public function testShowGlobalContentEndpoint()
    {
        GlobalContent::factory()->create([
            'name' => 'foo baz bar',
            'slug' => 'foo',
            'content' => [
                'foo' => [
                    'id' => 1,
                    'content' => 'baz'
                ]
            ]
        ]);

        $response = $this
            ->getJson(route('pages.get-global', 'faz'));
        $response->assertStatus(404);

        $response = $this
            ->getJson(route('pages.get-global', 'foo'));
        $response->assertStatus(200);

        $this->assertEquals('baz', $response->json('foo.content'));
    }

    public function testGetSiteEndpoint()
    {
        Page::factory()->create(['title' => 'foo baz bar', 'slug' => 'home']);

        $response = $this
            ->getJson(route('get-site'));
        $response->assertStatus(200);

        $this->assertEquals(tenant('id'), $response->json('id'));
    }
    public function testPagePreviewRestriction()
    {
        $page = Page::factory()->create([
            'title' => 'foo baz bar',
            'slug' => 'home',
            'status' => 'published'
        ]);

        $response = $this
            ->getJson(route('pages.show', 'home'));
        $response->assertStatus(200);
        $response = $this
            ->getJson(route('pages.show', 'home') . '?a=1231231231');
        $response->assertStatus(200);

        $page->update(['status' => 'draft']);
        $response = $this
            ->getJson(route('pages.show', 'home'));
        $response->assertStatus(401);

        $access = base64_encode($page->id . '-' . $page->slug);
        $response = $this
            ->getJson(route('pages.show', 'home') . '?a=' . $access);
        $response->assertStatus(200);
    }

    public function testPagePublishDate()
    {
        $page = Page::factory()->create([
            'title' => 'foo baz bar',
            'slug' => 'home',
            'status' => 'published',
            'published_at' => Carbon::now()->addHour()
        ]);

        $response = $this->getJson(route('pages.show', 'home'));
        $response->assertStatus(404);

        $page->update(['published_at' => Carbon::now()->subHours(2)]);
        $response = $this->getJson(route('pages.show', 'home'));
        $response->assertStatus(200);
    }

    public function test404Tracking()
    {
        $this->assertEquals(0, Seo404::query()->where('path', '/foo-faz')->count());
        $response = $this
            ->withHeaders(['x-path' => '/foo-faz'])
            ->getJson(route('pages.track-404'));

        $response->assertStatus(200);

        $this->assertEquals(1, Seo404::query()->where('path', '/foo-faz')->count());
        $this->assertEquals(1, Seo404::query()->where('path', '/foo-faz')->pluck('hits')->first());

        $response = $this
            ->withHeaders(['x-path' => '/foo-faz'])
            ->getJson(route('pages.track-404'));
        $this->assertEquals(1, Seo404::query()->where('path', '/foo-faz')->count());
        $this->assertEquals(2, Seo404::query()->where('path', '/foo-faz')->pluck('hits')->first());
    }

    public function testPageViewTrackingForPublishedPage()
    {
        $page = Page::factory()->create([
            'title' => 'Test Page',
            'slug' => 'test-page',
            'status' => 'published'
        ]);

        $response = $this->getJson(route('pages.show', 'test-page'));
        $response->assertStatus(200);

        Queue::assertPushed(TrackResourceView::class, function ($job) use ($page) {
            return true;
        });
    }

    public function testPageViewTrackingNotDispatchedForDraftPage()
    {
        $page = Page::factory()->create([
            'title' => 'Draft Page',
            'slug' => 'draft-page',
            'status' => 'draft'
        ]);

        $response = $this->getJson(route('pages.show', 'draft-page'));
        $response->assertStatus(401);

        Queue::assertNotPushed(TrackResourceView::class);
    }

    public function testPageViewTrackingNotDispatchedForPreviewWithAccessKey()
    {
        $page = Page::factory()->create([
            'title' => 'Preview Page',
            'slug' => 'preview-page',
            'status' => 'published'
        ]);

        $accessKey = base64_encode($page->id . '-' . $page->slug);
        $response = $this->getJson(route('pages.show', 'preview-page') . '?a=' . $accessKey);
        $response->assertStatus(200);

        Queue::assertNotPushed(TrackResourceView::class);
    }

    public function testResourceViewRecordCreation()
    {
        $page = Page::factory()->create([
            'title' => 'View Test Page',
            'slug' => 'view-test-page',
            'status' => 'published'
        ]);

        $response = $this->getJson(route('pages.show', 'view-test-page'));
        $response->assertStatus(200);

        Queue::assertPushed(TrackResourceView::class);
    }
}
