<?php

namespace SwaggerBake\Test\TestCase\Lib\Attribute;

use Cake\Routing\RouteBuilder;
use Cake\Routing\Router;
use Cake\TestSuite\TestCase;
use SwaggerBake\Lib\Configuration;
use SwaggerBake\Lib\Model\ModelScanner;
use SwaggerBake\Lib\Route\RouteScanner;
use SwaggerBake\Lib\Swagger;

class OpenApiResponseTest extends TestCase
{
    /**
     * @var string[]
     */
    public array $fixtures = [
        'plugin.SwaggerBake.Employees',
    ];

    private Swagger $swagger;

    /**
     * @throws \ReflectionException
     */
    public function setUp(): void
    {
        parent::setUp(); // TODO: Change the autogenerated stub
        Router::createRouteBuilder('/')->scope('/', function (RouteBuilder $builder) {
            $builder->setExtensions(['json']);
            $builder->resources('Employees', [
                'map' => [
                    'customResponseRef' => [
                        'action' => 'customResponseRef',
                        'method' => 'GET',
                        'path' => 'custom-response-ref'
                    ],
                    'customResponseSchema' => [
                        'action' => 'customResponseSchema',
                        'method' => 'GET',
                        'path' => 'custom-response-schema'
                    ],
                    'customResponseSchemaPublic' => [
                        'action' => 'customResponseSchemaPublic',
                        'method' => 'GET',
                        'path' => 'custom-response-schema-public'
                    ],
                    'customResponseSchemaPublicArray' => [
                        'action' => 'customResponseSchemaPublicArray',
                        'method' => 'GET',
                        'path' => 'custom-response-schema-public-array'
                    ],
                    'schemaItems' => [
                        'action' => 'schemaItems',
                        'method' => 'GET',
                        'path' => 'schema-items'
                    ],
                ]
            ]);
        });

        $config = new Configuration([
            'prefix' => '/',
            'yml' => '/config/swagger-with-existing.yml',
            'json' => '/webroot/swagger.json',
            'webPath' => '/swagger.json',
            'hotReload' => false,
            'exceptionSchema' => 'Exception',
            'requestAccepts' => ['application/x-www-form-urlencoded'],
            'responseContentTypes' => ['application/json'],
            'namespaces' => [
                'controllers' => ['\SwaggerBakeTest\App\\'],
                'entities' => ['\SwaggerBakeTest\App\\'],
                'tables' => ['\SwaggerBakeTest\App\\'],
            ]
        ], SWAGGER_BAKE_TEST_APP);

        $cakeRoute = new RouteScanner(new Router(), $config);
        $this->swagger = (new Swagger(new ModelScanner($cakeRoute, $config), $config))->build();
    }

    public function test_openapi_response_ref(): void
    {
        $arr = json_decode($this->swagger->build()->toString(), true);

        $operation = $arr['paths']['/employees/custom-response-ref']['get'];

        $schema = $operation['responses']['200']['content']['application/json']['schema'];
        $this->assertEquals('#/components/schemas/Pet', $schema['allOf'][0]['$ref']);

        $this->assertArrayHasKey('404', $operation['responses']);
        $this->assertEquals('new statusCode', $operation['responses']['404']['description']);

        $this->assertArrayHasKey('5XX', $operation['responses']);
        $this->assertEquals('status code range', $operation['responses']['5XX']['description']);
    }

    public function test_openapi_response_schema(): void
    {
        $arr = json_decode($this->swagger->build()->toString(), true);
        $operation = $arr['paths']['/employees/custom-response-schema']['get'];
        $schema = $operation['responses'][200]['content']['application/json']['schema'];
        $this->assertEquals('Custom Title', $schema['title']);
        $this->assertArrayHasKey('age', $schema['properties']);
        $this->assertArrayHasKey('name', $schema['properties']);
    }

    public function test_openapi_response_schema_public(): void
    {
        $arr = json_decode($this->swagger->build()->toString(), true);
        $this->assertArrayHasKey('CustomResponseSchemaPublic', $arr['components']['schemas']);
        $properties = $arr['components']['schemas']['CustomResponseSchemaPublic']['properties'];
        $this->assertArrayHasKey('name', $properties);
        $this->assertArrayHasKey('age', $properties);

        $operation = $arr['paths']['/employees/custom-response-schema-public']['get'];
        $ref = $operation['responses'][200]['content']['application/json']['schema']['$ref'];
        $this->assertEquals('#/components/schemas/CustomResponseSchemaPublic', $ref);
    }

    public function test_openapi_response_schema_public_array(): void
    {
        $arr = json_decode($this->swagger->build()->toString(), true);
        $operation = $arr['paths']['/employees/custom-response-schema-public-array']['get'];
        $ref = $operation['responses'][200]['content']['application/json']['schema']['items']['$ref'];
        $this->assertEquals('#/components/schemas/CustomResponseSchemaPublic', $ref);
    }
}