from ..utils.text_to_latex  import conversion_functions
from ..utils import transfer_to_dict
from ujson import JSONDecodeError
from typing import Union

def converter(data: Union[dict, str]):
    if isinstance(data, list):
        res = []
        for d in data:
            converter(d)

    try:
        content_dict = transfer_to_dict(data)
    except (JSONDecodeError):
        # print("load err")
        # print(type(data))
        return data
    question = content_dict["caption"] if "caption" in content_dict else content_dict
    
    answer = content_dict.get("answer", None)
    types = (question['type'])
    
    print(f"type is {types}")
    
    try:
        if types =="wave":
            print(f"wave")
            print(conversion_functions.get(types))
        conversion_func = conversion_functions.get(types)
        print(f"con func is {conversion_func}")
        if conversion_func:
            print(f"yes")
            # maybe \\newline
            # return conversion_func(te).replace("[br]", "<br />")
            question_part = conversion_func(question)
        else:
            
            raise ValueError(f"No conversion function for type {types} found.")
    except Exception as e:
        #  print(f"error for {type(data)}")
        #  print(e)
        pass
    
    if not answer:
        # return 'error'
        try: 
            
            return question_part
        except:
            return "error"
    else:
        if answer_converter(answer):
            return question_part + answer_converter(answer)
        return question_part
    

def answer_converter(answer: dict):
    print(f"answer is {answer}")
    try:
        answer_dict = transfer_to_dict(answer)
    except (JSONDecodeError):
        # print("load err")
        # print(type(data))
        return answer

    
    if answer_dict:
        types = answer.get("type", None)
        print(f"answer type is {types}")
        try:
            conversion_func = conversion_functions.get(types)
            print(f"type is {types}")
            if conversion_func:
                # maybe \\newline
                # return conversion_func(te).replace("[br]", "<br />")
                print(f"start")
                print(f"ans dict is {answer_dict}")
                answer_part = conversion_func(answer_dict)
                return answer_part
            else:
                
                raise ValueError(f"No conversion function for type {types} found.")
        except Exception as e:
                #  print(f"error for {type(data)}")
                #  print(e)
            pass
        return []
    

def is_final_object(obj):
    if isinstance(obj, dict):
        print(f"is dict")
        for key, val in obj.items():
            if isinstance(val, dict):
                if 'type' in val:
                    return False
                if not is_final_object(val):
                    return False
    elif isinstance(obj, list):
        for item in obj:
            if isinstance(item, dict):
                if 'type' in item:
                    return False
                if not is_final_object(item):
                    return False
    return True
    

def render(obj):
    print(f"start re")
    if isinstance(obj, dict) and 'type' in obj and obj['type']:
        obj_type = obj['type'].lower()
        conversion_func = conversion_functions.get(obj_type)
        if conversion_func:
            print(f"{obj_type}", obj)
            # maybe \\newline
            # return conversion_func(te).replace("[br]", "<br />")
            question_part = conversion_func(obj)
            print(f"fi ")
            print(question_part)
            return question_part
        
    elif isinstance(obj, str):
        print(f"str is {obj}")
        return obj.replace("[br]", "\n")
    elif isinstance(obj, list):
        return " ".join(obj)
    else:
        return "Invalid object type"

def to_old_version(obj):
    if isinstance(obj, dict):
        if 'type' in obj:
            if obj['type'] in ['merge', 'equation', 'latexarray']:
                nobjs = [to_old_version(o) for o in obj['value']]
                obj['value'] = nobjs
                return obj
            elif obj['type'] in ['select', 'multiselect']:
                nobjs = [to_old_version(o) for o in obj['options']]
                obj['options'] = nobjs
                return obj
            elif obj['type'] in ['table', 'matrix', 'grid']:
                for col in obj['value']:
                    for i, row in enumerate(col):
                        col[i] = to_old_version(row)
                return obj
            else:
                for k, val in obj.items():
                    obj[k] = to_old_version(val)
                return obj
        else:
            nobjs = {}
            is_list = all(isinstance(k, int) for k in obj.keys())
            for k, o in obj.items():
                nobjs[k] = to_old_version(o)
            if is_list:
                return {'type': 'merge', 'value': list(nobjs.values())}
            else:
                return nobjs
    elif isinstance(obj, list):
        # 对列表中的每个值递归调用
        print("list")
        print([to_old_version(val) for val in obj])
        print(f"s")
        return [to_old_version(val) for val in obj]
    else:
        return obj


    
def c2(obj):
    if not obj:
        return ""
    print(f"obj type is {type(obj)}")
    # if not isinstance(obj, dict):
    #     try:
    #         obj = transfer_to_dict(obj)
    #     except (JSONDecodeError):
    #         # print("load err")
    #         # print(type(data))
    #         return obj 
    print(f"obj is {obj}")
    obj = to_old_version(obj)
    print(f"obj is {obj}")
    
    while True:
        current_obj = obj
        if is_final_object(obj):
            return render(obj)
        print(f"not final")
        found = False
        if isinstance(obj, dict):
            for key, val in current_obj.items():
                print("keys is", key)
                if not isinstance(val, dict):
                    continue
                if is_final_object(val):
                    print(f"true")
                    if 'type' in val:
                        print(f"key is {key}")
                        current_obj[key] = render(val)
                        print(f"cu is {current_obj}")
            else:
                current_obj = val
                found = True
                break
        elif isinstance(obj, list):
            l = len(obj)
            print(f"len is {l}")
            for i in range(l):
                current_obj[i] = render(current_obj[i])
            print(f"final obj i is {current_obj}")
                


        if not found:
            break

        if current_obj is obj:
            break
    print(f"type if {type(current_obj)}")
    print(f"obj before render is {current_obj}")
    print(current_obj)
    
    return render(current_obj)

def c_by_type(data: dict):
    print(f"data is  {data}")
    
    data_type = data.get("type")
    solution = transfer_to_dict(data.get("solution", ""))
    content = transfer_to_dict(data.get("content"))
    explains = transfer_to_dict(data.get("explains"))
    knowledge_point = data.get("knowledge_point", None)
    answer = content.get("answer", None)
    # Check for empty solutions in certain question types
    if data_type in [1, 2, 3] and not solution:
        errorMsg('填空答案错误')
        return

    # Check for empty content in single and multiple choice questions
    if data_type in [2, 3] and ('answer' not in content or not answer):
        errorMsg('单选题干错误')
        return

    # Initialize the structure to store the processed data
    json_data = {'type': data_type, 'solution': None, "caption": None}


    json_data["caption"] = c2(content["caption"])
    json_data["knowledge_point"] = knowledge_point

    if data_type == 1 or data_type =="填空":
        # Fill-in-the-blank
        answer_index = get_answer_index(content['caption'])
        answer_index_count = len(answer_index)

        json_data['solution'] = []
        for sk, s in enumerate(solution):
            if sk > (answer_index_count - 1):
                continue

            # if not validate_solution(s, qid):
            #     return

            # Process the solution based on its type
            # json_data['solution'].append(render_solution(s))# 
            # Todo: add render 
            json_data['solution'].append(s)

    elif data_type == 2:
        # Single choice
        print(solution)
        print(type(solution))
        if not solution[0]['value']:
            errorMsg('单选题答案为空')
            return

        json_data['option'] = c2(content['answer'])
        json_data['solution'] = solution[0]['value']

    elif data_type == 3:
        # Multiple choice
        if not solution[0]['value']:
            errorMsg('多选题答案为空')
            return

        json_data['option'] = c2(content['answer'])
        json_data['solution'] = solution[0]['value']

    elif data_type == 4:
        # Custom question type handling
        qq = {'type': data_type, 'content': content, 'solution': solution, 'explains': explains}
        
        splits = ttl_question_show_answer(qq)

        if solution and splits is False:
            print(f"json data is {json_data}")
            errorMsg('答案拆分失败, c_b_type')
            return

        # json_data['solution'] = process_splits_solution(splits)
        
        # Todo: add render
        json_data['solution'] = splits

    else:
        errorMsg('题目type错误')
        return
    
    invalid = ['略', '详见答案']
    try:
        ss = explains.get('解答设置')
    except:
        print("Ex is ",explains)
    if explains.get('解答设置') == 'same':
        json_data['explain'] = ''
    else:
        jieda = explains.get('解答')
        if jieda:
            jieda = jieda.strip() if isinstance(jieda, str) else jieda
            if isinstance(jieda, str) and jieda in invalid:
                json_data['explain'] = ''
            else:
                # 假设 LatexRender.to_html 是一个已定义的函数，用来转换 LaTeX 字符串为 HTML
                json_data['explain'] = c2(jieda)
        else:
            json_data['explain'] = ''

    return json_data

    
    
def errorMsg(msg, qid=1):
    print(f"Error in question {qid}: {msg}")

    

def get_answer_index(caption):
        if isinstance(caption, dict):
            index = []
            if 'index' in caption and 'type' in caption:
                index.append(caption)
            else:
                for key, value in caption.items():
                    if isinstance(value, dict) and 'index' in value and 'type' in value:
                        index.append(value)
                    elif isinstance(value, (dict, list)):
                        temp = get_answer_index(value)
                        if temp:
                            index.extend(temp)
            return index if index else False

        elif isinstance(caption, list):
            index = []
            for item in caption:
                if isinstance(item, dict) and 'index' in item and 'type' in item:
                    index.append(item)
                elif isinstance(item, (dict, list)):
                    temp = get_answer_index(item)
                    if temp:
                        index.extend(temp)
            return index if index else False
        
        
def ttl_question_show_answer(question, q_type=1, mode=0):
        if question['type'] != 4:
            return False

        splits = split_question(question['type'], question['content'], question['solution'], question['explains'], True, mode)
        if splits is False:
            return False

        return splits


def split_question(q_type, content, solution, explains, flag, mode):
    # Implementation of split_question method
    pass


def c_by_type_new(data: dict):
    print(f"data is  {data}")
    
    data_type = data.get("type")
    solution = transfer_to_dict(data.get("solution", ""))
    content = transfer_to_dict(data.get("content"))
    explains = transfer_to_dict(data.get("explain"))
    knowledge_point = data.get("knowledge_point", None)
    difficulty = data.get("difficulty", None)
    answer = content.get("answer", None)
    # Check for empty solutions in certain question types
    if data_type in [1, 2, 3] and not solution:
        errorMsg('填空答案错误')
        return

    # Check for empty content in single and multiple choice questions
    if data_type in [2, 3] and ('answer' not in content or not answer):
        errorMsg('单选题干错误')
        return

    # Initialize the structure to store the processed data
    json_data = {'type': data_type, 'solution': None, "caption": None}


    json_data["caption"] = c2(content["caption"])
    json_data["knowledge_point"] = knowledge_point
    json_data["difficulty"] = difficulty
    
    

    if data_type == 1:
        # Fill-in-the-blank
        answer_index = get_answer_index(content['caption'])
        answer_index_count = len(answer_index)

        json_data['solution'] = []
        for sk, s in enumerate(solution):
            if sk > (answer_index_count - 1):
                continue

            # if not validate_solution(s, qid):
            #     return

            # Process the solution based on its type
            # json_data['solution'].append(render_solution(s))# 
            # Todo: add render 
            json_data['solution'].append(s)

    elif data_type == 2:
        # Single choice
        print(solution)
        print(type(solution))
        if not solution[0]['value']:
            errorMsg('单选题答案为空')
            return

        json_data['option'] = c2(content['answer'])
        json_data['solution'] = solution[0]['value']

    elif data_type == 3:
        # Multiple choice
        if not solution[0]['value']:
            errorMsg('多选题答案为空')
            return

        json_data['option'] = c2(content['answer'])
        json_data['solution'] = solution[0]['value']

    elif data_type == 4:
        # Custom question type handling
        qq = {'type': data_type, 'content': content, 'solution': solution, 'explains': explains}
        
        splits = ttl_question_show_answer(qq)

        if solution and splits is False:
            print(f"ddd")
            print(f"json data is {json_data}")
            errorMsg('答案拆分失败')
            return

        # json_data['solution'] = process_splits_solution(splits)
        
        # Todo: add render
        json_data['solution'] = splits

    else:
        print(f"data type is {data_type}")
        errorMsg('题目type错误')
        return
    
    invalid = ['略', '详见答案']
    try:
        ss = explains.get('解答设置')
    except:
        print("Ex is ",explains)
    if explains.get('解答设置') == 'same':
        json_data['explain'] = ''
    else:
        jieda = explains.get('解答')
        if jieda:
            jieda = jieda.strip() if isinstance(jieda, str) else jieda
            if isinstance(jieda, str) and jieda in invalid:
                json_data['explain'] = ''
            else:
                # 假设 LatexRender.to_html 是一个已定义的函数，用来转换 LaTeX 字符串为 HTML
                json_data['explain'] = c2(jieda)
        else:
            json_data['explain'] = ''

    return json_data