import ujson
import psutil

from fastapi import Request, status
from fastapi.responses import PlainTextResponse, JSONResponse
from fastapi.middleware.cors import CORSMiddleware
import traceback

from AvenirCommon.Util import GB_traceback
from AvenirCommon.Authenticate import authorize_api_to_api, authentication_not_needed

from SpectrumCommon.Const.GB import *
from .ExceptionUtils import SpectrumException
from AvenirCommon.Logger import logger


def setup_middleware(app):
    app.add_middleware(
        CORSMiddleware,
        allow_origins=['*'],
        allow_credentials=True,
        allow_methods=["*"],
        allow_headers=["*"],
    )
    
    @app.middleware("http")
    async def authorize(request: Request, call_next):
        if (authorize_api_to_api(request, "AVENIR_SW_API_KEY")
        or authentication_not_needed(request)):
            return await call_next(request)
        else:
            return PlainTextResponse("UNAUTHORIZED", status_code=status.HTTP_401_UNAUTHORIZED)
        
        
def setup_exception_handler(app):
    @app.exception_handler(Exception)
    async def debug_exception_handler(request: Request, exc: Exception):
        msg = GB_traceback(exc)
        call_stack = traceback.format_exception(exc)

        errorLog = {
            "subsystem": "Inner System", 
            'cpuPercent': psutil.cpu_percent(), 
            'percentMemoryAvailable': 100 * (psutil.virtual_memory().available / psutil.virtual_memory().total),
            "call_stack": call_stack,
        }
            
        logger.error(ujson.dumps(errorLog))

        response = None

        if hasattr(exc, 'SWErrorCode'):
            content = exc.__dict__
            response = JSONResponse(content=content, status_code=exc.status_code)
        elif hasattr(exc, 'detail'):
            content = { "detail" : exc.detail, "message" : "Old error handler code", "SWErrorCode" : GB_SW_OLDERROR }
            response = JSONResponse(content=content, status_code=500)
        else:
            exc = SpectrumException(GB_SW_UNKNOWN, extra_info=exc.__dict__)
            if 'error' in msg:
                if type(msg['error']) == dict:
                    exc.extra_info = msg['error']
                else:
                    exc.extra_info = {'msg': msg['error']}

            content = exc.__dict__
            response = JSONResponse(content=content, status_code=exc.status_code)
            
        return response
        # return JSONResponse(content={"detail": "Uncaught exception status 500", "call_stack": call_stack }, status_code=500)
    
    
# @app.exception_handler(Exception)
# def debug_exception_handler(request: Request, exc: Exception):    
#     # msg = GB_traceback(exc)
#     # return PlainTextResponse(content=ujson.dumps(msg), media_type="application/json", status_code=msg['status'])

#     return PlainTextResponse(
#         "".join(traceback.format_exception(None, exc, exc.__traceback__)),
#         status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
    # )
