import json
from utils import dateTimeToString, isDateTimeInstance
from autoload import localData
from flask import request, g
import re
import storage
import dynamic_functions
from cloudwatch_logger import print_log


def callback_function(function, data):
    if isinstance(data, dict):
        arg = get_args(function.get("arg"), data)
    else:
        arg = get_args(function.get("arg"), data[0])
    func_name = remove_function(function.get("call"))
    # Try to get function from dynamic_functions module
    func = dynamic_functions.get_function(func_name) or getattr(dynamic_functions, func_name, None)
    if func is None:
        raise NameError(f"Function '{func_name}' not found in dynamic_functions module")
    result = func(*arg)
    return result


def remove_function(function):
    head, sep, tail = function.partition("(")
    return head


def get_args(args, value):
    arg_values = []
    for arg in args:
        if isinstance(arg, bool):
            arg_values.append(arg)
        elif arg is None:
            arg_values.append(None)
        elif "db." in arg:
            date = value[arg.replace("db.", "")]
            if isDateTimeInstance(date):
                date = dateTimeToString(date)
            arg_values.append(date)
        elif "fun." in arg:
            func_name = arg.replace("fun.", "")
            # Try to get function from dynamic_functions module
            function_to_call = dynamic_functions.get_function(func_name) or getattr(dynamic_functions, func_name, None)
            if function_to_call is None:
                raise NameError(f"Function '{func_name}' not found in dynamic_functions module")
            result = function_to_call()
            arg_values.append(result)
        elif "sys.input." in arg:
            payload = g.payload
            result = payload.get(arg.replace("sys.input.", ""))
            arg_values.append(result)
        elif "s3." in arg:
            if isinstance(value, dict):
                arg_values.append(value.get(arg.replace("s3.", "")))
            else:
                arg_values.append(value)
        elif "sys.config." in arg:
            result = localData['dataConfig'][arg.replace("sys.config.", "")]
            arg_values.append(result)
        else:
            arg_values.append(arg)
    return arg_values


def load_from_S3(details):
    misc = details.get("misc")
    file_data = None
    req_applicant_type = request.json.get("applicant_type", 1)
    for file_type in misc:
        config_applicant_type = file_type.get("applicant_type")
        if config_applicant_type is not None and str(config_applicant_type) != str(req_applicant_type):
            continue

        type_name = file_type.get("type")
        _file = file_type.get("file")
        if "{" in _file:
            var_name = get_value_from_variable(_file)
            for var in var_name:
                if var in request.json:
                    _file = _file.replace("{" + var + "}", str(request.json.get(var)))
        try:
            file_data = storage.getFile(_file)
            if file_data:
                print_log(f"{type_name} Found")
                return file_data
        except Exception as e:
            return {}
    return file_data



def get_value_from_variable(text):
    matches = re.findall(r"\{(.*?)}", text)
    unique_matches = list(set(matches))
    return unique_matches


def check_if_rejection(rules_dict):
    policy_names = rules_dict.keys()
    if any("rejection" in policy for policy in policy_names):
        return True
    return False