<?php

/**
 * 文件功能：后台职务权限管理功能测试
 *
 * 覆盖职务权限字段的保存、更新、校验与页面展示，
 * 确保后台配置可以稳定驱动聊天室顶部管理菜单。
 */

namespace Tests\Feature\Feature;

use App\Models\Department;
use App\Models\Position;
use App\Models\User;
use App\Support\PositionPermissionRegistry;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Tests\TestCase;

/**
 * 类功能：验证后台职务权限管理页的关键行为。
 */
class AdminPositionPermissionTest extends TestCase
{
    use RefreshDatabase;

    /**
     * 验证站长可以创建带聊天室权限的职务。
     */
    public function test_site_owner_can_store_position_with_room_permissions(): void
    {
        $owner = $this->createSiteOwner();
        $department = $this->createDepartment();

        $response = $this->actingAs($owner)->post(route('admin.positions.store'), [
            'department_id' => $department->id,
            'name' => '值班主持',
            'icon' => '🎙️',
            'rank' => 66,
            'level' => 66,
            'max_persons' => 2,
            'max_reward' => 100,
            'daily_reward_limit' => 300,
            'recipient_daily_limit' => 2,
            'red_packet_amount' => 12000,
            'red_packet_count' => 12,
            'sort_order' => 8,
            'permissions' => [
                PositionPermissionRegistry::ROOM_ANNOUNCEMENT,
                PositionPermissionRegistry::ROOM_PUBLIC_BROADCAST,
            ],
        ]);

        $response->assertRedirect(route('admin.positions.index'));

        $position = Position::query()->where('name', '值班主持')->firstOrFail();

        $this->assertSame(12000, (int) $position->red_packet_amount);
        $this->assertSame(12, (int) $position->red_packet_count);
        $this->assertSame([
            PositionPermissionRegistry::ROOM_ANNOUNCEMENT,
            PositionPermissionRegistry::ROOM_PUBLIC_BROADCAST,
        ], $position->permissions);
    }

    /**
     * 验证非法权限码会被后台校验拒绝。
     */
    public function test_invalid_permission_code_is_rejected_when_storing_position(): void
    {
        $owner = $this->createSiteOwner();
        $department = $this->createDepartment();

        $response = $this->from(route('admin.positions.index'))->actingAs($owner)->post(route('admin.positions.store'), [
            'department_id' => $department->id,
            'name' => '巡查主持',
            'icon' => '🛰️',
            'rank' => 55,
            'level' => 55,
            'max_persons' => 1,
            'sort_order' => 2,
            'permissions' => [
                PositionPermissionRegistry::ROOM_ANNOUNCEMENT,
                'room.invalid_permission',
            ],
        ]);

        $response->assertRedirect(route('admin.positions.index'));
        $response->assertSessionHasErrors('permissions.1');
    }

    /**
     * 验证站长可以更新职务的聊天室权限配置。
     */
    public function test_site_owner_can_update_position_permissions(): void
    {
        $owner = $this->createSiteOwner();
        $department = $this->createDepartment();
        $position = Position::create([
            'department_id' => $department->id,
            'name' => '公告员',
            'icon' => '📣',
            'rank' => 60,
            'level' => 60,
            'sort_order' => 1,
            'permissions' => [
                PositionPermissionRegistry::ROOM_ANNOUNCEMENT,
            ],
        ]);

        $response = $this->actingAs($owner)->put(route('admin.positions.update', $position), [
            'department_id' => $department->id,
            'name' => '公告员',
            'icon' => '📣',
            'rank' => 60,
            'level' => 60,
            'max_persons' => null,
            'max_reward' => null,
            'daily_reward_limit' => null,
            'recipient_daily_limit' => null,
            'red_packet_amount' => 6600,
            'red_packet_count' => 6,
            'sort_order' => 1,
            'permissions' => [
                PositionPermissionRegistry::ROOM_RED_PACKET,
                PositionPermissionRegistry::ROOM_FULLSCREEN_EFFECT,
            ],
        ]);

        $response->assertRedirect(route('admin.positions.index'));

        $position->refresh();

        $this->assertSame(6600, (int) $position->red_packet_amount);
        $this->assertSame(6, (int) $position->red_packet_count);
        $this->assertSame([
            PositionPermissionRegistry::ROOM_RED_PACKET,
            PositionPermissionRegistry::ROOM_FULLSCREEN_EFFECT,
        ], $position->permissions);
    }

    /**
     * 验证礼包总量不能小于礼包份数。
     */
    public function test_red_packet_amount_must_cover_packet_count(): void
    {
        $owner = $this->createSiteOwner();
        $department = $this->createDepartment();

        $response = $this->from(route('admin.positions.index'))->actingAs($owner)->post(route('admin.positions.store'), [
            'department_id' => $department->id,
            'name' => '礼包主持',
            'icon' => '🧧',
            'rank' => 55,
            'level' => 55,
            'max_persons' => 1,
            'red_packet_amount' => 5,
            'red_packet_count' => 10,
            'sort_order' => 2,
            'permissions' => [
                PositionPermissionRegistry::ROOM_RED_PACKET,
            ],
        ]);

        $response->assertRedirect(route('admin.positions.index'));
        $response->assertSessionHasErrors('red_packet_amount');
    }

    /**
     * 验证职务管理页面会渲染权限配置与摘要文案。
     */
    public function test_positions_index_renders_permission_form_and_summary(): void
    {
        $owner = $this->createSiteOwner();
        $department = $this->createDepartment();

        Position::create([
            'department_id' => $department->id,
            'name' => '活动主持',
            'icon' => '🎁',
            'rank' => 70,
            'level' => 70,
            'sort_order' => 1,
            'permissions' => [
                PositionPermissionRegistry::ROOM_ANNOUNCEMENT,
                PositionPermissionRegistry::ROOM_RED_PACKET,
            ],
        ]);

        $response = $this->actingAs($owner)->get(route('admin.positions.index'));

        $response->assertOk();
        $response->assertSee('权限管理');
        $response->assertSee('设置公告');
        $response->assertSee('礼包红包');
        $response->assertSee('默认礼包总量');
        $response->assertSee('默认礼包份数');
        $response->assertSee('警告用户');
        $response->assertSee('冻结用户');
    }

    /**
     * 创建站长账号。
     */
    private function createSiteOwner(): User
    {
        return User::factory()->create([
            'id' => 1,
            'user_level' => 100,
        ]);
    }

    /**
     * 创建测试用部门。
     */
    private function createDepartment(): Department
    {
        return Department::create([
            'name' => '测试部门',
            'rank' => 90,
            'color' => '#334155',
            'sort_order' => 1,
            'description' => '后台权限测试部门',
        ]);
    }
}
