<?php

use Firebase\JWT\JWT;
use App\Models\Player;
use App\Lottery\ErrorCode;
use Symfony\Component\HttpFoundation\Response;
use Illuminate\Foundation\Testing\RefreshDatabase;

uses(RefreshDatabase::class);

test('player me returns profile with dev bearer', function () {
    $player = Player::query()->create([
        'site_code' => 'main',
        'site_player_id' => 'uid-42',
        'username' => 'alice',
        'nickname' => 'A',
        'default_currency' => 'NPR',
        'status' => 0,
    ]);

    $this->withHeaders([
        'Authorization' => 'Bearer dev:'.$player->id,
        'X-Locale' => 'zh',
    ])
        ->getJson('/api/v1/player/me')
        ->assertOk()
        ->assertJsonPath('code', ErrorCode::Success->value)
        ->assertJsonPath('data.id', $player->id)
        ->assertJsonPath('data.site_player_id', 'uid-42')
        ->assertJsonPath('data.username', 'alice')
        ->assertJsonPath('data.locale', 'zh')
        ->assertJsonStructure([
            'data' => [
                'last_login_at',
                'created_at',
            ],
        ]);

    $player->refresh();
    expect($player->last_login_at)->not->toBeNull();
});

test('player auth missing bearer returns localized sso 8001', function () {
    $code = ErrorCode::PlayerAuthorizationInvalid->value;
    $this->withHeader('Accept-Language', 'zh-CN,zh;q=0.9')
        ->getJson('/api/v1/player/me')
        ->assertStatus(Response::HTTP_UNAUTHORIZED)
        ->assertJsonPath('code', $code)
        ->assertJsonPath('msg', __("sso.$code", [], 'zh'));
});

test('api unknown route returns unified not_found json without hitting locale middleware', function () {
    $this->withHeader('X-Locale', 'zh')
        ->getJson('/api/v1/player/__no_route__xxx')
        ->assertStatus(Response::HTTP_NOT_FOUND)
        ->assertJsonPath('code', ErrorCode::NotFound->value)
        ->assertJsonPath('msg', __('api.not_found', [], 'zh'));
});

test('player me works with main site jwt when dev bypass is off', function () {
    config(['lottery.player_auth.dev_bypass' => false]);
    config(['lottery.main_site.sso_jwt_secret' => 'jwt-test-secret']);

    $player = Player::query()->create([
        'site_code' => 'main',
        'site_player_id' => 'jwt-user-1',
        'username' => null,
        'nickname' => null,
        'default_currency' => 'NPR',
        'status' => 0,
    ]);

    $now = time();
    $jwt = JWT::encode([
        'site_code' => 'main',
        'site_player_id' => 'jwt-user-1',
        'iat' => $now,
        'exp' => $now + 300,
    ], 'jwt-test-secret', 'HS256');

    $this->withHeader('Authorization', 'Bearer '.$jwt)
        ->getJson('/api/v1/player/me')
        ->assertOk()
        ->assertJsonPath('data.site_player_id', 'jwt-user-1');
});

test('jwt first successful login auto-registers player mapping', function () {
    config(['lottery.player_auth.dev_bypass' => false]);
    config(['lottery.main_site.sso_jwt_secret' => 'jwt-test-secret']);

    expect(Player::query()->count())->toBe(0);

    $now = time();
    $jwt = JWT::encode([
        'site_code' => 'main',
        'site_player_id' => 'brand-new-sso-1',
        'iat' => $now,
        'exp' => $now + 300,
    ], 'jwt-test-secret', 'HS256');

    $response = $this->withHeader('Authorization', 'Bearer '.$jwt)
        ->getJson('/api/v1/player/me')
        ->assertOk()
        ->assertJsonPath('data.site_player_id', 'brand-new-sso-1')
        ->assertJsonPath('data.default_currency', 'NPR');

    $username = $response->json('data.username');
    expect($username)->toMatch('/^nlotto\d{6}$/')
        ->and($response->json('data.nickname'))->toBe($username);

    $player = Player::query()->where('site_player_id', 'brand-new-sso-1')->first();
    expect($player)->not->toBeNull()
        ->and($player->username)->toBe($username)
        ->and($player->nickname)->toBe($username);
});

test('player me rejects non-active status with 8005', function () {
    $code = ErrorCode::PlayerAccountSuspended->value;
    $player = Player::query()->create([
        'site_code' => 'main',
        'site_player_id' => 'frozen-1',
        'username' => null,
        'nickname' => null,
        'default_currency' => 'NPR',
        'status' => 1,
    ]);

    $this->withHeaders([
        'Authorization' => 'Bearer dev:'.$player->id,
        'Accept-Language' => 'zh-CN,zh;q=0.9',
    ])
        ->getJson('/api/v1/player/me')
        ->assertStatus(403)
        ->assertJsonPath('code', $code)
        ->assertJsonPath('msg', __("sso.$code", [], 'zh'));
});
