<?php

namespace Tests\App\Controllers\Api;

use App\Controllers\Api\UiController;
use CodeIgniter\HTTP\IncomingRequest;
use CodeIgniter\HTTP\URI;
use CodeIgniter\HTTP\UserAgent;
use CodeIgniter\Test\CIUnitTestCase;
use CodeIgniter\Test\Mock\MockIncomingRequest;
use Config\App;
use Config\Services;

class FakeJsonRequest extends MockIncomingRequest
{
    public function __construct(private readonly ?array $payload)
    {
        parent::__construct(config(App::class), new URI('https://test.alrahmaisgl.org'), 'php://input', new UserAgent());
    }

    public function getJSON(bool $assoc = false, int $depth = 512, int $options = 0): ?array
    {
        return $this->payload;
    }
}

class TestableUiController extends UiController
{
    private ?object $currentUser = null;
    private ?IncomingRequest $requestOverride = null;

    public function setCurrentUser(?object $user): void
    {
        $this->currentUser = $user;
    }

    public function setJsonRequest(FakeJsonRequest $request): void
    {
        $this->requestOverride = $request;
        $this->setRequest($request);
    }

    protected function getCurrentUser(): ?object
    {
        return $this->currentUser;
    }
}

class UiControllerTest extends CIUnitTestCase
{
    private TestableUiController $controller;

    protected function setUp(): void
    {
        parent::setUp();
        Services::resetSingle('session');

        $this->controller = new TestableUiController();
    }

    public function testGetStyleRequiresAuthentication()
    {
        $response = $this->controller->getStyle();

        $this->assertFalse($response['status']);
        $this->assertSame(401, $response['code']);
    }

    public function testGetStyleReturnsSessionColors()
    {
        $session = Services::session();
        $session->set([
            'style_color' => 'green',
            'menu_color' => 'brand',
            'menu_custom_bg' => '#123456',
            'menu_custom_text' => '#ffffff',
            'menu_custom_mode' => 'dark',
        ]);

        $this->controller->setCurrentUser((object) ['id' => 5]);

        $response = $this->controller->getStyle();

        $this->assertTrue($response['status']);
        $this->assertSame('green', $response['data']['style_color']);
        $this->assertArrayHasKey('available_palettes', $response['data']);
    }

    public function testUpdateStyleInvalidJsonReturnsBadRequest()
    {
        $this->controller->setCurrentUser((object) ['id' => 10]);
        $request = new FakeJsonRequest(null);
        $this->controller->setJsonRequest($request);

        $response = $this->controller->updateStyle();

        $this->assertFalse($response['status']);
        $this->assertSame(400, $response['code']);
    }

    public function testUpdateStyleChangesAccentAndMenu()
    {
        $this->controller->setCurrentUser((object) ['id' => 10]);
        $request = new FakeJsonRequest([
            'accent' => 'blue',
            'menu' => 'sky',
        ]);
        $this->controller->setJsonRequest($request);

        $response = $this->controller->updateStyle();

        $this->assertTrue($response['status']);
        $this->assertSame('sky', $response['data']['menu_color']);
        $this->assertSame('blue', $response['data']['style_color']);
    }

    public function testUpdateStyleHandlesCustomMenu()
    {
        $this->controller->setCurrentUser((object) ['id' => 10]);
        $request = new FakeJsonRequest([
            'accent' => 'purple',
            'menu' => 'custom',
            'menu_bg' => 'ffffff',
            'menu_text' => '000000',
            'menu_mode' => 'auto',
        ]);
        $this->controller->setJsonRequest($request);

        $response = $this->controller->updateStyle();

        $this->assertTrue($response['status']);
        $this->assertSame('custom', $response['data']['menu_color']);
        $this->assertSame('#FFFFFF', session()->get('menu_custom_bg'));
        $this->assertSame('#000000', session()->get('menu_custom_text'));
    }
}
