<?php

declare(strict_types=1);

namespace KupShop\GraphQLBundle\Tests\ApiAdmin\Content;

use KupShop\ContentBundle\Util\Block;
use KupShop\GraphQLBundle\Tests\GraphQLTestCase;
use KupShop\KupShopBundle\Context\ContextManager;
use KupShop\KupShopBundle\Context\LanguageContext;

class EditableContentTest extends GraphQLTestCase
{
    private ContextManager $contextManager;
    private Block $block;

    protected function setUp(): void
    {
        parent::setUp();

        $this->block = $this->get(Block::class);
        $this->contextManager = $this->get(ContextManager::class);
    }

    /** @dataProvider data_testEditableContentUpdate */
    public function testEditableContentUpdate(int $editableContentId, array $areas, ?bool $overwrite, array $expectedAreas, ?string $expectedError = null): void
    {
        $response = $this->doAdminRequest('
            mutation updateEditableContent($id: Int!, $overwrite: Boolean, $areas: [EditableAreaInput!]!) {
              editableContentUpdate(input: { 
                id: $id
                overwrite: $overwrite
                areas: $areas
              }) {
                result
                editableContent {
                    id
                    areas {
                        name
                        content
                        data
                    }
                }
              }
            }',
            [
                'id' => $editableContentId,
                'overwrite' => $overwrite,
                'areas' => $areas,
            ]);

        $data = json_decode($response->getContent(), true);

        if ($expectedError) {
            $this->assertNotEmpty($data['errors']);
            $this->assertEquals($expectedError, $data['errors'][0]['message']);

            return;
        }

        $result = $data['data']['editableContentUpdate'];

        $this->assertTrue($result['result']);
        $this->assertEquals($expectedAreas, $result['editableContent']['areas']);
    }

    public function data_testEditableContentUpdate(): iterable
    {
        $areaInData = [
            'name' => 'Test',
            'content' => '<div class="w-text">Testik WPJ</div>',
            'data' => '[{"type":"text","id":"96d17f81-0c10-494d-9dc6-50cf1e835da3","settings":{"html":"Testik WPJ"}}]',
        ];

        yield 'Areas should stay in same state 1' => [1, [], null, [$areaInData]];
        yield 'Areas should stay in same state 2' => [1, [], false, [$areaInData]];

        yield 'Areas should be emptied' => [1, [], true, []];

        yield 'Add new area' => [1, [
            [
                'id' => null,
                'name' => 'Test add',
                'data' => '[{"type":"text","id":"16d17f81-0c10-494d-9dc6-50cf1e835da3","settings":{"html":"Test add"}}]',
            ],
        ], null, [
            $areaInData,
            [
                'name' => 'Test add',
                'content' => '<div class="w-text">Test add</div>',
                'data' => '[{"type":"text","id":"16d17f81-0c10-494d-9dc6-50cf1e835da3","settings":{"html":"Test add"}}]',
            ],
        ]];

        yield 'Update area' => [1, [
            [
                'id' => 2,
                'name' => 'Test update',
                'data' => '[{"type":"text","id":"96d17f81-0c10-494d-9dc6-50cf1e835da3","settings":{"html":"Test update"}}]',
            ],
        ], null, [
            [
                'name' => 'Test update',
                'content' => '<div class="w-text">Test update</div>',
                'data' => '[{"type":"text","id":"96d17f81-0c10-494d-9dc6-50cf1e835da3","settings":{"html":"Test update"}}]',
            ],
        ]];
        yield 'Update area partially' => [1, [
            [
                'id' => 2,
                'name' => 'Test update partially',
            ],
        ], null, [
            array_replace($areaInData, ['name' => 'Test update partially']),
        ]];

        yield 'Invalid JSON error' => [1, [['id' => 2, 'data' => 'invalid json']], null, [], 'Failed to parse JSON in EditableArea.data!'];
        yield 'Invalid EditableArea.id error' => [1, [['id' => 99, 'data' => '[]']], null, [], 'Unable to update EditableArea! Specified EditableArea.id does not belong to updated EditableContent!'];
        yield 'EditableArea.id is mandatory error' => [1, [['data' => '[]']], null, [], 'EditableArea.id field is mandatory!'];
    }

    /** @dataProvider data_testEditableContentTranslate */
    public function testEditableContentTranslate(int $editableContentId, string $language, array $areas, array $expectedAreas, ?string $expectedError = null): void
    {
        $response = $this->doAdminRequest('
            mutation translateEditableContent($id: Int!, $language: String!, $areas: [EditableAreaInput!]!) {
              editableContentTranslate(input: { 
                id: $id
                language: $language
                areas: $areas
              }) {
                result
              }
            }',
            [
                'id' => $editableContentId,
                'language' => $language,
                'areas' => $areas,
            ]);

        $data = json_decode($response->getContent(), true);

        if ($expectedError) {
            $this->assertNotEmpty($data['errors']);
            $this->assertEquals($expectedError, $data['errors'][0]['message']);

            return;
        }

        $this->assertTrue($data['data']['editableContentTranslate']['result']);

        $blocks = $this->contextManager->activateContexts([LanguageContext::class => $language], fn () => $this->block->getBlocks($editableContentId, true));
        $translatedAreas = array_map(fn ($x) => ['name' => $x['name'], 'content' => $x['content'], 'data' => $x['json_content']], $blocks);

        $this->assertEquals($expectedAreas, $translatedAreas);
    }

    public function data_testEditableContentTranslate(): iterable
    {
        yield 'EditableContent successfully translated' => [1, 'sk', [
            [
                'id' => 2,
                'name' => 'Test SK',
                'data' => '[{"type":"text","id":"96d17f81-0c10-494d-9dc6-50cf1e835da3","settings":{"html":"Testik WPJ SK"}}]',
            ],
        ], [
            [
                'name' => 'Test SK',
                'content' => '<div class="w-text">Testik WPJ SK</div>',
                'data' => '[{"type":"text","id":"96d17f81-0c10-494d-9dc6-50cf1e835da3","settings":{"html":"Testik WPJ SK"}}]',
            ],
        ]];

        yield 'Invalid JSON error' => [1, 'sk', [['id' => 2, 'data' => 'invalid json']], [], 'Failed to parse JSON in EditableArea.data!'];
        yield 'Invalid EditableArea.id error' => [1, 'sk', [['id' => 99, 'data' => '[]']], [], 'Unable to update EditableArea! Specified EditableArea.id does not belong to updated EditableContent!'];
        yield 'EditableArea.id is mandatory error' => [1, 'sk', [['data' => '[]']], [], 'EditableArea.id field is mandatory!'];
    }

    protected function getDataSet()
    {
        return $this->getJsonDataSetFromFile();
    }
}
