<?php

/**
 * 文件功能：VIP 支付集成功能测试
 * 用于验证聊天室发起 VIP 支付下单与接收异步回调开通会员的关键链路
 */

namespace Tests\Feature\Feature;

use App\Models\Sysparam;
use App\Models\User;
use App\Models\VipLevel;
use App\Models\VipPaymentOrder;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Illuminate\Support\Facades\Http;
use Illuminate\Support\Facades\Redis;
use Tests\TestCase;

/**
 * VIP 支付集成功能测试
 * 覆盖创建订单、异步开通会员以及聊天室内购买成功喜报等关键链路。
 */
class VipPaymentIntegrationTest extends TestCase
{
    use RefreshDatabase;

    /**
     * 每个测试前清空 Redis，避免聊天室在线状态与消息缓存互相污染。
     */
    protected function setUp(): void
    {
        parent::setUp();
        Redis::flushall();
    }

    /**
     * 测试用户可以发起 VIP 支付并跳转到支付中心页面
     */
    public function test_user_can_create_vip_payment_order_and_redirect_to_payment_center(): void
    {
        $this->seedVipPaymentConfig();

        $user = User::factory()->create();
        $vipLevel = VipLevel::factory()->create([
            'name' => '黄金会员',
            'price' => 68,
            'duration_days' => 30,
        ]);

        Http::fake([
            'https://novalink.test/api/open/v1/pay/orders' => Http::response([
                'success' => true,
                'message' => '支付单创建成功',
                'data' => [
                    'payment_order_no' => 'PO202604111200001234',
                    'pay_url' => 'https://novalink.test/payment/checkout/alipay/PO202604111200001234',
                ],
            ], 201),
        ]);

        $response = $this->actingAs($user)->post(route('vip.payment.store'), [
            'vip_level_id' => $vipLevel->id,
            'provider' => 'alipay',
        ]);

        $response->assertRedirect('https://novalink.test/payment/checkout/alipay/PO202604111200001234');
        Http::assertSent(function ($request) {
            $data = $request->data();

            return $request->url() === 'https://novalink.test/api/open/v1/pay/orders'
                && ($data['provider'] ?? null) === 'alipay';
        });
        $this->assertDatabaseHas('vip_payment_orders', [
            'user_id' => $user->id,
            'vip_level_id' => $vipLevel->id,
            'payment_order_no' => 'PO202604111200001234',
            'status' => 'pending',
            'provider' => 'alipay',
        ]);
    }

    /**
     * 测试用户可以选择微信支付并跳转到平台二维码页面
     */
    public function test_user_can_create_wechat_vip_payment_order_and_redirect_to_wechat_checkout_page(): void
    {
        $this->seedVipPaymentConfig();

        $user = User::factory()->create();
        $vipLevel = VipLevel::factory()->create([
            'name' => '黄金会员',
            'price' => 68,
            'duration_days' => 30,
        ]);

        Http::fake([
            'https://novalink.test/api/open/v1/pay/orders' => Http::response([
                'success' => true,
                'message' => '支付单创建成功',
                'data' => [
                    'payment_order_no' => 'PO202604131530001234',
                    'pay_url' => 'https://novalink.test/payment/checkout/wechat/PO202604131530001234',
                ],
            ], 201),
        ]);

        $response = $this->actingAs($user)->post(route('vip.payment.store'), [
            'vip_level_id' => $vipLevel->id,
            'provider' => 'wechat',
        ]);

        $response->assertRedirect('https://novalink.test/payment/checkout/wechat/PO202604131530001234');
        Http::assertSent(function ($request) {
            $data = $request->data();

            return $request->url() === 'https://novalink.test/api/open/v1/pay/orders'
                && ($data['provider'] ?? null) === 'wechat';
        });
        $this->assertDatabaseHas('vip_payment_orders', [
            'user_id' => $user->id,
            'vip_level_id' => $vipLevel->id,
            'payment_order_no' => 'PO202604131530001234',
            'status' => 'pending',
            'provider' => 'wechat',
        ]);
    }

    /**
     * 测试异步回调只会为同一笔订单开通一次会员，避免重复叠加时长
     */
    public function test_async_notify_opens_vip_only_once(): void
    {
        $this->seedVipPaymentConfig();

        $user = User::factory()->create();
        $vipLevel = VipLevel::factory()->create([
            'name' => '钻石会员',
            'price' => 88,
            'duration_days' => 30,
        ]);

        $order = VipPaymentOrder::factory()->create([
            'user_id' => $user->id,
            'vip_level_id' => $vipLevel->id,
            'amount' => 88.00,
            'provider' => 'wechat',
            'vip_name' => $vipLevel->name,
            'vip_duration_days' => $vipLevel->duration_days,
            'payment_order_no' => 'PO202604111530001234',
            'merchant_order_no' => 'VPO202604111530001234',
        ]);

        $payload = [
            'payment_order_no' => $order->payment_order_no,
            'merchant_order_no' => $order->merchant_order_no,
            'status' => 'paid',
            'amount' => '88.00',
            'provider' => 'wechat',
            'provider_trade_no' => '4200002512202604139876543210',
            'paid_at' => '2026-04-11 15:35:12',
        ];

        $rawBody = json_encode($payload, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
        $signature = hash_hmac('sha256', $rawBody, 'chatroom-secret');

        $firstResponse = $this->call(
            'POST',
            route('vip.payment.notify'),
            [],
            [],
            [],
            [
                'CONTENT_TYPE' => 'application/json',
                'HTTP_X_PAYMENT_SIGNATURE' => $signature,
            ],
            $rawBody
        );

        $firstResponse->assertOk();
        $user->refresh();
        $this->assertSame($vipLevel->id, $user->vip_level_id);
        $this->assertNotNull($user->hy_time);
        $firstExpireAt = $user->hy_time?->toDateTimeString();

        $secondResponse = $this->call(
            'POST',
            route('vip.payment.notify'),
            [],
            [],
            [],
            [
                'CONTENT_TYPE' => 'application/json',
                'HTTP_X_PAYMENT_SIGNATURE' => $signature,
            ],
            $rawBody
        );

        $secondResponse->assertOk();
        $user->refresh();
        $this->assertSame($firstExpireAt, $user->hy_time?->toDateTimeString());
        $this->assertDatabaseHas('vip_payment_orders', [
            'id' => $order->id,
            'status' => 'paid',
            'provider' => 'wechat',
        ]);
    }

    /**
     * 测试会员中心页面只展示当前用户自己的购买记录
     */
    public function test_vip_center_only_shows_current_user_records(): void
    {
        $this->seedVipPaymentConfig();

        $currentUser = User::factory()->create();
        $otherUser = User::factory()->create();

        VipPaymentOrder::factory()->create([
            'user_id' => $currentUser->id,
            'order_no' => 'VPO_CURRENT_001',
        ]);

        VipPaymentOrder::factory()->create([
            'user_id' => $otherUser->id,
            'order_no' => 'VPO_OTHER_001',
        ]);

        $response = $this->actingAs($currentUser)->get(route('vip.center'));

        $response->assertOk();
        $response->assertSee('VPO_CURRENT_001');
        $response->assertDontSee('VPO_OTHER_001');
        $response->assertSee('我的购买记录');
    }

    /**
     * 测试允许自定义的会员可以在会员中心保存自己的欢迎语和离开语。
     */
    public function test_vip_member_can_update_custom_presence_messages(): void
    {
        $this->seedVipPaymentConfig();

        $vipLevel = VipLevel::factory()->create([
            'allow_custom_messages' => true,
        ]);
        $user = User::factory()->create([
            'vip_level_id' => $vipLevel->id,
            'hy_time' => now()->addDays(30),
        ]);

        $response = $this->actingAs($user)->put(route('vip.center.presence.update'), [
            'custom_join_message' => '{username} 乘着流光闪耀登场',
            'custom_leave_message' => '{username} 留下一缕星辉悄然退场',
        ]);

        $response->assertRedirect(route('vip.center'));
        $this->assertDatabaseHas('users', [
            'id' => $user->id,
            'custom_join_message' => '{username} 乘着流光闪耀登场',
            'custom_leave_message' => '{username} 留下一缕星辉悄然退场',
        ]);
    }

    /**
     * 测试普通用户或不允许自定义的会员无法保存专属语句。
     */
    public function test_non_customizable_vip_member_cannot_update_custom_presence_messages(): void
    {
        $this->seedVipPaymentConfig();

        $vipLevel = VipLevel::factory()->create([
            'allow_custom_messages' => false,
        ]);
        $user = User::factory()->create([
            'vip_level_id' => $vipLevel->id,
            'hy_time' => now()->addDays(30),
        ]);

        $response = $this->actingAs($user)->put(route('vip.center.presence.update'), [
            'custom_join_message' => '不应被保存',
            'custom_leave_message' => '不应被保存',
        ]);

        $response->assertRedirect(route('vip.center'));
        $this->assertDatabaseMissing('users', [
            'id' => $user->id,
            'custom_join_message' => '不应被保存',
        ]);
    }

    /**
     * 初始化支付中心模拟配置
     */
    private function seedVipPaymentConfig(): void
    {
        Sysparam::updateOrCreate(['alias' => 'vip_payment_enabled'], ['body' => '1']);
        Sysparam::clearCache('vip_payment_enabled');
        Sysparam::updateOrCreate(['alias' => 'vip_payment_base_url'], ['body' => 'https://novalink.test']);
        Sysparam::updateOrCreate(['alias' => 'vip_payment_app_key'], ['body' => 'chatroom-app']);
        Sysparam::updateOrCreate(['alias' => 'vip_payment_app_secret'], ['body' => 'chatroom-secret']);
        Sysparam::updateOrCreate(['alias' => 'vip_payment_timeout'], ['body' => '10']);

        Sysparam::clearCache('vip_payment_base_url');
        Sysparam::clearCache('vip_payment_app_key');
        Sysparam::clearCache('vip_payment_app_secret');
        Sysparam::clearCache('vip_payment_timeout');
    }
}
