import json
from tqdm import tqdm
from itertools import permutations
import copy

def get_all_rankings(elements):
    if not elements:
        yield []
        return

    first = elements[0]
    rest = elements[1:]

    for ranking in get_all_rankings(rest):
        for i in range(len(ranking) + 1):
            yield ranking[:i] + [[first]] + ranking[i:]

        for i in range(len(ranking)):
            yield ranking[:i] + [ranking[i] + [first]] + ranking[i+1:]


def calculate_tov(compare_results, response_ids):
    min_changes = float('inf')

    for ranking in get_all_rankings(response_ids):
        current_changes = 0
        rank_map = {id: i for i, group in enumerate(ranking) for id in group}

        for comp in compare_results:
            id1 = comp['response_id_1']
            id2 = comp['response_id_2']
            result = comp['result']

            rank1 = rank_map[id1]
            rank2 = rank_map[id2]

            if rank1 < rank2:
                expected1 = id1
            elif rank2 < rank1: 
                expected1 = id2
            else: 
                expected1 = -1
            actual1 = result[0]

            if actual1 != expected1:
                if actual1 != -1 and expected1 != -1:
                    current_changes += 1
                else:
                    current_changes += 1
            
            expected2 = expected1
            
            actual2 = result[1]

            if actual2 != expected2:
                if actual2 != -1 and expected2 != -1:
                    current_changes += 1
                else:
                    current_changes += 1

        min_changes = min(min_changes, current_changes)

    return min_changes


def process_json_file(input_path, output_path, error_log_path):
    try:
        with open(input_path, 'r', encoding='utf-8') as f:
            data = json.load(f)
    except FileNotFoundError:
        print(f"Error: The file {input_path} was not found.")
        return
    except json.JSONDecodeError:
        print(f"Error: The file {input_path} contains invalid JSON.")
        return

    new_data = []
    error_ids = []
    response_ids = [1, 2, 3, 4]

    for sample in tqdm(data, desc="Processing samples"):
        new_sample = copy.deepcopy(sample)
        has_minus_two = False

        for comp in new_sample.get('compare_results', []):
            if -2 in comp.get('result', []):
                has_minus_two = True
                break

        if has_minus_two:
            new_sample['IPI'] = -1.0
            new_sample['TOV'] = -1
            error_ids.append(str(new_sample['id']))
        else:
            D = 0
            for comp in new_sample.get('compare_results', []):
                r1, r2 = comp.get('result', [0, 0])
                if r1 == r2:
                    D += 1
                elif r1 != r2 and (r1 == -1 or r2 == -1):
                    D += 0
            ipi = (15 - D) / 15.0
            new_sample['IPI'] = ipi

            tov = calculate_tov(new_sample.get('compare_results', []), response_ids)
            new_sample['TOV'] = tov

        new_data.append(new_sample)

    try:
        with open(output_path, 'w', encoding='utf-8') as f:
            json.dump(new_data, f, indent=4)
        print(f"\nSuccessfully created the new JSON file at: {output_path}")
    except IOError as e:
        print(f"Error writing to {output_path}: {e}")

    try:
        with open(error_log_path, 'w', encoding='utf-8') as f:
            for error_id in error_ids:
                f.write(error_id + '\n')
        if error_ids:
            print(f"IDs with '-2' have been logged in: {error_log_path}")
        else:
            print("No samples with '-2' were found.")
    except IOError as e:
        print(f"Error writing to {error_log_path}: {e}")


if __name__ == '__main__':
    INPUT_FILE = 'xxx'
    OUTPUT_FILE = 'xxx'
    ERROR_FILE = 'xxx'
    
    process_json_file(INPUT_FILE, OUTPUT_FILE, ERROR_FILE)