"""
分数分配工具

解决题目分数无法整除的问题，确保：
1. 所有题目分数之和精确等于总分
2. 题目分数差异最小化（最多相差1分）
3. 支持整数分配和小数分配两种模式
"""
from typing import List, Tuple
from decimal import Decimal, ROUND_HALF_UP
import math


class ScoreDistributor:
    """
    智能分数分配器
    
    使用示例：
        distributor = ScoreDistributor(total_score=100, question_count=6)
        scores = distributor.distribute()
        # 结果: [17, 17, 17, 17, 16, 16]  总和=100
    """
    
    def __init__(self, total_score: float, question_count: int):
        """
        初始化分配器
        
        Args:
            total_score: 总分（如 100）
            question_count: 题目数量（如 6）
        """
        if question_count <= 0:
            raise ValueError("题目数量必须大于0")
        if total_score <= 0:
            raise ValueError("总分必须大于0")
            
        self.total_score = total_score
        self.question_count = question_count
    
    def distribute_integer(self) -> List[int]:
        """
        整数分配模式
        
        将总分分配为整数，前面的题目分数可能比后面的多1分
        
        Returns:
            分数列表，如 [17, 17, 17, 17, 16, 16]
            
        示例：
            100分 / 6题 = [17, 17, 17, 17, 16, 16]
            100分 / 7题 = [15, 15, 14, 14, 14, 14, 14]
        """
        total = int(self.total_score)
        count = self.question_count
        
        # 基础分数（向下取整）
        base_score = total // count
        # 需要额外加1分的题目数量
        extra_count = total % count
        
        # 生成分数列表
        scores = []
        for i in range(count):
            if i < extra_count:
                scores.append(base_score + 1)
            else:
                scores.append(base_score)
        
        return scores
    
    def distribute_decimal(self, decimal_places: int = 1) -> List[float]:
        """
        小数分配模式
        
        将总分分配为小数，最后一题用于补齐差额
        
        Args:
            decimal_places: 小数位数，默认1位
            
        Returns:
            分数列表，如 [16.7, 16.7, 16.7, 16.7, 16.7, 16.5]
        """
        count = self.question_count
        
        # 计算每题分数并四舍五入
        per_score = self.total_score / count
        rounded_score = round(per_score, decimal_places)
        
        # 前 n-1 题使用四舍五入的分数
        scores = [rounded_score] * (count - 1)
        
        # 最后一题用总分减去前面的和，确保总分精确
        last_score = round(self.total_score - sum(scores), decimal_places)
        scores.append(last_score)
        
        return scores
    
    def distribute(self, mode: str = "integer") -> List[float]:
        """
        分配分数
        
        Args:
            mode: 分配模式
                - "integer": 整数分配（推荐）
                - "decimal": 小数分配
                - "decimal_1": 保留1位小数
                - "decimal_2": 保留2位小数
                
        Returns:
            分数列表
        """
        if mode == "integer":
            return [float(s) for s in self.distribute_integer()]
        elif mode == "decimal" or mode == "decimal_1":
            return self.distribute_decimal(1)
        elif mode == "decimal_2":
            return self.distribute_decimal(2)
        else:
            return [float(s) for s in self.distribute_integer()]
    
    def get_score_for_question(self, question_index: int, mode: str = "integer") -> float:
        """
        获取指定题目的分数
        
        Args:
            question_index: 题目索引（从0开始）
            mode: 分配模式
            
        Returns:
            该题目的分数
        """
        scores = self.distribute(mode)
        if 0 <= question_index < len(scores):
            return scores[question_index]
        raise IndexError(f"题目索引 {question_index} 超出范围 [0, {self.question_count})")
    
    def validate(self) -> Tuple[bool, str]:
        """
        验证分配结果
        
        Returns:
            (是否有效, 信息)
        """
        scores = self.distribute()
        total = sum(scores)
        
        if abs(total - self.total_score) < 0.01:
            return True, f"分配有效：{scores}，总分={total}"
        else:
            return False, f"分配无效：{scores}，总分={total}，期望={self.total_score}"
    
    @staticmethod
    def format_score(score: float, decimal_places: int = 1) -> str:
        """
        格式化分数显示
        
        Args:
            score: 分数
            decimal_places: 小数位数
            
        Returns:
            格式化的分数字符串
        """
        if score == int(score):
            return str(int(score))
        return f"{score:.{decimal_places}f}"
    
    @staticmethod
    def calculate_pass_score(total_score: float, pass_rate: float = 0.6) -> float:
        """
        计算及格分数
        
        Args:
            total_score: 总分
            pass_rate: 及格率，默认60%
            
        Returns:
            及格分数（整数）
        """
        return math.ceil(total_score * pass_rate)


def distribute_scores(total_score: float, question_count: int, mode: str = "integer") -> List[float]:
    """
    便捷函数：分配分数
    
    Args:
        total_score: 总分
        question_count: 题目数量
        mode: 分配模式（integer/decimal）
        
    Returns:
        分数列表
    """
    distributor = ScoreDistributor(total_score, question_count)
    return distributor.distribute(mode)


def get_question_score(
    total_score: float, 
    question_count: int, 
    question_index: int,
    mode: str = "integer"
) -> float:
    """
    便捷函数：获取指定题目的分数
    
    Args:
        total_score: 总分
        question_count: 题目数量
        question_index: 题目索引（从0开始）
        mode: 分配模式
        
    Returns:
        该题目的分数
    """
    distributor = ScoreDistributor(total_score, question_count)
    return distributor.get_score_for_question(question_index, mode)
