<?php

declare(strict_types=1);

namespace App\Http\Controllers\Api\Admin;

use App\Http\Controllers\Controller;
use App\Models\Question;
use App\Models\QuestionBank;
use App\Models\QuizAttempt;
use App\Models\User;
use App\Models\WrongQuestion;
use App\Support\ApiResponse;
use hg\apidoc\annotation as Apidoc;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;

#[Apidoc\Group('后台')]
#[Apidoc\Title('控制台')]
#[Apidoc\RouteMiddleware(['jwt.auth'])]
final class DashboardController extends Controller
{
    #[Apidoc\Title('控制台概览')]
    #[Apidoc\Url('/admin/dashboard')]
    #[Apidoc\Method('GET')]
    #[Apidoc\RouteMiddleware(['permission:dashboard'])]
    public function index(Request $request): JsonResponse
    {
        $user = $request->user();
        $bankScope = QuestionBank::query()->whereNull('deleted_at');
        if ($user->role !== 'admin') {
            $bankScope->where('owner_id', $user->id);
        }
        $bankIds = (clone $bankScope)->pluck('id');
        $questionScope = Question::query()->whereIn('question_bank_id', $bankIds);
        $todayAnswered = DB::table('quiz_attempt_questions')
            ->join('quiz_attempts', 'quiz_attempts.id', '=', 'quiz_attempt_questions.quiz_attempt_id')
            ->join('questions', 'questions.id', '=', 'quiz_attempt_questions.question_id')
            ->whereIn('questions.question_bank_id', $bankIds)
            ->whereDate('quiz_attempt_questions.answered_at', today())
            ->whereNotNull('quiz_attempt_questions.answered_at');
        $answered = (clone $todayAnswered)->count();
        $correct = (clone $todayAnswered)->where('quiz_attempt_questions.is_correct', true)->count();
        $trend = DB::table('quiz_attempt_questions')
            ->join('questions', 'questions.id', '=', 'quiz_attempt_questions.question_id')
            ->whereIn('questions.question_bank_id', $bankIds)
            ->where('quiz_attempt_questions.answered_at', '>=', now()->subDays(6)->startOfDay())
            ->whereNotNull('quiz_attempt_questions.answered_at')
            ->selectRaw('date(quiz_attempt_questions.answered_at) as day, count(*) as answered_count')
            ->groupBy('day')
            ->orderBy('day')
            ->get();
        $classRanking = DB::table('classes')
            ->leftJoin('class_members', 'class_members.class_id', '=', 'classes.id')
            ->leftJoin('quiz_attempts', 'quiz_attempts.user_id', '=', 'class_members.user_id')
            ->whereNull('classes.deleted_at')
            ->when($user->role !== 'admin', fn ($query) => $query->where('classes.owner_id', $user->id))
            ->selectRaw('classes.id, classes.name, count(distinct class_members.user_id) as members_count, count(distinct quiz_attempts.id) as attempts')
            ->groupBy('classes.id', 'classes.name')
            ->orderByDesc('attempts')
            ->limit(5)
            ->get();
        $recentAttempts = QuizAttempt::query()
            ->join('users', 'users.id', '=', 'quiz_attempts.user_id')
            ->leftJoin('question_banks', 'question_banks.id', '=', 'quiz_attempts.question_bank_id')
            ->when($user->role !== 'admin', fn ($query) => $query->whereIn('quiz_attempts.question_bank_id', $bankIds))
            ->selectRaw('quiz_attempts.id, users.name as user_name, coalesce(question_banks.name, "固定试卷") as bank_name, quiz_attempts.mode, quiz_attempts.total_questions, quiz_attempts.correct_count, quiz_attempts.started_at')
            ->latest('quiz_attempts.started_at')
            ->limit(8)
            ->get();

        return ApiResponse::success([
            'stats' => [
                'banks' => (clone $bankScope)->count(),
                'questions' => (clone $questionScope)->count(),
                'today_answered' => $answered,
                'accuracy' => $answered > 0 ? round($correct / $answered * 100, 2) : 0,
                'users' => $user->role === 'admin' ? User::query()->count() : null,
                'wrong_questions' => WrongQuestion::query()
                    ->join('questions', 'questions.id', '=', 'wrong_questions.question_id')
                    ->whereIn('questions.question_bank_id', $bankIds)
                    ->whereNull('wrong_questions.mastered_at')
                    ->count(),
            ],
            'trend' => $trend,
            'class_ranking' => $classRanking,
            'recent_attempts' => $recentAttempts,
        ]);
    }
}
