<?php

namespace Tests\Feature;

use Illuminate\Foundation\Testing\RefreshDatabase;
use Mtc\ContentManager\Models\VersionContent;
use Mtc\MercuryDataModels\Content;
use Mtc\MercuryDataModels\Page;
use Mtc\MercuryDataModels\PageVersion;
use Tests\TestCase;

class PageVersionTest extends TestCase
{
    use RefreshDatabase;

    protected $tenancy = true;

    public function testStructureMatches()
    {
        $page = Page::query()->find(27);
        $version = PageVersion::query()->find(3);

        $response = $this->asTenant(tenant())->getJson(route('pages.show', $page->slug));

        $response->assertStatus(200);
        $page_content = $response->json();
        $response = $this->asTenant(tenant())
            ->getJson(route('pages.show', [
                'page' => $page->slug,
                'v' => $version->uuid,
                'a' => base64_encode($page?->id . '-' . $page?->slug),
            ]));

        $this->assertTrue(
            $this->arrayStructuresMatch($page_content, $response->json()),
            'Version content structure does not match page structure.'
        );
    }

    public function testVersionContentIsLoaded()
    {
        $page = Page::query()->find(27);
        $version = PageVersion::query()->find(3);
        $response = $this->asTenant(tenant())
            ->getJson(route('pages.show', [
                'page' => $page->slug,
                'v' => $version->uuid,
                'a' => base64_encode($page?->id . '-' . $page?->slug),
        ]));

        $response->assertStatus(200);
        $this->assertEquals('"Say hello to your next Dacia"', $response->json('data.0.data.0.value'));
    }

    public function testVersionRequiresAccessParam()
    {
        $page = Page::query()->find(27);
        $version = PageVersion::query()->find(3);
        $response = $this->asTenant(tenant())
            ->getJson(route('pages.show', [
                'page' => $page->slug,
                'v' => $version->uuid,
                'a' => base64_encode($page?->id . '-' . $page?->slug),
            ]));

        $response->assertStatus(200);

        $response = $this->asTenant(tenant())
            ->getJson(route('pages.show', [
                'page' => $page->slug,
                'v' => $version->uuid,
            ]));

        $response->assertStatus(401);
    }

    public function setUp(): void
    {
        parent::setUp();
        $this->seedData();
    }

    private function arrayStructuresMatch(array $array1, array $array2): bool
    {
        // Check if both arrays have the same keys
        $keys1 = array_keys($array1);
        $keys2 = array_keys($array2);
        if (!empty(array_diff($keys1, $keys2)) || !empty(array_diff($keys2, $keys1))) {
            return false;
        }

        // Recursively check nested structures
        foreach ($array1 as $key => $value) {
            if (is_array($value) && is_array($array2[$key])) {
                if (!$this->arrayStructuresMatch($value, $array2[$key])) {
                    return false;
                }
            } elseif (is_array($value) !== is_array($array2[$key])) {
                return false;
            }
        }

        return true;
    }


    private function seedData()
    {
        Page::unguard();
        Content::unguard();
        PageVersion::unguard();
        VersionContent::unguard();

        $data = json_decode(file_get_contents(dirname(__DIR__) . '/Data/version_content.json'), true);

        (new Page($data['page']))->save();
        (new PageVersion($data['version']))->save();

        foreach ($data['page_content'] as $content) {
            (new Content($content))->save();
        }

        foreach ($data['version_content'] as $content) {
            (new VersionContent($content))->save();
        }
    }
}
