<?php

declare(strict_types=1);

namespace HyperfTest\Cases\Integration\User;

use App\Model\Platform;
use App\Model\Role;
use App\Model\User;
use App\Model\UserDataScope;
use HyperfTest\TestCase;
use Qbhy\HyperfAuth\AuthManager;

use function Hyperf\Support\make;

/**
 * @internal
 * @coversNothing
 */
class DataScopeControllerTest extends TestCase
{
    protected function getAuthToken(): string
    {
        $admin_role = $this->fetchAdminRole();
        $user = $this->fetchUser(static function ($query) use ($admin_role): void {
            $query->where('status', 1)->where('role_id', $admin_role->id);
        });
        if (!$user) {
            $this->markTestSkipped('没有可用的 administrator 用户，无法测试');
        }

        $auth = make(AuthManager::class);
        return $auth->guard('jwt')->login($user);
    }

    protected function fetchAdminRole(): Role
    {
        if (\Swoole\Coroutine::getCid() > 0) {
            return Role::query()->where('name', 'administrator')->firstOrFail();
        }

        $role = null;
        \Swoole\Coroutine\run(static function () use (&$role): void {
            $role = Role::query()->where('name', 'administrator')->firstOrFail();
        });

        return $role;
    }

    protected function authHeaders(): array
    {
        return ['Authorization' => 'Bearer ' . $this->getAuthToken()];
    }

    protected function fetchUser(?callable $callback = null): ?User
    {
        if (\Swoole\Coroutine::getCid() > 0) {
            $query = User::query();
            if ($callback !== null) {
                $callback($query);
            }

            return $query->first();
        }

        $user = null;

        \Swoole\Coroutine\run(static function () use ($callback, &$user): void {
            $query = User::query();
            if ($callback !== null) {
                $callback($query);
            }

            $user = $query->first();
        });

        return $user;
    }

    /**
     * 在协程内创建测试用户及 platform scope 数据
     *
     * @return array{user_id: int, platform_name: string}
     */
    protected function createUserWithPlatformScope(): array
    {
        $run = static function (): array {
            $suffix = bin2hex(random_bytes(4));
            $user = User::query()->create([
                'username' => 'scope_test_' . $suffix,
                'password' => 'Pass_' . $suffix,
                'email' => 'scope_test_' . $suffix . '@example.com',
                'status' => 1,
            ]);

            $platform = Platform::query()->first();

            UserDataScope::query()->insert([
                'user_id' => $user->id,
                'scope_type' => 'platform',
                'scope_id' => $platform->id,
                'created_at' => date('Y-m-d H:i:s'),
            ]);

            return ['user_id' => $user->id, 'platform_name' => $platform->name];
        };

        if (\Swoole\Coroutine::getCid() > 0) {
            return $run();
        }

        $result = null;
        \Swoole\Coroutine\run(static function () use ($run, &$result): void {
            $result = $run();
        });

        return $result;
    }

    /**
     * 测试 platform scope 返回真实平台名称（而非 "Platform #ID"）
     */
    public function test_data_scope_returns_real_platform_name(): void
    {
        $setup = $this->createUserWithPlatformScope();

        $response = $this->get('/api/v1/users/' . $setup['user_id'] . '/data-scope', [], $this->authHeaders());

        $response->assertStatus(200);
        $response->assertJsonPath('code', 0);

        $body = json_decode($response->getContent(), true);
        $scopes = $body['data']['scopes'];

        $this->assertNotEmpty($scopes);

        $platform_scope = null;
        foreach ($scopes as $scope) {
            if ($scope['scope_type'] === 'platform') {
                $platform_scope = $scope;
                break;
            }
        }

        $this->assertNotNull($platform_scope, '应包含 platform 类型的 scope');
        $this->assertSame($setup['platform_name'], $platform_scope['name'], '平台名称应为真实名称，而非 "Platform #ID"');
        $this->assertStringNotContainsString('Platform #', (string) $platform_scope['name']);
    }

    /**
     * 测试未认证请求返回 401
     */
    public function test_data_scope_without_token_returns_401(): void
    {
        $response = $this->get('/api/v1/users/1/data-scope');

        $response->assertStatus(401);
    }

    /**
     * 测试不存在的用户返回 404
     */
    public function test_data_scope_not_found_returns_404(): void
    {
        $response = $this->get('/api/v1/users/999999/data-scope', [], $this->authHeaders());

        $response->assertStatus(404);
        $response->assertJsonPath('code', 404);
    }
}
