<?php

namespace Slovocast\Tests\Controller;

use Slovocast\Tests\TestCase;
use Slovocast\Controller\Controller;
use Psr\Http\Message\ResponseInterface as Response;
use Odan\Session\SessionInterface;

class ControllerTest extends TestCase
{
    public function testHtmlInlineResponse(): void
    {
        $testController = new class extends Controller {
            public function handle(): Response
            {
                return $this->renderInline(
                    '<p>{{ name }}</p>',
                    [ 'name' => 'Dave' ]
                );
            }
        };

        $app = $this->getAppInstance();
        $app->get('/test', $testController);

        $request = $this->createRequest('GET', '/test');
        $response = $app->handle($request);

        $this->assertEquals('<p>Dave</p>', $response->getBody());
    }

    public function testHtmlInlineResponseCodes(): void
    {
        $testController = new class extends Controller {
            public function handle(): Response
            {
                $response = $this->renderInline(
                    '<p>{{ name }}</p>',
                    [ 'name' => 'Oh no!' ]
                );

                return $response->withStatus(400);
            }
        };

        $app = $this->getAppInstance();
        $app->get('/test', $testController);

        $request = $this->createRequest('GET', '/test');
        $response = $app->handle($request);

        $this->assertEquals(400, $response->getStatusCode());
        $this->assertEquals('<p>Oh no!</p>', $response->getBody());
        $this->assertEquals('text/html', $response->getHeaderLine('Content-Type'));
    }

    public function testJsonResponse(): void
    {
        $testController = new class extends Controller {
            public function handle(): Response
            {
                return $this->json([ 'data' => 'hello' ]);
            }
        };

        $app = $this->getAppInstance();
        $app->get('/test', $testController);

        $request = $this->createRequest('GET', '/test');
        $response = $app->handle($request);

        $this->assertEquals('{"data":"hello"}', $response->getBody());
        $this->assertEquals(
            'application/json',
            $response->getHeaderLine('Content-Type')
        );
    }

    /**
     * We have some Global variables set in the Configuration, for now its
     * hardcoded in the Bootstrap class.
     */
    public function testRenderSiteName(): void
    {
        $testController = new class extends Controller {
            public function handle(): Response
            {
                return $this->renderInline("<h1>{{ site_name }}</h1>");
            }
        };

        $app = $this->getAppInstance();
        $app->get('/test', $testController);

        $request = $this->createRequest('GET', '/test');
        $response = $app->handle($request);

        $this->assertEquals('<h1>Slovocast</h1>', $response->getBody());
    }

    public function testFlashMessages(): void
    {
        $app = $this->getAppInstance();
        $session = $app->getContainer()->get(SessionInterface::class);

        $testController = new class($session) extends Controller {
            protected SessionInterface $session;

            public function __construct(SessionInterface $session)
            {
                $this->session = $session;
            }

            public function handle(): Response
            {
                $this->session->getFlash()->add("error", "Error message");
                return $this->render('home.twig');
            }
        };

        $app->get('/test', $testController);
        $request = $this->createRequest('GET', '/test');

        $response = $app->handle($request);
        $flash = $app->getContainer()->get(SessionInterface::class)->getFlash();

        $body = $response->getBody();
        // the flash class is in the body for this test case
        $this->assertTrue(str_contains($body, '<div class="flash error" role="alert">'));
        $this->assertTrue(str_contains($body, "Error message"));
        $this->assertEmpty($flash->all());
    }
}