<?php

/**
 * 文件功能：后台职务管理控制器
 * 提供职务的 CRUD 功能，包含任命权限白名单（多选 position_appoint_limits）的同步
 * 职务属于部门，包含等级、图标、人数上限、奖励上限等配置
 *
 * @author   ChatRoom Laravel
 *
 * @version  1.0.0
 */

namespace App\Http\Controllers\Admin;

use App\Http\Controllers\Controller;
use App\Models\Department;
use App\Models\Position;
use App\Models\Sysparam;
use App\Support\PositionPermissionRegistry;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use Illuminate\Validation\Rule;
use Illuminate\View\View;

/**
 * 类功能：负责后台职务资料、任命白名单与聊天室权限配置的维护。
 */
class PositionController extends Controller
{
    /**
     * 职务列表页
     */
    public function index(): View
    {
        // 按部门分组展示
        $departments = Department::with([
            'positions' => fn ($q) => $q->withCount(['activeUserPositions'])->with('appointablePositions')->ordered(),
        ])->ordered()->get();

        // 全部职务（供任命白名单多选框使用）
        $allPositions = Position::with('department')->ordered()->get();

        // 全局奖励接收次数上限（0 = 不限）
        $globalRecipientDailyMax = (int) Sysparam::getValue('reward_recipient_daily_max', '0');

        $positionPermissions = PositionPermissionRegistry::groupedDefinitions();
        $permissionLabels = PositionPermissionRegistry::labelMap();

        return view('admin.positions.index', compact(
            'departments',
            'allPositions',
            'globalRecipientDailyMax',
            'positionPermissions',
            'permissionLabels',
        ));
    }

    /**
     * 创建职务（同时同步任命白名单）
     */
    public function store(Request $request): RedirectResponse
    {
        $data = $request->validate([
            'department_id' => 'required|exists:departments,id',
            'name' => 'required|string|max:50',
            'icon' => 'nullable|string|max:10',
            'rank' => 'required|integer|min:0|max:99',
            'level' => 'required|integer|min:1|max:100',
            'max_persons' => 'nullable|integer|min:1',
            'max_reward' => 'nullable|integer|min:0',
            'daily_reward_limit' => 'nullable|integer|min:0',
            'recipient_daily_limit' => 'nullable|integer|min:0',
            'red_packet_amount' => 'nullable|integer|min:1|max:999999999|gte:red_packet_count',
            'red_packet_count' => 'nullable|integer|min:1|max:100',
            'sort_order' => 'required|integer|min:0',
            'appointable_ids' => 'nullable|array',
            'appointable_ids.*' => 'exists:positions,id',
            'permissions' => 'nullable|array',
            'permissions.*' => ['string', Rule::in(PositionPermissionRegistry::codes())],
        ]);

        $appointableIds = $data['appointable_ids'] ?? [];
        unset($data['appointable_ids']);
        $data['permissions'] = array_values(array_unique($data['permissions'] ?? []));
        $data['red_packet_amount'] = (int) ($data['red_packet_amount'] ?? 8888);
        $data['red_packet_count'] = (int) ($data['red_packet_count'] ?? 10);

        $position = Position::create($data);

        // 同步任命白名单（有选则写，没选则清空=无任命权）
        $position->appointablePositions()->sync($appointableIds);

        return redirect()->route('admin.positions.index')->with('success', "职务【{$data['name']}】创建成功！");
    }

    /**
     * 快速补丁：仅更新职务的数值限额字段（内联编辑专用）
     *
     * 允许修改的字段：max_persons / max_reward / daily_reward_limit。
     * 只接受 JSON AJAX 请求，只更新提交的字段，其余字段保持不变。
     *
     * @param  Position  $position  目标职务
     */
    public function quickPatch(Request $request, Position $position): \Illuminate\Http\JsonResponse
    {
        $data = $request->validate([
            'max_persons' => 'sometimes|nullable|integer|min:1|max:9999',
            'max_reward' => 'sometimes|nullable|integer|min:0|max:999999',
            'daily_reward_limit' => 'sometimes|nullable|integer|min:0|max:999999',
        ]);

        // 用 fill+save 确保 null 值（不限）也能正确写入
        $position->fill($data)->save();

        return response()->json(['status' => 'success']);
    }

    /**
     * 保存全局奖励金币接收次数上限
     *
     * 控制每位用户单日内可从所有职务持有者处累计接收奖励的最高次数。
     * 0 表示不限制，保存到 sysparam 表中（key: reward_recipient_daily_max）。
     */
    public function saveRewardConfig(Request $request): \Illuminate\Http\JsonResponse|RedirectResponse
    {
        $request->validate([
            'reward_recipient_daily_max' => 'required|integer|min:0|max:9999',
        ]);

        $value = (string) $request->integer('reward_recipient_daily_max');

        Sysparam::updateOrCreate(
            ['alias' => 'reward_recipient_daily_max'],
            [
                'body' => $value,
                'guidetxt' => '用户单日最多接收奖励金币次数（0=不限，统计所有职务持有者的发放总次数）',
            ]
        );

        Sysparam::clearCache('reward_recipient_daily_max');

        $label = $value === '0' ? '不限' : "{$value} 次";

        // AJAX 请求返回 JSON，普通表单提交返回重定向
        if ($request->expectsJson()) {
            return response()->json(['status' => 'success', 'message' => "全局接收次数上限已更新为：{$label}"]);
        }

        return redirect()->route('admin.positions.index')
            ->with('success', "全局接收次数上限已更新为：{$label}");
    }

    /**
     * 更新职务（含任命白名单同步）
     */
    public function update(Request $request, Position $position): RedirectResponse
    {
        $data = $request->validate([
            'department_id' => 'required|exists:departments,id',
            'name' => 'required|string|max:50',
            'icon' => 'nullable|string|max:10',
            'rank' => 'required|integer|min:0|max:99',
            'level' => 'required|integer|min:1|max:100',
            'max_persons' => 'nullable|integer|min:1',
            'max_reward' => 'nullable|integer|min:0',
            'daily_reward_limit' => 'nullable|integer|min:0',
            'recipient_daily_limit' => 'nullable|integer|min:0',
            'red_packet_amount' => 'nullable|integer|min:1|max:999999999|gte:red_packet_count',
            'red_packet_count' => 'nullable|integer|min:1|max:100',
            'sort_order' => 'required|integer|min:0',
            'appointable_ids' => 'nullable|array',
            'appointable_ids.*' => 'exists:positions,id',
            'permissions' => 'nullable|array',
            'permissions.*' => ['string', Rule::in(PositionPermissionRegistry::codes())],
        ]);

        $appointableIds = $data['appointable_ids'] ?? [];
        unset($data['appointable_ids']);
        $data['permissions'] = array_values(array_unique($data['permissions'] ?? []));
        $data['red_packet_amount'] = (int) ($data['red_packet_amount'] ?? 8888);
        $data['red_packet_count'] = (int) ($data['red_packet_count'] ?? 10);

        $position->update($data);
        $position->appointablePositions()->sync($appointableIds);

        return redirect()->route('admin.positions.index')->with('success', "职务【{$data['name']}】更新成功！");
    }

    /**
     * 删除职务（有在职人员时拒绝）
     */
    public function destroy(Position $position): RedirectResponse
    {
        if ($position->isFull() || $position->activeUserPositions()->exists()) {
            return redirect()->route('admin.positions.index')
                ->with('error', "职务【{$position->name}】尚有在职人员，请先撤销后再删除。");
        }

        $position->delete();

        return redirect()->route('admin.positions.index')->with('success', "职务【{$position->name}】已删除！");
    }
}
