import os
import sys
import json
import tiktoken
from radon.complexity import cc_visit
from concurrent.futures import ProcessPoolExecutor, as_completed
# Add the pipeline/ directory to sys.path
script_dir = os.path.dirname(os.path.abspath(__file__))
pipeline_root = os.path.abspath(os.path.join(script_dir, ".."))
sys.path.insert(0, pipeline_root)
from app.search.search_utils import remove_line_numbers


def str2list(input_str):
    """
    Change the input str into a list
    """
    str_list = input_str.split('\n')
    for ele in str_list:
        ele += '\n'
    return str_list


def list2str(input_list):
    """
    Change the input list into a string
    """
    return ''.join(input_list)


def get_cyclomatic_complexity(function_code: str) -> int | None:
    try:
        blocks = cc_visit(function_code)
        if not blocks:
            print('blocks is empty')
            return None
        # Return the highest block's complexity (there should only be one for a single function)
        return blocks[0].complexity
    except Exception as e:
        print(f"Failed to compute complexity: {e}")
        return None


def cal_token_num(func_body: str, model_name = "gpt-4"):
    enc = tiktoken.encoding_for_model(model_name)
    return len(enc.encode(func_body))


def sort_tokenlen_complexity(ref_dataset_path):
    result_list: list[dict] = []
    with open(ref_dataset_path, 'r') as f:
        ref_dataset = json.load(f)
    for prj_name, tasks in ref_dataset.items():
        if (prj_name != 'seaborn'):
            continue
        for task_id, task_info in tasks.items():
            prompt_len = len(task_info['prompt'])
            func_body_list = task_info['full_function'][prompt_len:]
            func_body_str = list2str(func_body_list)
            func_body_str = remove_line_numbers(func_body_str)
            token_len = cal_token_num(func_body_str)
            full_func_str = remove_line_numbers(list2str(task_info['full_function']))
            complexity = get_cyclomatic_complexity(full_func_str)
            # print(f'func_body_str:\n{func_body_str}\ntoken_len: {token_len}\ncomplexity: {complexity}\n')
            result = {
                'project_name': prj_name,
                'task_id': task_id,
                'token_len': float(token_len),
                'complexity': float(complexity) if complexity is not None else None
            }
            result_list.append(result)

    sorted_by_token = sorted(result_list, key=lambda x: x['token_len'])
    sorted_by_complexity = sorted(result_list, key=lambda x: (x['complexity'] is not None, x['complexity'] or 0))
    
    repocod_token_len_file = 'pipeline/Test_Analysis/repocod_token_len.json'
    repocod_complexity_file = 'pipeline/Test_Analysis/repocod_complexity.json'
    with open(repocod_token_len_file, 'w') as f:
        json.dump(sorted_by_token, f, indent=2)
    with open(repocod_complexity_file, 'w') as f:
        json.dump(sorted_by_complexity, f, indent=2)


def find_pass_selected_tests(TASK_ROOT_FOLDER):
    all_task = 0
    pass_task = 0
    for prj_name in os.listdir(TASK_ROOT_FOLDER):
        prj_folder = os.path.join(TASK_ROOT_FOLDER, prj_name)
        for prj_id in os.listdir(prj_folder):
            prj_id_folder = os.path.join(prj_folder, prj_id)
            log_path = os.path.join(prj_id_folder, 'nohup_output.log')
            if not os.path.exists(log_path):
                continue
            with open(log_path, 'r') as f:
                log_content = f.read()
            if 'Patch decision: yes' in log_content and 'PASSED! We picked the test' in log_content:
                pass_task += 1
            else:
                print(f'{prj_id} failed to pass test cases.')
            all_task += 1
    print(f'all_task: {all_task}, pass_task: {pass_task}')

            
            

    

if __name__ == "__main__":
    ref_dataset_path = 'REPOCOD/ref_dataset.json'
    TASK_ROOT_FOLDER = 'REPOCOD/Tasks4Agents'
    # sort_tokenlen_complexity(ref_dataset_path)
    find_pass_selected_tests(TASK_ROOT_FOLDER)
    # seaborn_1 failed to pass test cases.
    # seaborn_13 failed to pass test cases.
    # seaborn_14 failed to pass test cases.
    # seaborn_19 failed to pass test cases.
    # seaborn_23 failed to pass test cases.
    # seaborn_24 failed to pass test cases.
    # seaborn_36 failed to pass test cases.
    # seaborn_39 failed to pass test cases. no test parsed
    # seaborn_40 failed to pass test cases. no test parsed
    # seaborn_50 failed to pass test cases.
    # seaborn_58 failed to pass test cases.
    


