import math
import statistics
from datetime import datetime

from django.db.models import Avg, Sum
from django.utils import timezone

from account.decorators import login_required
from account.models import AdminType, User, UserProfile
from submission.models import JudgeStatus, Submission
from utils.api import APIView


class ClassRankAPI(APIView):
    """获取班级排名列表"""

    def get(self, request):
        # 获取年级参数
        grade = int(request.GET.get("grade"))
        # 获取所有有用户的班级
        classes = (
            User.objects.filter(
                class_name__isnull=False,
                is_disabled=False,
                admin_type__in=[AdminType.REGULAR_USER, AdminType.STUDENT_ADMIN],
                class_name__startswith=str(grade),
            )
            .values("class_name")
            .distinct()
        )

        class_stats = []
        for class_info in classes:
            class_name = class_info["class_name"]
            users = User.objects.filter(
                class_name=class_name,
                is_disabled=False,
                admin_type__in=[AdminType.REGULAR_USER, AdminType.STUDENT_ADMIN],
            )
            user_ids = list(users.values_list("id", flat=True))

            profiles = UserProfile.objects.filter(user_id__in=user_ids)

            total_ac = profiles.aggregate(total=Sum("accepted_number"))["total"] or 0
            total_submission = profiles.aggregate(total=Sum("submission_number"))["total"] or 0
            avg_ac = profiles.aggregate(avg=Avg("accepted_number"))["avg"] or 0

            user_count = users.count()

            class_stats.append(
                {
                    "class_name": class_name,
                    "user_count": user_count,
                    "total_ac": int(total_ac),
                    "total_submission": int(total_submission),
                    "avg_ac": round(avg_ac, 2),
                    "ac_rate": round(total_ac / total_submission * 100, 2) if total_submission > 0 else 0,
                }
            )

        # 按总AC数排序
        class_stats.sort(key=lambda x: (-x["total_ac"], x["total_submission"]))

        # 添加排名
        for i, stat in enumerate(class_stats):
            stat["rank"] = i + 1

        return self.success(class_stats)


class UserClassRankAPI(APIView):
    """获取用户在班级中的排名"""

    @login_required
    def get(self, request):
        user = request.user
        if not user.class_name:
            return self.error("用户没有班级信息")
        scope = request.GET.get("scope", "").lower()
        show_all = scope == "all"
        try:
            limit = int(request.GET.get("limit", "10"))
        except ValueError:
            limit = 10
        if limit <= 0 or limit > 250:
            limit = 10
        try:
            offset = int(request.GET.get("offset", "0"))
        except ValueError:
            offset = 0
        if offset < 0:
            offset = 0

        # 获取同班所有用户
        class_users = User.objects.filter(
            class_name=user.class_name,
            is_disabled=False,
            admin_type__in=[AdminType.REGULAR_USER, AdminType.STUDENT_ADMIN],
        ).select_related("userprofile")

        user_ranks = []
        for class_user in class_users:
            profile = class_user.userprofile
            user_ranks.append(
                {
                    "user_id": class_user.id,
                    "username": class_user.username,
                    "accepted_number": profile.accepted_number,
                    "submission_number": profile.submission_number,
                }
            )

        # 按AC数排序
        user_ranks.sort(key=lambda x: (-x["accepted_number"], x["submission_number"]))

        # 添加排名
        my_rank = -1
        for i, rank_info in enumerate(user_ranks):
            rank_info["rank"] = i + 1
            if rank_info["user_id"] == user.id:
                my_rank = i + 1

        trimmed_ranks = user_ranks
        if not show_all and my_rank > 0 and len(user_ranks) > 10:
            center_index = my_rank - 1
            start = max(0, center_index - 5)
            end = start + 10
            if end > len(user_ranks):
                end = len(user_ranks)
                start = max(0, end - 10)
            trimmed_ranks = user_ranks[start:end]
        elif show_all:
            trimmed_ranks = user_ranks[offset : offset + limit]

        return self.success(
            {
                "class_name": user.class_name,
                "my_rank": my_rank,
                "total": len(user_ranks),
                "ranks": trimmed_ranks,
            }
        )


class ClassPKAPI(APIView):
    """班级PK比较 - 多维度教育评价"""

    def post(self, request):
        class_names = request.data.get("class_name", [])
        if not class_names or len(class_names) < 1:
            return self.error("至少需要选择1个班级")

        # 获取时间段参数
        start_time = request.data.get("start_time")
        end_time = request.data.get("end_time")

        # 将时间字符串转换为datetime对象
        # 处理空字符串、None 或 undefined 的情况
        if start_time and isinstance(start_time, str) and start_time.strip():
            try:
                start_time = datetime.fromisoformat(start_time.replace("Z", "+00:00"))
                if timezone.is_naive(start_time):
                    start_time = timezone.make_aware(start_time)
            except (ValueError, AttributeError):
                start_time = None
        else:
            start_time = None

        if end_time and isinstance(end_time, str) and end_time.strip():
            try:
                end_time = datetime.fromisoformat(end_time.replace("Z", "+00:00"))
                if timezone.is_naive(end_time):
                    end_time = timezone.make_aware(end_time)
            except (ValueError, AttributeError):
                end_time = None
        else:
            end_time = None

        class_comparisons = []

        # 预计算全局阈值（所有参与PK班级的学生AC数合并）
        all_user_ids = list(
            User.objects.filter(
                class_name__in=class_names,
                is_disabled=False,
                admin_type__in=[AdminType.REGULAR_USER, AdminType.STUDENT_ADMIN],
            ).values_list("id", flat=True)
        )
        all_ac_list = sorted(
            [p.accepted_number for p in UserProfile.objects.filter(user_id__in=all_user_ids)],
            reverse=True,
        )
        if len(all_ac_list) > 1:
            _quantiles = statistics.quantiles(all_ac_list, n=4)
            global_q1 = _quantiles[0]
            global_q3 = _quantiles[2]
        else:
            global_q1 = all_ac_list[0] if all_ac_list else 0
            global_q3 = all_ac_list[0] if all_ac_list else 0

        for class_name in class_names:
            users = User.objects.filter(
                class_name=class_name,
                is_disabled=False,
                admin_type__in=[AdminType.REGULAR_USER, AdminType.STUDENT_ADMIN],
            )
            user_ids = list(users.values_list("id", flat=True))

            # 获取所有学生的AC数列表（用于统计计算）
            profiles = UserProfile.objects.filter(user_id__in=user_ids)
            ac_list = sorted([p.accepted_number for p in profiles], reverse=True)
            submission_list = sorted([p.submission_number for p in profiles], reverse=True)

            user_count = len(ac_list)
            if user_count == 0:
                continue

            # 基础统计
            total_ac = sum(ac_list)
            total_submission = sum(submission_list)
            avg_ac = statistics.mean(ac_list) if ac_list else 0

            # 中位数和分位数
            median_ac = statistics.median(ac_list) if ac_list else 0
            q1_ac = statistics.quantiles(ac_list, n=4)[0] if len(ac_list) > 1 else 0
            q3_ac = statistics.quantiles(ac_list, n=4)[2] if len(ac_list) > 1 else 0
            iqr = q3_ac - q1_ac

            # 标准差
            std_dev = statistics.stdev(ac_list) if len(ac_list) > 1 else 0

            # 前10%和后10%统计
            top_10_count = max(1, math.ceil(user_count * 0.10))
            bottom_10_count = max(1, math.ceil(user_count * 0.10))
            top_10_avg = statistics.mean(ac_list[:top_10_count]) if top_10_count > 0 else 0
            bottom_10_avg = statistics.mean(ac_list[-bottom_10_count:]) if bottom_10_count > 0 else 0

            # 中间80%均值（截尾均值，去掉前10%和后10%）
            if top_10_count + bottom_10_count < user_count:
                middle_list = ac_list[top_10_count:-bottom_10_count]
            else:
                middle_list = ac_list
            middle_80_avg = statistics.mean(middle_list) if middle_list else avg_ac

            # 优秀率（AC数 >= 全局Q3，即超过PK组所有学生的前25%）
            excellent_count = sum(1 for ac in ac_list if ac >= global_q3)
            excellent_rate = (excellent_count / user_count * 100) if user_count > 0 else 0

            # 及格率（AC数 >= 全局Q1，即超过PK组所有学生的后25%）
            pass_count = sum(1 for ac in ac_list if ac >= global_q1)
            pass_rate = (pass_count / user_count * 100) if user_count > 0 else 0

            # 参与度（有提交记录的学生比例）
            active_count = sum(1 for sub in submission_list if sub > 0)
            active_rate = (active_count / user_count * 100) if user_count > 0 else 0

            # 时间段内的统计（如果提供了时间段）
            recent_stats = {}
            if start_time and end_time:
                submissions = Submission.objects.filter(
                    user_id__in=user_ids,
                    create_time__gte=start_time,
                    create_time__lte=end_time,
                )
                recent_ac = submissions.filter(result__in=[JudgeStatus.ACCEPTED, JudgeStatus.AST_CHECK_FAILED]).values("user_id", "problem_id").distinct().count()
                recent_submission = submissions.count()

                # 时间段内的用户AC数列表
                recent_user_ac = {}
                for user_id in user_ids:
                    user_recent_ac = submissions.filter(user_id=user_id, result__in=[JudgeStatus.ACCEPTED, JudgeStatus.AST_CHECK_FAILED]).values("problem_id").distinct().count()
                    recent_user_ac[user_id] = user_recent_ac

                recent_ac_list = sorted(recent_user_ac.values(), reverse=True)
                if recent_ac_list:
                    recent_stats = {
                        "recent_total_ac": recent_ac,
                        "recent_total_submission": recent_submission,
                        "recent_avg_ac": statistics.mean(recent_ac_list),
                        "recent_median_ac": statistics.median(recent_ac_list),
                        "recent_top_10_avg": statistics.mean(recent_ac_list[: max(1, math.ceil(len(recent_ac_list) * 0.10))]) if recent_ac_list else 0,
                        "recent_active_count": sum(1 for ac in recent_ac_list if ac > 0),
                    }

            class_comparisons.append(
                {
                    "class_name": class_name,
                    "user_count": user_count,
                    # 基础统计
                    "total_ac": int(total_ac),
                    "total_submission": int(total_submission),
                    "avg_ac": round(avg_ac, 2),
                    # 中位数和分位数
                    "median_ac": round(median_ac, 2),
                    "q1_ac": round(q1_ac, 2),
                    "q3_ac": round(q3_ac, 2),
                    "iqr": round(iqr, 2),
                    # 标准差
                    "std_dev": round(std_dev, 2),
                    # 分层统计
                    "top_10_avg": round(top_10_avg, 2),
                    "middle_80_avg": round(middle_80_avg, 2),
                    "bottom_10_avg": round(bottom_10_avg, 2),
                    # 比率统计
                    "excellent_rate": round(excellent_rate, 2),
                    "pass_rate": round(pass_rate, 2),
                    "active_rate": round(active_rate, 2),
                    # 正确率
                    "ac_rate": round(total_ac / total_submission * 100, 2) if total_submission > 0 else 0,
                    # 时间段统计（如果有）
                    **recent_stats,
                }
            )

        # 计算综合分（需要所有班级数据就绪后才能归一化）
        max_median = max((c["median_ac"] for c in class_comparisons), default=1) or 1
        max_middle = max((c["middle_80_avg"] for c in class_comparisons), default=1) or 1

        for c in class_comparisons:
            score = (
                0.40 * (c["median_ac"] / max_median * 100)
                + 0.15 * (c["middle_80_avg"] / max_middle * 100)
                + 0.20 * c["active_rate"]
                + 0.15 * c["pass_rate"]
                + 0.10 * c["excellent_rate"]
            )
            c["composite_score"] = round(score, 1)

        # 按综合分排序（主），中位数（次）
        class_comparisons.sort(key=lambda x: (-x["composite_score"], -x["median_ac"]))

        return self.success(
            {
                "comparisons": class_comparisons,
                "has_time_range": bool(start_time and end_time),
            }
        )
