import re
import json

def extract_code_block(text):
    code_blocks = re.findall(r'```.*?\n(.*?)```', text, re.DOTALL)
    if not code_blocks:
        code_blocks = re.findall(r'```(.*?)```', text, re.DOTALL)
    return code_blocks

def extract_result_from_code_block(text):
    """从代码块中提取结果"""
    code_blocks = extract_code_block(text)
    if len(code_blocks) == 0:
        return None
    
    # 使用最后一个代码块
    content = code_blocks[-1].strip()
    
    # 检查是否是错误消息
    if content.startswith('"') and content.endswith('"'):
        # 移除引号
        return {"answer": content.strip('"')}
    
    try:
        # 尝试评估作为Python列表
        result = eval(content)
        if isinstance(result, list):
            return {"answer": result}
    except:
        pass
    
    return None

def can_move(board, moves, lang):
    K = len(board)
    goal_state = tuple(i for i in range(1, K*K+1))

    # 定义一个函数来执行移动
    def apply_move(state, move, lang):
        state = list(state)
        move_type = move[0]
        row_or_col = int(move[1]) - 1  # 将索引调整为从0开始
        steps = int(move[2]) % K       # 移动K步等于不移动
        if steps == 0:
            return tuple(state)
        if move_type == 'R':
            idx = row_or_col * K
            row = state[idx:idx+K]
            # 循环移动行
            row = row[steps:] + row[:steps]
            state[idx:idx+K] = row
        elif move_type == 'C':
            col = state[row_or_col::K]
            # 循环移动列
            col = col[steps:] + col[:steps]
            state[row_or_col::K] = col
        else:
            print(f"非法移动: {move}") if lang=='zh' else print(f"Out of the boundary: {move}")
            return False  # 超出边界时，返回无法完成
        return tuple(state)

    # 检查给定的路径
    def verify_path(start_state, moves):
        current_state = start_state
        for move in moves:
            current_state = apply_move(current_state, move, lang)
            if current_state is False:  # 如果移动不合法
                return False
        return current_state == goal_state

    flat_board = []
    for line in board:
        for item in line:
            flat_board.append(item)
    return verify_path(tuple(flat_board), moves)

def verify(pred, answer, meta):
    if isinstance(answer, str):
        try:
            answer = json.loads(answer)
        except json.JSONDecodeError:
            pass
    
    if isinstance(meta, str):
        meta = json.loads(meta)
    elif isinstance(meta, dict):
        pass
    else:
        raise ValueError('meta should be dict or str')
    
    lang = meta['language']
    
    # 从预测中提取结果，使用新的代码块提取函数
    result = extract_result_from_code_block(pred)
    if result is None:
        return 0
    
    # 检查无有效移动序列的情况
    invalid_markers = ["No valid sequence", "无有效", "不存在", "not exist"]
    
    # 检查答案是否表示无有效移动
    answer_str = str(answer) if isinstance(answer, (list, dict)) else answer
    answer_invalid = any(marker.lower() in answer_str.lower() for marker in invalid_markers)
    
    # 检查预测是否表示无有效移动
    result_str = str(result["answer"])
    result_invalid = any(marker.lower() in result_str.lower() for marker in invalid_markers)
    
    # 如果答案表示无有效移动，预测也表示无有效移动，则正确
    if answer_invalid and result_invalid:
        return 1
    # 如果答案表示无有效移动，但预测表示有有效移动，则错误
    elif answer_invalid and not result_invalid:
        return 0
    # 如果答案表示有有效移动，但预测表示无有效移动，则错误
    elif not answer_invalid and result_invalid:
        return 0
    
    # 处理有效移动序列的情况
    moves = result["answer"]
    if not isinstance(moves, list):
        return 0
    
    board = meta["question"]
    try:
        result = int(can_move(board, moves, lang))
        return result
    except Exception:
        return 0