<?php

namespace MintyPHP\Tests\Support;

use MintyPHP\Http\Input\RequestInput;
use MintyPHP\I18n;
use MintyPHP\Router;
use PHPUnit\Framework\TestCase;

class RequestReturnTargetHelperTest extends TestCase
{
    private array $serverBackup = [];
    private string $defaultLocaleBackup = 'en';
    private string $localeBackup = '';

    protected function setUp(): void
    {
        parent::setUp();
        $this->serverBackup = $_SERVER;
        $this->defaultLocaleBackup = (string) I18n::$defaultLocale;
        $this->localeBackup = (string) I18n::$locale;
        I18n::$defaultLocale = 'de';
        I18n::$locale = 'de';
        Router::$baseUrl = '/';
    }

    protected function tearDown(): void
    {
        $_SERVER = $this->serverBackup;
        I18n::$defaultLocale = $this->defaultLocaleBackup;
        I18n::$locale = $this->localeBackup;
        parent::tearDown();
    }

    public function testResolveReturnTargetPrefersBodyValue(): void
    {
        $input = new RequestInput('POST', ['return' => 'admin/roles'], ['return' => 'admin/users?active=1'], []);

        $this->assertSame('admin/users?active=1', \requestResolveReturnTargetFromInput($input));
    }

    public function testResolveReturnTargetFallsBackToQueryValue(): void
    {
        $input = new RequestInput('GET', ['return' => 'admin/departments?tenant=abc'], [], []);

        $this->assertSame('admin/departments?tenant=abc', \requestResolveReturnTargetFromInput($input));
    }

    public function testResolveReturnTargetFallsBackToStaticPathForInvalidReturn(): void
    {
        $input = new RequestInput('POST', ['return' => 'https://evil.example/path'], [], []);

        $this->assertSame('admin/users', \requestResolveReturnTargetFromInput($input, 'admin/users'));
    }

    public function testResolveReturnTargetIgnoresRefererWhenReturnIsInvalid(): void
    {
        $_SERVER['HTTP_REFERER'] = 'https://app.example/admin/roles';
        $_SERVER['HTTP_HOST'] = 'app.example';

        $input = new RequestInput('POST', ['return' => 'https://evil.example/path'], [], []);

        $this->assertSame('admin/users', \requestResolveReturnTargetFromInput($input, 'admin/users'));
    }

    public function testResolveReturnTargetFallsBackToStaticPathForEmptyReturn(): void
    {
        $input = new RequestInput('GET', [], [], []);

        $this->assertSame('admin/users', \requestResolveReturnTargetFromInput($input, 'admin/users'));
    }

    public function testResolveReturnTargetStripsLocalePrefixAndNestedReturn(): void
    {
        $input = new RequestInput('GET', ['return' => '/de/admin/users?active=1&return=admin/old'], [], []);

        $this->assertSame('admin/users?active=1', \requestResolveReturnTargetFromInput($input));
    }

    public function testPathWithReturnTargetAppendsReturnQuery(): void
    {
        $this->assertSame(
            'admin/users/edit/abc?return=admin%2Fusers%3Factive%3D1',
            \requestPathWithReturnTarget('admin/users/edit/abc', 'admin/users?active=1')
        );
    }

    public function testPathWithReturnTargetPreservesExistingQueryAndRemovesNestedReturn(): void
    {
        $this->assertSame(
            'admin/users/edit/abc?tab=profile&return=admin%2Fusers%3Factive%3D1',
            \requestPathWithReturnTarget(
                'admin/users/edit/abc?tab=profile',
                'admin/users?active=1&return=admin/old'
            )
        );
    }

    public function testPathWithReturnTargetIgnoresExternalReturnTarget(): void
    {
        $_SERVER['HTTP_REFERER'] = 'https://app.example/admin/roles';
        $_SERVER['HTTP_HOST'] = 'app.example';

        $this->assertSame(
            'admin/users/edit/abc',
            \requestPathWithReturnTarget('admin/users/edit/abc', 'https://evil.example')
        );
    }

    public function testPathWithReturnTargetNormalizesLocalePrefixedReturnTarget(): void
    {
        $this->assertSame(
            'admin/users/edit/abc?return=admin%2Fusers%3Factive%3D1',
            \requestPathWithReturnTarget('admin/users/edit/abc', '/de/admin/users?active=1')
        );
    }

    public function testResolveReturnTargetUsesDeepestNestedReturnTarget(): void
    {
        $input = new RequestInput(
            'GET',
            ['return' => 'admin/users/edit/abc?return=admin/users?active=1'],
            [],
            []
        );

        $this->assertSame('admin/users?active=1', \requestResolveReturnTargetFromInput($input, 'admin/users'));
    }

    public function testResolveReturnTargetFallsBackToListWhenReturnPointsToDetailPath(): void
    {
        $input = new RequestInput('GET', ['return' => 'admin/users/edit/abc'], [], []);

        $this->assertSame('admin/users', \requestResolveReturnTargetFromInput($input, 'admin/users'));
    }

    public function testPathWithReturnTargetFlattensNestedEditReturnTargetToList(): void
    {
        $this->assertSame(
            'admin/users/edit/abc?return=admin%2Fusers%3Factive%3D1',
            \requestPathWithReturnTarget(
                'admin/users/edit/abc',
                'admin/users/edit/abc?return=admin/users?active=1'
            )
        );
    }
}
