"""
debatewiki共识计算技能
使用Python实现的无依赖共识计算功能
"""

import json
import sys
from typing import Dict, List, Any, Optional


def calculate_voting_consensus(messages: List[Dict[str, Any]], threshold: float = 0.7) -> Dict[str, Any]:
    """
    计算投票共识
    
    Args:
        messages: 包含投票信息的消息列表
        threshold: 达成共识所需的阈值 (0-1)
        
    Returns:
        包含共识结果的字典
    """
    votes = extract_votes(messages)
    
    if not votes:
        return {
            "achieved": False,
            "agreement_ratio": 0.0,
            "summary": "No votes found in messages",
            "votes": {}
        }
    
    yes_votes = sum(1 for vote in votes.values() if vote)
    total_votes = len(votes)
    
    agreement_ratio = yes_votes / total_votes if total_votes > 0 else 0
    achieved = agreement_ratio >= threshold
    
    summary = f"Voting Consensus (threshold: {threshold*100:.0f}%)\n"
    summary += f"- Total votes: {total_votes}\n"
    summary += f"- Yes votes: {yes_votes}\n"
    summary += f"- Agreement: {(agreement_ratio*100):.1f}%\n"
    summary += f"- Result: {'ACHIEVED' if achieved else 'NOT ACHIEVED'}\n"
    
    if votes:
        summary += f"\nVotes:\n"
        yes_voters = [agent for agent, vote in votes.items() if vote]
        no_voters = [agent for agent, vote in votes.items() if not vote]
        summary += f"- Yes ({len(yes_voters)}): {', '.join(yes_voters) if yes_voters else 'None'}\n"
        summary += f"- No ({len(no_voters)}): {', '.join(no_voters) if no_voters else 'None'}\n"
    
    return {
        "achieved": achieved,
        "agreement_ratio": agreement_ratio,
        "summary": summary,
        "votes": votes
    }


def extract_votes(messages: List[Dict[str, Any]]) -> Dict[str, bool]:
    """
    从消息中提取投票
    
    Args:
        messages: 消息列表
        
    Returns:
        投票字典，键为代理名称，值为投票(True/False)
    """
    votes = {}
    
    for message in messages:
        agent_name = message.get('agent_name', 'unknown')
        content = message.get('content', '')
        
        # 查找投票模式
        if 'vote:' in content.lower():
            if 'yes' in content.lower() or 'agree' in content.lower() or 'support' in content.lower():
                votes[agent_name] = True
            elif 'no' in content.lower() or 'disagree' in content.lower() or 'oppose' in content.lower():
                votes[agent_name] = False
    
    return votes


def calculate_deliberation_consensus(messages: List[Dict[str, Any]], 
                                  max_rounds: int = 10, 
                                  convergence_threshold: float = 0.85) -> Dict[str, Any]:
    """
    计算审议共识
    
    Args:
        messages: 消息列表
        max_rounds: 最大审议轮数
        convergence_threshold: 收敛阈值 (0-1)
        
    Returns:
        包含审议共识结果的字典
    """
    # 按轮次分组消息
    rounds = group_messages_by_rounds(messages)
    
    # 计算每轮的收敛度
    convergence_history = calculate_convergence(rounds)
    
    # 确定最终收敛度
    final_convergence = convergence_history[-1] if convergence_history else 0
    achieved = final_convergence >= convergence_threshold
    
    summary = f"Deliberation Consensus\n"
    summary += f"- Max Rounds: {max_rounds}\n"
    summary += f"- Convergence Threshold: {(convergence_threshold*100):.0f}%\n"
    summary += f"- Final Convergence: {(final_convergence*100):.1f}%\n"
    summary += f"- Result: {'ACHIEVED' if achieved else 'NOT ACHIEVED'}\n"
    
    summary += f"\nRound Progress:\n"
    for i, conv_score in enumerate(convergence_history):
        summary += f"- Round {i+1}: {(conv_score*100):.1f}% convergence\n"
    
    if not achieved and len(rounds) >= max_rounds:
        summary += f"\nNote: Max rounds reached without convergence.\n"
    
    return {
        "achieved": achieved,
        "agreement_ratio": final_convergence,
        "summary": summary,
        "convergence_history": convergence_history,
        "rounds_count": len(rounds)
    }


def group_messages_by_rounds(messages: List[Dict[str, Any]]) -> Dict[int, List[Dict[str, Any]]]:
    """
    按轮次对消息进行分组
    """
    rounds = {}
    
    for message in messages:
        content = message.get('content', '')
        
        # 查找轮次标记
        import re
        round_match = re.search(r'round:\s*(\d+)', content, re.IGNORECASE)
        
        if round_match:
            round_num = int(round_match.group(1))
            if round_num not in rounds:
                rounds[round_num] = []
            rounds[round_num].append(message)
        else:
            # 如果没有明确轮次标记，将所有消息放在第1轮
            if 1 not in rounds:
                rounds[1] = []
            rounds[1].append(message)
    
    return rounds


def calculate_convergence(rounds: Dict[int, List[Dict[str, Any]]]) -> List[float]:
    """
    计算轮次间的收敛度
    """
    convergence_scores = []
    round_numbers = sorted(rounds.keys())
    
    for i in range(1, len(round_numbers)):
        prev_round = rounds[round_numbers[i-1]]
        curr_round = rounds[round_numbers[i]]
        
        similarity = calculate_similarity_between_rounds(prev_round, curr_round)
        convergence_scores.append(similarity)
    
    # 如果只有一轮，收敛度为0
    if not convergence_scores:
        convergence_scores.append(0)
    
    return convergence_scores


def calculate_similarity_between_rounds(round_a: List[Dict[str, Any]], 
                                     round_b: List[Dict[str, Any]]) -> float:
    """
    计算两轮之间的相似度
    """
    if not round_a or not round_b:
        return 0
    
    # 提取立场
    stances_a = extract_stances(round_a)
    stances_b = extract_stances(round_b)
    
    if not stances_a or not stances_b:
        return 0
    
    # 比较立场
    matches = 0
    total = 0
    
    for agent, stance_a in stances_a.items():
        if agent in stances_b:
            total += 1
            if stance_a == stances_b[agent]:
                matches += 1
    
    return matches / total if total > 0 else 0


def extract_stances(messages: List[Dict[str, Any]]) -> Dict[str, str]:
    """
    从消息中提取立场
    """
    stances = {}
    
    for message in messages:
        agent_name = message.get('agent_name', 'unknown')
        content = message.get('content', '')
        
        # 查找立场标记
        import re
        stance_match = re.search(r'stance:\s*(support|oppose|neutral)', content, re.IGNORECASE)
        
        if stance_match:
            stances[agent_name] = stance_match.group(1).lower()
    
    return stances


def main():
    """
    主函数，处理命令行输入
    """
    if len(sys.argv) < 2:
        print("Usage: python consensus_skill.py <function_name> [json_input]")
        sys.exit(1)
    
    function_name = sys.argv[1]
    
    # 从stdin或命令行参数获取输入
    if len(sys.argv) > 2:
        input_data = json.loads(sys.argv[2])
    else:
        input_str = sys.stdin.read()
        input_data = json.loads(input_str)
    
    if function_name == "calculate_voting_consensus":
        result = calculate_voting_consensus(
            input_data.get("messages", []),
            input_data.get("threshold", 0.7)
        )
    elif function_name == "calculate_deliberation_consensus":
        result = calculate_deliberation_consensus(
            input_data.get("messages", []),
            input_data.get("max_rounds", 10),
            input_data.get("convergence_threshold", 0.85)
        )
    elif function_name == "extract_votes":
        result = extract_votes(input_data.get("messages", []))
    else:
        result = {"error": f"Unknown function: {function_name}"}
    
    print(json.dumps(result, ensure_ascii=False, indent=2))


if __name__ == "__main__":
    main()