<?php

declare(strict_types=1);

namespace App\Http\Controllers\Api\Admin;

use App\Http\Controllers\Controller;
use App\Models\SchoolClass;
use App\Support\ApiResponse;
use hg\apidoc\annotation as Apidoc;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Str;

#[Apidoc\Group('后台')]
#[Apidoc\Title('班级管理')]
#[Apidoc\RouteMiddleware(['jwt.auth'])]
final class ClassController extends Controller
{
    #[Apidoc\Title('班级列表')]
    #[Apidoc\Url('/admin/classes')]
    #[Apidoc\Method('GET')]
    #[Apidoc\RouteMiddleware(['permission:classes'])]
    public function index(Request $request): JsonResponse
    {
        $query = SchoolClass::query()->withCount('members')->latest();
        if ($request->user()->role !== 'admin') {
            $query->where('owner_id', $request->user()->id);
        }

        return ApiResponse::page($query->paginate((int) $request->query('per_page', 20)));
    }

    #[Apidoc\Title('创建班级')]
    #[Apidoc\Url('/admin/classes')]
    #[Apidoc\Method('POST')]
    #[Apidoc\RouteMiddleware(['permission:classes'])]
    public function store(Request $request): JsonResponse
    {
        $data = $request->validate([
            'name' => ['required', 'string', 'max:100'],
            'description' => ['nullable', 'string'],
        ]);

        $class = SchoolClass::create($data + [
            'owner_id' => $request->user()->id,
            'join_code' => strtoupper(Str::random(8)),
            'is_active' => true,
        ]);

        return ApiResponse::success($class, '班级已创建');
    }

    #[Apidoc\Title('更新班级')]
    #[Apidoc\Url('/admin/classes/{class}')]
    #[Apidoc\Method('PUT')]
    #[Apidoc\RouteMiddleware(['permission:classes'])]
    public function update(Request $request, mixed $class): JsonResponse
    {
        $class = $this->resolveClass($class);
        abort_if($request->user()->role !== 'admin' && $class->owner_id !== $request->user()->id, 403, '权限不足');

        $data = $request->validate([
            'name' => ['sometimes', 'required', 'string', 'max:100'],
            'description' => ['nullable', 'string'],
            'is_active' => ['sometimes', 'boolean'],
        ]);

        $class->update($data);

        return ApiResponse::success($class->fresh()->loadCount('members'), '班级已更新');
    }

    #[Apidoc\Title('分配成员')]
    #[Apidoc\Url('/admin/classes/{class}/members')]
    #[Apidoc\Method('POST')]
    #[Apidoc\RouteMiddleware(['permission:classes'])]
    public function addMember(Request $request, mixed $class): JsonResponse
    {
        $class = $this->resolveClass($class);
        abort_if($request->user()->role !== 'admin' && $class->owner_id !== $request->user()->id, 403, '权限不足');

        $data = $request->validate([
            'user_id' => ['required', 'exists:users,id'],
            'role' => ['nullable', 'in:student,assistant'],
        ]);

        $class->members()->syncWithoutDetaching([
            $data['user_id'] => ['role' => $data['role'] ?? 'student'],
        ]);

        return ApiResponse::success($class->load('members'), '成员已加入');
    }

    #[Apidoc\Title('批量分配成员')]
    #[Apidoc\Url('/admin/classes/{class}/members/batch')]
    #[Apidoc\Method('POST')]
    #[Apidoc\RouteMiddleware(['permission:classes'])]
    public function addMembers(Request $request, mixed $class): JsonResponse
    {
        $class = $this->resolveClass($class);
        abort_if($request->user()->role !== 'admin' && $class->owner_id !== $request->user()->id, 403, '权限不足');

        $data = $request->validate([
            'user_ids' => ['required', 'array', 'min:1'],
            'user_ids.*' => ['integer', 'exists:users,id'],
            'role' => ['nullable', 'in:student,assistant'],
        ]);

        $role = $data['role'] ?? 'student';
        $members = collect($data['user_ids'])
            ->unique()
            ->mapWithKeys(fn (int $userId): array => [$userId => ['role' => $role]])
            ->all();
        $class->members()->syncWithoutDetaching($members);

        return ApiResponse::success($class->fresh()->loadCount('members'), '成员已加入');
    }

    private function resolveClass(mixed $class): SchoolClass
    {
        if ($class instanceof SchoolClass && $class->exists) {
            return $class;
        }

        return SchoolClass::query()->findOrFail((int) $class);
    }
}
