# coding: utf-8

from __future__ import absolute_import
from __future__ import division
from __future__ import print_function
from __future__ import unicode_literals

import os
import json

from werkzeug.wrappers import Response

from . import utils

__author__ = "asaka <lan@leancloud.rocks>"


APP_ID = os.environ.get("LEANCLOUD_APP_ID")
APP_KEY = os.environ.get("LEANCLOUD_APP_KEY")
ANDX_KEY = os.environ.get("LEANCLOUD_APP_ANDX_KEY")
MASTER_KEY = os.environ.get("LEANCLOUD_APP_MASTER_KEY")
HOOK_KEY = os.environ.get("LEANCLOUD_APP_HOOK_KEY")


_ENABLE_TEST = False
current_environ = None


class AuthorizationMiddleware(object):
    def __init__(self, app):
        self.app = app

    def __call__(self, environ, start_response):
        if _ENABLE_TEST:
            global current_environ
            current_environ = environ

        self.parse_header(environ)
        app_params = environ["_app_params"]
        if not any(app_params.values()):  # all app_params's value is None
            self.parse_body(environ)

        unauth_response = Response(
            json.dumps({"code": 401, "error": "Unauthorized."}),
            status=401,
            mimetype="application/json",
        )
        if app_params["id"] is None:
            return unauth_response(environ, start_response)
        if (APP_ID == app_params["id"]) and (
            app_params["key"] in [MASTER_KEY, APP_KEY, ANDX_KEY]
        ):
            return self.app(environ, start_response)
        if (APP_ID == app_params["id"]) and (app_params["master_key"] == MASTER_KEY):
            return self.app(environ, start_response)

        return unauth_response(environ, start_response)

    @classmethod
    def parse_header(cls, environ):
        request = environ["leanengine.request"]

        app_id = (
            request.headers.get("x-avoscloud-application-id")
            or request.headers.get("x-uluru-application-id")
            or request.headers.get("x-lc-id")
        )
        app_key = (
            request.headers.get("x-avoscloud-application-key")
            or request.headers.get("x-uluru-application-key")
            or request.headers.get("x-lc-key")
        )
        session_token = (
            request.headers.get("x-uluru-session-token")
            or request.headers.get("x-avoscloud-session-token")
            or request.headers.get("x-lc-session")
        )
        master_key = request.headers.get("x-uluru-master-key") or request.headers.get(
            "x-avoscloud-master-key"
        )
        hook_key = request.headers.get("x-lc-hook-key")

        if app_key and ",master" in app_key:
            master_key, _ = app_key.split(",")
            app_key = None

        if app_key is None:
            request_sign = request.headers.get(
                "x-avoscloud-request-sign"
            ) or request.headers.get("x-lc-sign")
            if request_sign:
                request_sign = request_sign.split(",") if request_sign else []
                sign = request_sign[0].lower()
                timestamp = request_sign[1]
                # if len(request_sign) == 3 and request_sign[2] == 'master':
                #     key = MASTER_KEY
                # else:
                #     APP_KEY
                # if sign == utils.sign_by_key(timestamp, key):
                #     app_key = key
                if len(request_sign) == 3:
                    if (request_sign[2] == "master") and (
                        sign == utils.sign_by_key(timestamp, MASTER_KEY)
                    ):
                        master_key = MASTER_KEY
                    elif (request_sign[2] == "ax-sig-1") and (
                        sign == utils.sign_by_key(timestamp, ANDX_KEY)
                    ):
                        app_key = ANDX_KEY
                elif sign == utils.sign_by_key(timestamp, APP_KEY):
                    app_key = APP_KEY

        environ["_app_params"] = {
            "id": app_id,
            "key": app_key,
            "master_key": master_key,
            "session_token": session_token,
            "hook_key": hook_key,
        }

    @classmethod
    def parse_body(cls, environ):
        request = environ["leanengine.request"]
        if (not request.content_type) or ("text/plain" not in request.content_type):
            return

        body = json.loads(request.get_data(as_text=True))

        environ["_app_params"]["id"] = body.get("_ApplicationId")
        environ["_app_params"]["key"] = body.get("_ApplicationKey")
        environ["_app_params"]["master_key"] = body.get("_MasterKey")
        environ["_app_params"]["session_token"] = body.get("_SessionToken")
