<?php

declare(strict_types=1);

namespace HyperfTest\Cases\Integration\System;

use App\Model\User;
use HyperfTest\TestCase;
use HyperfTest\Traits\AuthenticatedTestTrait;
use Qbhy\HyperfAuth\AuthManager;

use function Hyperf\Support\make;

/**
 * POST /api/v1/routes/sync 集成测试
 *
 * 覆盖管理员成功、非管理员 403、重复调用幂等
 *
 * @internal
 * @coversNothing
 */
class RouteSyncTest extends TestCase
{
    use AuthenticatedTestTrait;

    private static ?User $nonAdminUser = null;

    protected function getNonAdminHeaders(): array
    {
        if (self::$nonAdminUser === null) {
            self::$nonAdminUser = $this->runInCoroutine(static function (): User {
                return User::query()->create([
                    'username' => 'route_sync_test_nonadmin_' . uniqid(),
                    'password' => 'TestPass123',
                    'email' => 'route_sync_nonadmin_' . uniqid() . '@example.com',
                    'status' => 1,
                ]);
            });
        }

        return $this->runInCoroutine(function (): array {
            $auth = make(AuthManager::class);
            $token = $auth->guard('jwt')->login(self::$nonAdminUser);
            return ['Authorization' => 'Bearer ' . $token];
        });
    }

    public static function tearDownAfterClass(): void
    {
        if (self::$nonAdminUser !== null) {
            $user_id = self::$nonAdminUser->id;
            $cleanup = static function () use ($user_id): void {
                User::query()->where('id', $user_id)->delete();
            };

            if (\Swoole\Coroutine::getCid() > 0) {
                $cleanup();
            } else {
                \Swoole\Coroutine\run($cleanup);
            }
            self::$nonAdminUser = null;
        }

        parent::tearDownAfterClass();
    }

    // ========== 管理员成功 ==========

    public function test_admin_can_sync_routes(): void
    {
        $response = $this->post('/api/v1/routes/sync', [], $this->authHeaders());

        $response->assertOk();
        $body = $response->json();

        $this->assertSame(0, $body['code']);
        $this->assertSame('同步成功', $body['message']);
        $this->assertIsArray($body['data']);
        $this->assertArrayHasKey('synced', $body['data']);
        $this->assertArrayHasKey('total', $body['data']);
        $this->assertIsInt($body['data']['synced']);
        $this->assertIsInt($body['data']['total']);
        $this->assertGreaterThan(0, $body['data']['synced']);
        $this->assertSame($body['data']['synced'], $body['data']['total']);
    }

    // ========== 非管理员 403 ==========

    public function test_non_admin_receives_403(): void
    {
        $response = $this->post('/api/v1/routes/sync', [], $this->getNonAdminHeaders());

        $response->assertStatus(403);
    }

    // ========== 未认证 401 ==========

    public function test_unauthenticated_returns_401(): void
    {
        $response = $this->post('/api/v1/routes/sync');

        $response->assertStatus(401);
    }

    // ========== 重复调用幂等 ==========

    public function test_repeated_sync_is_idempotent(): void
    {
        $response1 = $this->post('/api/v1/routes/sync', [], $this->authHeaders());
        $response1->assertOk();
        $data1 = $response1->json('data');

        $response2 = $this->post('/api/v1/routes/sync', [], $this->authHeaders());
        $response2->assertOk();
        $data2 = $response2->json('data');

        $this->assertSame($data1['synced'], $data2['synced']);
        $this->assertSame($data1['total'], $data2['total']);
    }
}
