<?php

declare(strict_types=1);

namespace HyperfTest\Traits;

use App\Model\Role;
use App\Model\User;
use Qbhy\HyperfAuth\AuthManager;

use function Hyperf\Support\make;

/**
 * 集成测试通用认证辅助
 *
 * 提供 admin Token 获取、协程安全数据库查询等公共方法，
 * 避免各 Controller 测试类重复实现。
 */
trait AuthenticatedTestTrait
{
    protected function getAdminToken(): 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
    {
        return $this->runInCoroutine(static function (): Role {
            return Role::query()->where('name', 'administrator')->firstOrFail();
        });
    }

    protected function fetchUser(?callable $callback = null): ?User
    {
        return $this->runInCoroutine(static function () use ($callback): ?User {
            $query = User::query();
            if ($callback !== null) {
                $callback($query);
            }
            return $query->first();
        });
    }

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

    /**
     * 在协程环境中执行回调，自动处理 Swoole 协程包装
     */
    protected function runInCoroutine(callable $callback): mixed
    {
        if (\Swoole\Coroutine::getCid() > 0) {
            return $callback();
        }

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