import base64
import contextvars
import json
import logging

import requests
from cachetools import TTLCache
from cryptography.fernet import Fernet
from fastapi import Request
from starlette.middleware.base import BaseHTTPMiddleware

logger = logging.getLogger("uvicorn.info")
# 每个请求独立的 headers 存储容器
user_api_key_setting_ctx = contextvars.ContextVar("user_api_key_setting", default={})
user_api_key_cache = TTLCache(maxsize=1000, ttl=60 * 3)


class EnvCipher:
    _fernet = Fernet("eTqwN75IVksW4Ef5dv3dhQpP-1LedATSUf186hzhLqE=")

    @classmethod
    def encrypt(cls, plaintext: str) -> str:
        token = cls._fernet.encrypt(plaintext.encode("utf-8"))
        return base64.urlsafe_b64encode(token).decode("utf-8")

    @classmethod
    def decrypt(cls, ciphertext: str) -> str:
        token = base64.urlsafe_b64decode(ciphertext.encode("utf-8"))
        return cls._fernet.decrypt(token).decode("utf-8")


class UserApiSettingMiddleware(BaseHTTPMiddleware):
    async def dispatch(self, request: Request, call_next):
        # 获取当前请求的 headers 信息
        header = dict(request.headers)
        token = header.get('authorization')
        if token:
            # 根据capspace token 获取对应的api key配置信息
            user_api_key_setting_ctx.set(get_capsapce_user_api_setting(token))
        response = await call_next(request)
        return response


def get_capsapce_user_api_setting(token: str):
    if token in user_api_key_cache:
        return user_api_key_cache.get(token)
    else:
        user_api_key = dict()
        # 从远程服务获取用户api_key并放入缓存
        remote_url = "http://47.100.251.14:9099/prod-api/internal/datasource/user/connections/with-credentials"
        remote_result = requests.get(remote_url, headers={"Accept": "application/json", "Authorization": token}).json()
        if remote_result['code'] == 200:
            credentials = remote_result['data']['credentials']
            for key, value in credentials.items():
                payload_value = value['payload']
                credential = json.loads(EnvCipher.decrypt(payload_value))
                if credential['credentials']:
                    for cre_key, cre_val in credential['credentials'].items():
                        user_api_key[cre_key] = cre_val
        else:
            raise RuntimeError(f"获取用户数据权限异常,异常信息:{remote_result['message']}")
        user_api_key_cache[token] = user_api_key
        return user_api_key
