import random
from typing import List, Dict

def shuffle_question_options(question_text, options_dict, correct_answer_key):
    """
    Shuffle options while maintaining correct answer text
    Returns: shuffled_options_dict, correct_answer_key
    """
    if not isinstance(options_dict, dict) or len(options_dict) < 2:
        return options_dict, correct_answer_key
    
    # Get the correct answer text
    correct_answer_text = options_dict.get(correct_answer_key, "")
    
    # Get all option values
    option_values = list(options_dict.values())
    
    # Shuffle the values
    random.shuffle(option_values)
    
    # Create new options dict with shuffled values
    option_keys = sorted(options_dict.keys())
    shuffled_options = {key: option_values[i] for i, key in enumerate(option_keys)}
    
    # Find new key for correct answer
    new_correct_key = correct_answer_key
    for key, value in shuffled_options.items():
        if value == correct_answer_text:
            new_correct_key = key
            break
    
    return shuffled_options, new_correct_key


def shuffle_questions_options_batch(questions_data):
    """
    Shuffle options for multiple questions while avoiding consecutive same correct positions
    Returns: list of questions with shuffled options
    """
    if not questions_data:
        return []
    
    shuffled_questions = []
    last_two_positions = []
    
    for data in questions_data:
        options_dict = data.options
        correct_answer_key = data.correct_answer
        
        if not isinstance(options_dict, dict) or len(options_dict) < 2:
            # Can't shuffle, keep original
            shuffled_questions.append({
                "question": data.question,
                "options": [{"key": k, "value": v} for k, v in options_dict.items()],
                "level": data.difficulty,
                "correct_answer": correct_answer_key,
                "ques_id": data.id
            })
            continue
        
        # Get correct answer text
        correct_answer_text = options_dict.get(correct_answer_key, "")
        
        # Get all option keys and values
        option_keys = sorted(options_dict.keys())
        option_values = list(options_dict.values())
        
        # Find current correct answer position
        try:
            correct_index = option_values.index(correct_answer_text)
        except ValueError:
            # Correct answer not found, keep original
            shuffled_questions.append({
                "question": data.question,
                "options": [{"key": k, "value": v} for k, v in options_dict.items()],
                "level": data.difficulty,
                "correct_answer": correct_answer_key,
                "ques_id": data.id
            })
            continue
        
        # Determine positions to avoid
        positions_to_avoid = set()
        if len(last_two_positions) >= 2:
            # If last 2 questions had same correct position, avoid it
            if last_two_positions[-1] == last_two_positions[-2]:
                positions_to_avoid.add(last_two_positions[-1])
        
        # Get valid positions
        valid_positions = [i for i in range(len(option_values)) if i not in positions_to_avoid]
        
        if not valid_positions:
            valid_positions = list(range(len(option_values)))
        
        # Choose random position
        new_correct_index = random.choice(valid_positions)
        
        # Shuffle values
        shuffled_values = option_values.copy()
        shuffled_values[correct_index], shuffled_values[new_correct_index] = \
            shuffled_values[new_correct_index], shuffled_values[correct_index]
        
        # Create new options dict
        shuffled_options = {key: shuffled_values[i] for i, key in enumerate(option_keys)}
        
        # Find new correct key
        new_correct_key = correct_answer_key
        for key, value in shuffled_options.items():
            if value == correct_answer_text:
                new_correct_key = key
                break
        
        # Track position
        last_two_positions.append(new_correct_index)
        if len(last_two_positions) > 2:
            last_two_positions.pop(0)
        
        shuffled_questions.append({
            "question": data.question,
            "options": [{"key": k, "value": v} for k, v in shuffled_options.items()],
            "level": data.difficulty,
            "correct_answer": new_correct_key,
            "ques_id": data.id
        })
    
    return shuffled_questions


def randomize_correct_options(questions: List[Dict]) -> List[Dict]:
    """
    Randomize correct answer positions to avoid consecutive same options.
    
    Args:
        questions: List of question dicts with 'options' array and 'answer' text
        
    Returns:
        List of questions with shuffled options
    """
    if not questions:
        return questions
    
    randomized_questions = []
    last_two_positions = []  # Track last 2 correct positions
    
    for question in questions:
        options = question.get('options', [])
        correct_answer = question.get('answer', '')
        
        if len(options) < 2 or not correct_answer:
            # Skip if not enough options or no correct answer
            randomized_questions.append(question)
            continue
        
        # Find current correct answer index
        try:
            current_correct_index = options.index(correct_answer)
        except ValueError:
            # Correct answer not found in options, skip this question
            randomized_questions.append(question)
            continue
        
        # Determine which positions to avoid
        positions_to_avoid = set()
        if len(last_two_positions) >= 2:
            # If last 2 questions had same correct position, avoid it
            if last_two_positions[-1] == last_two_positions[-2]:
                positions_to_avoid.add(last_two_positions[-1])
        elif len(last_two_positions) == 1:
            # For second question, can use any position
            pass
        
        # Get available positions (excluding positions to avoid)
        valid_positions = [i for i in range(len(options)) if i not in positions_to_avoid]
        
        # If all positions are blocked (shouldn't happen), use all positions
        if not valid_positions:
            valid_positions = list(range(len(options)))
        
        # Choose random position from valid positions
        new_correct_index = random.choice(valid_positions)
        
        # Create new options array with swapped positions
        new_options = options.copy()
        
        # Swap correct answer to new position
        new_options[current_correct_index], new_options[new_correct_index] = \
            new_options[new_correct_index], new_options[current_correct_index]
        
        # Update question with new options
        updated_question = question.copy()
        updated_question['options'] = new_options
        updated_question['answer'] = new_options[new_correct_index]
        
        randomized_questions.append(updated_question)
        
        # Track this position for next iteration
        last_two_positions.append(new_correct_index)
        if len(last_two_positions) > 2:
            last_two_positions.pop(0)  # Keep only last 2
    
    return randomized_questions


def randomize_correct_options_simple(questions: List[Dict]) -> List[Dict]:
    """
    Simple version: Just shuffle options for each question randomly.
    Ensures variety in correct answer positions across questions.
    
    Args:
        questions: List of question dicts with 'options' array and 'answer' text
        
    Returns:
        List of questions with shuffled options
    """
    if not questions:
        return questions
    
    randomized_questions = []
    
    for question in questions:
        options = question.get('options', [])
        correct_answer = question.get('answer', '')
        
        if len(options) < 2 or not correct_answer:
            randomized_questions.append(question)
            continue
        
        # Create a copy of options and shuffle
        shuffled_options = options.copy()
        random.shuffle(shuffled_options)
        
        # Update question with shuffled options
        updated_question = question.copy()
        updated_question['options'] = shuffled_options
        # Answer text remains same, just position changes
        updated_question['answer'] = correct_answer
        
        randomized_questions.append(updated_question)
    
    return randomized_questions