import json

from flask import Request, Response, send_file

from configs.firebase import SERVER_TIMESTAMP, db
from functions.Users import getUser

mimetype='application/json'
post_headers = {"Access-Control-Request-Methods": "POST, GET, OPTIONS, DELETE, PUT", "Access-Control-Request-Headers": "Content-Type, Authorization, x-uid", 'Access-Control-Allow-Origin': '*'}
import traceback


class API_Error(Exception):
    def __init__(self, message:str, status_code=500, meta={}) -> None:
        ''' New Error Instance '''
        self.message = message
        self.status_code = int(status_code)
        self.meta = meta
        super().__init__(self.to_dict())

    def to_dict(self):
        ''' dict Error object '''
        return dict(
            message=self.message,
            status_code = self.status_code,
            meta=self.meta
        )
    def to_json(self):
        ''' JSON serializable Error object '''
        return json.dumps(self.to_dict())
    
    def response(self):
        return Response(self.to_json(), status=self.status_code, headers=post_headers, mimetype=mimetype)


def sendResponse(function, request: Request, id=None, authRequired=True, sendFile=False):
    try:
        if request.method == "OPTIONS":
            return Response("", status=200, headers=post_headers, mimetype=mimetype)
        parameters = dict(request.args.to_dict())
        parameters.update(request.json if request.json else {})
        uid = request.headers.get('x-uid',request.headers.get('X-Uid'))
        currentUser = getUser(uid)
        if not currentUser and authRequired: raise API_Error("Authentication failed.", 401)
        parameters['currentUser'] = currentUser
        parameters['hostname'] = request.headers.get('domain-hostname')
        parameters['shopname'] = request.headers.get('shop-name')
        parameters['uid'] = uid
        if id:parameters['id'] = id
        if sendFile: return function(parameters)
        data  = function(parameters)
        return Response(json.dumps(data, default=str), 200, post_headers, mimetype=mimetype)
    except API_Error as e:
        print(e)
        print(traceback.format_exc())
        return e.response()
    except Exception as e:
        print(e)
        print(traceback.format_exc())
        return Response(json.dumps(dict(status=500, message='Internal Server Error', meta={"error": str(e)})), status=500, headers=post_headers, mimetype=mimetype)


# def authenticate(uid=None, auth_header=None) -> dict:
#     try:
#         if uid:
#             currentUser = auth.get_user(uid)
#         else:
#             currentUser = auth.verify_id_token(auth_header)
#     except Exception as e:
#         raise API_Error("Authentication failed.", 403, meta=dict(error=e))
#     return currentUser

def saveError(uid, functionName:str, userMessage:str, **kwargs):
    error = dict(
        createdAt=SERVER_TIMESTAMP,
        uid=uid,
        userMessage=userMessage,
        functionName=functionName,
        server='python'
    )
    error.update(kwargs)
    db.collection("LOGS").add(error)
    print("ERROR LOGGED",uid, functionName, userMessage)
    return error

def priorityLogger(uid, functionName:str, userMessage:str,serverMessage=None, **kwargs):
    error = dict(
        createdAt=SERVER_TIMESTAMP,
        uid=uid,
        userMessage=userMessage,
        functionName=functionName,
        server='python',
        serverMessage=serverMessage
    )
    error.update(kwargs)
    db.collection("PRIORITY_LOGS").add(error)
    print("ERROR LOGGED",uid, functionName, userMessage)
    return error