import sys
import jwt
import re

from log_config.logger import print_log
from middleware.database import validate_basic_auth, get_jwt_key
import config


def endpoint_exists(endpoint, endpoint_list):
    for item in endpoint_list:
        pattern = re.sub(r'{\w+}', r'w+', item)  # Replace path parameters with regex pattern
        if re.match(pattern, endpoint):
            return True
    return False


class Middleware:

    def auth(self, request):
        print_log('Middleware authentication', request.json.get('vendor') if request.json.get('vendor') else 'admin')
        try:
            if endpoint_exists(request.path, config.BASIC_AUTH_ROUTES) and endpoint_exists(request.path, config.JWT_AUTH_ROUTES):
                if 'HTTP_X_CLIENT_ID' and 'HTTP_X_CLIENT_SECRET' in request.environ:
                    client_id = request.environ['HTTP_X_CLIENT_ID']
                    client_secret = request.environ['HTTP_X_CLIENT_SECRET']
                    if validate_basic_auth(client_id, client_secret, request.remote_addr):
                        return True
                elif 'HTTP_AUTHORIZATION' in request.environ:
                    token = request.environ['HTTP_AUTHORIZATION'].replace('Bearer ', '')
                    vid = self.get_vendor_id(token)
                    jwt_key = get_jwt_key(vid)
                    if self.verify_jwt(token, jwt_key):
                        return True
                else:
                    return False
            if endpoint_exists(request.path, config.JWT_AUTH_ROUTES):
                if 'HTTP_AUTHORIZATION' in request.environ:
                    token = request.environ['HTTP_AUTHORIZATION'].replace('Bearer ', '')
                    vid = self.get_vendor_id(token)
                    jwt_key = get_jwt_key(vid)
                    if self.verify_jwt(token, jwt_key):
                        return True
                else:
                    return False
            elif endpoint_exists(request.path, config.BASIC_AUTH_ROUTES):
                if 'HTTP_X_CLIENT_ID' and 'HTTP_X_CLIENT_SECRET' in request.environ:
                    client_id = request.environ['HTTP_X_CLIENT_ID']
                    client_secret = request.environ['HTTP_X_CLIENT_SECRET']
                    if validate_basic_auth(client_id, client_secret, request.remote_addr):
                        return True
                else:
                    return False
            return True
        except jwt.ExpiredSignatureError:
            return False
        except jwt.InvalidSignatureError:
            return False
        except Exception as ex:
            print("Exception: " + repr(ex), file=sys.stderr)
            return False

    @staticmethod
    def get_vendor_id(token):
        payload = jwt.decode(token, options={"verify_signature": False})
        return payload['vendor_id']

    @staticmethod
    def verify_jwt(token, key):
        if jwt.decode(token, key, algorithms='HS512'):
            return True
        return False
