<?php

/**
 * 文件功能：后台通用系统参数页权限边界测试
 *
 * 覆盖通用系统参数页对站长专属敏感配置的读写隔离，
 * 防止 SMTP、VIP 支付、微信机器人及 AI 机器人等配置被越权访问。
 */

namespace Tests\Feature\Feature;

use App\Models\Sysparam;
use App\Models\User;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Tests\TestCase;

/**
 * 类功能：验证后台通用系统参数页只允许维护白名单公共配置。
 */
class AdminSystemControllerTest extends TestCase
{
    use RefreshDatabase;

    /**
     * 验证通用系统参数页不会展示站长专属敏感配置。
     */
    public function test_system_page_does_not_show_site_owner_only_sensitive_configs(): void
    {
        $this->seedSystemParams();
        $admin = $this->createSuperAdmin();

        $response = $this->actingAs($admin)->get(route('admin.system.edit'));

        $response->assertOk();
        $response->assertSee('sys_name');
        $response->assertSee('sys_notice');
        $response->assertDontSee('smtp_host');
        $response->assertDontSee('vip_payment_app_secret');
        $response->assertDontSee('wechat_bot_config');
        $response->assertDontSee('chatbot_max_gold');
        $response->assertDontSee('levelexp');
        $response->assertDontSee('level_warn');
        $response->assertDontSee('level_mute');
        $response->assertDontSee('level_kick');
        $response->assertDontSee('level_announcement');
        $response->assertDontSee('level_ban');
        $response->assertDontSee('level_banip');
        $response->assertDontSee('level_freeze');
        $response->assertSee('maxlevel');
        $response->assertSee('superlevel');
    }

    /**
     * 验证通用系统参数页更新时只会持久化白名单字段。
     */
    public function test_system_page_update_only_persists_whitelisted_configs(): void
    {
        $this->seedSystemParams();
        $admin = $this->createSuperAdmin();

        $response = $this->actingAs($admin)->put(route('admin.system.update'), [
            'sys_name' => '新版聊天室',
            'sys_notice' => '新的公共公告',
            'levelexp' => '20,80,180',
            'level_warn' => '40',
            'level_mute' => '50',
            'level_kick' => '60',
            'level_announcement' => '65',
            'level_ban' => '80',
            'level_banip' => '90',
            'level_freeze' => '95',
            'maxlevel' => '88',
            'superlevel' => '666',
            'smtp_host' => 'attacker.smtp.example',
            'vip_payment_app_secret' => 'tampered-secret',
            'wechat_bot_config' => '{"api":{"bot_key":"stolen"}}',
            'chatbot_max_gold' => '999999',
            'rogue_secret_token' => 'hacked',
        ]);

        $response->assertRedirect(route('admin.system.edit'));
        $response->assertSessionHas('success');

        $this->assertDatabaseHas('sysparam', [
            'alias' => 'sys_name',
            'body' => '新版聊天室',
        ]);
        $this->assertDatabaseHas('sysparam', [
            'alias' => 'sys_notice',
            'body' => '新的公共公告',
        ]);
        $this->assertDatabaseHas('sysparam', [
            'alias' => 'levelexp',
            'body' => '10,50,150',
        ]);
        $this->assertDatabaseHas('sysparam', [
            'alias' => 'level_warn',
            'body' => '5',
        ]);
        $this->assertDatabaseHas('sysparam', [
            'alias' => 'level_mute',
            'body' => '50',
        ]);
        $this->assertDatabaseHas('sysparam', [
            'alias' => 'level_kick',
            'body' => '60',
        ]);
        $this->assertDatabaseHas('sysparam', [
            'alias' => 'level_announcement',
            'body' => '60',
        ]);
        $this->assertDatabaseHas('sysparam', [
            'alias' => 'level_ban',
            'body' => '80',
        ]);
        $this->assertDatabaseHas('sysparam', [
            'alias' => 'level_banip',
            'body' => '90',
        ]);
        $this->assertDatabaseHas('sysparam', [
            'alias' => 'level_freeze',
            'body' => '14',
        ]);
        $this->assertDatabaseHas('sysparam', [
            'alias' => 'maxlevel',
            'body' => '88',
        ]);
        $this->assertDatabaseHas('sysparam', [
            'alias' => 'superlevel',
            'body' => '89',
        ]);

        // 敏感配置必须保持原值，不能被通用系统页伪造请求覆盖。
        $this->assertDatabaseHas('sysparam', [
            'alias' => 'smtp_host',
            'body' => 'owner.smtp.example',
        ]);
        $this->assertDatabaseHas('sysparam', [
            'alias' => 'vip_payment_app_secret',
            'body' => 'owner-secret',
        ]);
        $this->assertDatabaseHas('sysparam', [
            'alias' => 'wechat_bot_config',
            'body' => '{"api":{"bot_key":"owner-only"}}',
        ]);
        $this->assertDatabaseHas('sysparam', [
            'alias' => 'chatbot_max_gold',
            'body' => '5000',
        ]);
        $this->assertDatabaseMissing('sysparam', [
            'alias' => 'rogue_secret_token',
        ]);
    }

    /**
     * 验证非站长的高等级后台用户不能访问系统参数页。
     */
    public function test_non_site_owner_cannot_access_system_page(): void
    {
        $this->seedSystemParams();
        $admin = User::factory()->create([
            'user_level' => 100,
        ]);

        $this->actingAs($admin)
            ->get(route('admin.system.edit'))
            ->assertForbidden();
    }

    /**
     * 验证非站长的高等级后台用户看不到系统参数菜单入口。
     */
    public function test_non_site_owner_dashboard_hides_system_menu_link(): void
    {
        $this->seedSystemParams();
        $admin = User::factory()->create([
            'user_level' => 100,
        ]);

        $response = $this->actingAs($admin)->get(route('admin.dashboard'));

        $response->assertOk();
        $response->assertDontSee('⚙️ 聊天室参数', false);
    }

    /**
     * 创建可访问后台通用系统页的超级管理员账号。
     */
    private function createSuperAdmin(): User
    {
        return User::factory()->create([
            'id' => 1,
            'user_level' => 100,
        ]);
    }

    /**
     * 预置通用系统页测试所需的公共参数与敏感参数。
     */
    private function seedSystemParams(): void
    {
        foreach ($this->systemParams() as $alias => $body) {
            Sysparam::updateOrCreate(
                ['alias' => $alias],
                [
                    'body' => $body,
                    'guidetxt' => strtoupper($alias).' 配置说明',
                ]
            );
        }
    }

    /**
     * 返回本轮测试覆盖的系统参数样本。
     *
     * @return array<string, string>
     */
    private function systemParams(): array
    {
        return [
            'sys_name' => '原始聊天室',
            'sys_notice' => '原始公告',
            'levelexp' => '10,50,150',
            'level_warn' => '5',
            'level_mute' => '50',
            'level_kick' => '60',
            'level_announcement' => '60',
            'level_ban' => '80',
            'level_banip' => '90',
            'level_freeze' => '14',
            'maxlevel' => '99',
            'superlevel' => '100',
            'smtp_host' => 'owner.smtp.example',
            'vip_payment_app_secret' => 'owner-secret',
            'wechat_bot_config' => '{"api":{"bot_key":"owner-only"}}',
            'chatbot_max_gold' => '5000',
        ];
    }
}
