import os
import json
import functools
from fastapi import Request
from fastapi.responses import JSONResponse
from pvmlib.fork.actions import Actions
from aiohttp import ClientSession

class MsManager:
    @staticmethod
    def Forks(func):
        @functools.wraps(func)
        def wrapper(*args, **kwargs):
            return func(*args, **kwargs)
        return wrapper

    @staticmethod
    def Create(configs, ctx=[]):
        def decorator(func):
            @functools.wraps(func)
            async def wrapper(request: Request, data, *args, **kwargs):
                
                data = {}
                response = {}
                headers = {}

                for key, value in request.headers.items():
                    headers.pop("host", None)
                    headers.update({key: value})

                body_bytes = await request.body()
                if body_bytes:
                    body_json = json.loads(body_bytes)
                    data.update(body_json)
                
                if request.query_params:
                    data.update(request.query_params)

                async with ClientSession() as session:
                    for config in configs:
                        fork_conf = func.__globals__['confFork']().get(config['fork'])
                        if fork_conf:
                            app = fork_conf['App']
                            endpoint = fork_conf['EndPoint']
                            version = fork_conf['Version']
                            url_base = os.environ.get('URL_ENDPOINT_SERVICES', None)
                            url = f"{url_base}/{app}/api/{version}/{endpoint}"
                            query = fork_conf.get('Query', None)
                            
                            action_map = {
                                Actions.POST: lambda: session.post(url, json=data, headers=headers),
                                Actions.GET: lambda: session.get(format_query_params(data, query, url), headers=headers),
                                Actions.UPDATE: lambda: session.put(url, json=data, headers=headers),
                                Actions.DELETE: lambda: session.delete(url, headers=headers)
                            }
                            
                            action = action_map.get(config['action'])
                            if action is None:
                                continue

                            async with action() as response:
                                if response is None:
                                    continue

                                data_response = await response.json()

                                if response.status != 200:
                                    return JSONResponse(status_code=response.status, content=data_response)

                                fnc_name = config['fnc']
                                if fnc_name in func.__globals__:
                                    fnc = func.__globals__[fnc_name]
                                    data = fnc(data, data_response)
                                
                                data.update(data_response['data'])

                return await func(request, data, *args, **kwargs)
            return wrapper
        return decorator

def format_query_params(data, keys, url):
    query_params = []
    for key in keys.split(","):
        if key in data:
            query_params.append(f"{key}={data[key]}")
    
    if query_params:
        url += "?" + "&".join(query_params)
    return url