import time
import json
from enum import Enum
from cacheout import LFUCache
from lib.client import AsyncRequestClient
from tornado.httputil import url_concat
from utils import Sign,ReadConf

clientCache = LFUCache() #运行时系统缓存
gateway = ReadConf("GATEWAY")
authConf = ReadConf("AUTH_SERVER")
GATEWAY_HOST = gateway.get("HOST")
GATEWAY_PORT = gateway.get("PORT")
PROTOVOL = gateway.get("PROTOVOL")
AUTH_HOST = authConf.get("HOST")
AUTH_PORT = authConf.get("PORT")
AUTH_PROTOVOL = authConf.get("PROTOVOL")



class ProxyOAuthV1(object):
    def __init__(self) -> None:
        self.httpClient = None
        self.signParam = {}
    
    def signatuer(self,signManger):
        pass
        # 签名认证
        '''keys = sorted(self.signParam.keys())
        key_str = "".join(keys)
        values_str = ""
        for key in keys:
            values_str += str(self.signParam[key])
        s = "{}{}".format(
            key_str,
            values_str.replace('\'', '').replace(' ', '').replace('\"', ''))
        # 加密
        signature_str1 = md5(s)
        # 加盐加密na
        signature_str = md5("NCSS-SASH-{}".format(signature_str1))
        return signature_str'''


    async def post(self, url, body, headers={}, timeOut=1):
        if not self.httpClient:
            raise RuntimeError("缺少http请求对象")
        signStr = self.signatuer()
        headers.update({"Authorization":f"Bearer {signStr}"})
        r = await self.httpClient.post(url, body, headers, timeOut)
        return r
    
    async def get(self,url, param, headers={}, timeOut=1):
        if not self.httpClient:
            raise RuntimeError("缺少http请求对象")
        signStr = self.signatuer()
        headers.update({"Authorization":f"Bearer {signStr}"})
        r = await self.httpClient.get(url, param, headers, timeOut)
        return r
    

class ProxyOAuthV2(ProxyOAuthV1):
    def __init__(self) -> None:
        super(ProxyOAuthV2,self).__init__()
        self.clientId = ""
        self.clientSecret = ""
        self.token = ""
        self.expiresAt = 0
        self.getAuthParamUrl = f"{AUTH_PROTOVOL}://{AUTH_HOST}:{AUTH_PORT}/api/v1/base/platform/dev/login/"

    async def RequestInit(self):
        self.clientId = clientCache.get("clientId")
        self.clientSecret = clientCache.get("clientSecret")
        self.expiresAt = clientCache.get("expiresAt")
        self.token = clientCache.get("token")
        if (not (self.clientId and self.clientSecret and self.expiresAt and self.token)) or (int(time.time()) >= self.expiresAt):
            login = {
                "account":"dev-001",
                "password":"tyxh@123"
            }
            r = await self.httpClient.post(self.getAuthParamUrl,login,1)
            data = json.loads(str(r.body, encoding='utf-8'))
            assert data["err_code"] == 0, f"{data['err_code']};MSG:{data['err_msg']}"
            loginInfo = data.get("data")
            if not loginInfo:
                raise RuntimeError("登录权限信息格式返回不正确")
            loginRes = loginInfo.get("login_res")
            if loginRes != 2:
                raise RuntimeError(f"登录失败:{loginRes}")
            self.clientId = loginInfo.get("client_id")
            self.clientSecret = loginInfo.get("client_secret")
            self.token = loginInfo.get("token")
            self.expiresAt = loginInfo.get("expires_at")
            clientCache.set_many({"clientId":self.clientId,"clientSecret":self.clientSecret,"expiresAt":self.expiresAt,"token":self.token})


class OAuthModeEnum(Enum):
    V1 = ProxyOAuthV1()
    V2 = ProxyOAuthV2()

class Proxy(object):
    def __init__(self):
        self._host = ""
        self._port = 0000

    @property
    def host(self):
        return

    @host.setter
    def host(self, value):
        self._host = value

    @property
    def port(self):
        return

    @port.setter
    def port(self, value):
        if not isinstance(value, int):
            return TypeError(f"端口必须是一个int:{value}")
        self._port = value

class PlatformProxy(Proxy):
    def __init__(self):
        super(PlatformProxy, self).__init__()
        self._sign = Sign()
        self._host = GATEWAY_HOST
        self._port = GATEWAY_PORT
        self._protocol = PROTOVOL
        self._client = AsyncRequestClient()  # 默认是异步请求连接对象
        self.headers = {
            "Dev-Type":"Terminal"
        }

    @property
    def client(self):
        return self._client

    @client.setter
    def client(self, value):
        value.host = self._host
        value.host = self._port
        self._client = value
    
    @property
    def protocol(self):
        return

    @protocol.setter
    def protocol(self, value):
        self._protocol = value

    def _json(self):
        if self._r["err_code"] != 0:
            raise RuntimeError(f"返回结果异常:{self._r['err_msg']}")
        return self._r["data"]

    async def load(self, api, body):
        self._sign.param = body
        signStr = self._sign.sign()
        params = dict(_time=str(int(time.time())))
        oathV2 = ProxyOAuthV2()
        oathV2.httpClient = AsyncRequestClient()
        oathV2.httpClient._headers.update({"Content-Type":"application/json"})
        await oathV2.RequestInit()
        self._client._headers = {
            "Authorization": f"Bearer {signStr}",
            "client-id":oathV2.clientId,
            "client-secret":oathV2.clientSecret,
            "token":oathV2.token
        }
        self._client._headers.update(self.headers)
        url = url_concat(f"{self._protocol}://{self._host}:{self._port}{api}", params)
        return url

    async def post(self, api, body, timeOut=1):
        url = await self.load(api, body)  # 代理处理完成获得完整url
        try:
            res = await self._client.post(url, body, timeOut)
            self._r = json.loads(str(res.body, encoding="utf-8"))
            return self._json()
        except Exception as e:
            raise RuntimeError(f"网关代理异常:{e}")

    