"""公共函数"""
import base64
import os

import jwt
from flask import jsonify, current_app, request
import json
import decimal
import time
import requests
from livekit import AccessToken, VideoGrant
from sqlalchemy import or_, and_

from configs.config import SDK_CONFIG_URL, SDK_CONFIG_APPSECRET, SDK_CONFIG_APPID, client, Bucket, env, SecretKey, Region, UPLOAD_FOLDER
from src.libs.db_link import LinkMysql
from src.libs.log_utils import Logger
from src.modules.friend import FriendComment, FriendGive

# 时间戳转成字符串
def time_to_datetime(sp):
    import datetime
    str_time = time.strftime("%Y-%m-%d %H:%M:%S", time.localtime(sp))
    datetime_time = datetime.datetime.strptime(str_time, '%Y-%m-%d %H:%M:%S')
    return datetime_time


# str到datetime
def str_to_datetime(str_time):
    import datetime
    datetime_time = datetime.datetime.strptime(str_time, '%Y-%m-%d %H:%M:%S')
    return datetime_time


# todo Decimal 类型json
class DecimalEncoder(json.JSONEncoder):
    def default(self, res):
        if isinstance(res, decimal.Decimal):
            return float(res)
        super(DecimalEncoder, self).default(res)


def check_float(string):
    """判断是否正小数和正正数"""
    # 支付时，输入的金额可能是小数，也可能是整数
    s = str(string)
    if s.count('.') == 1:  # 判断小数点个数
        sl = s.split('.')  # 按照小数点进行分割
        left = sl[0]  # 小数点前面的
        right = sl[1]  # 小数点后面的
        if left.startswith('-') and left.count('-') == 1 and right.isdigit():
            lleft = left.split('-')[1]  # 按照-分割，然后取负号后面的数字
            if lleft.isdigit():
                return False
            elif left.isdigit() and right.isdigit():
                # 判断是否为正小数
                return True
            elif s.isdigit():
                s = int(s)
                if s != 0:
                    return True
    return False


def paginate_info(paginate):
    """分页信息"""
    result = {
        'total': paginate.total,
        'page': paginate.page,
        'max_page': paginate.pages,
    }
    return result


def my_paginate_info(paginate, items):
    """自定义分页信息"""
    result = {
        'total': paginate.total_count,
        'page': paginate.current_page,
        'max_page': paginate.max_pages,
        'items': items
    }
    return result


def result_format_decimal(data):
    if data is None:
        data = ''
    rdata = json.dumps(data, cls=DecimalEncoder)
    rdata_dict = json.loads(rdata)
    r = {
        'data': rdata_dict,
    }
    return jsonify(r)


def result_format(code: object = 200, data: object = None, **kwargs):
    if data is None:
        data = ''

    if isinstance(data, decimal.Decimal):
        return str(data)
    r = {
        'code': code,
        'data': data,
        **kwargs
    }
    return jsonify(r)


def logger(data):
    """记录错误与日志公用方法"""

    basedir = os.path.abspath(os.path.dirname(__file__))
    basedir = basedir.rsplit('/libs', 1)[0] + '/log.txt'
    f = open(basedir, 'a+')
    f.write(data + '\n')
    f.close()
    return True


def return_table_field(table_items, info_items, replace_filed, get_info_id, get_info_filed):
    """
    :param table_items: 列表数据源，也是替换好返回的字典
    :param info_items: 用来替换的数据源
    :param replace_filed: 要替换数据的字典key名称
    :param get_info_id:用来比对数据字典的key名称
    :param get_info_filed: 用户替换字典数据的数据的key名称
    :return:
    """
    res = []
    for item in table_items:
        item[replace_filed] = ''
        for info_item in info_items:
            if item['%s_id' % replace_filed] == info_item[get_info_id]:
                item[replace_filed] = info_item[get_info_filed]

        res.append(item)
    return res


def branch_secret_key(items, level):
    """返回分支的秘钥公用秘钥"""
    secret_key = ''
    for item in items:
        if item['user_level_id'] == level:
            secret_key = item['secret_key']
    return secret_key


def serialization_tuple(items, fileds_list):
    """
        格式化orm对应，对应的数据
        items list数据
        fileds_list 对应字段名称
    """
    res = []
    for item in items:
        line = {}
        for i in range(len(fileds_list)):
            line[fileds_list[i]] = item[i]
        res.append(line)
    return res


def time_to_str(timeStamp):
    if timeStamp == 0:
        return ''
    timeArray = time.localtime(timeStamp)
    date_str = time.strftime("%Y-%m-%d %H:%M:%S", timeArray)
    return date_str


# str到时间戳
def str_to_time(str_time):
    import datetime
    datetime_time = datetime.datetime.strptime(str_time, '%Y-%m-%d %H:%M:%S')
    res = datetime_to_time(datetime_time)
    return res


# todo datetime -> time
def datetime_to_time(dtime):
    if dtime == None:
        return 0
    un_time = time.mktime(dtime.timetuple())
    return int(un_time)


def trans_str(data):
    data_str = {}
    for i, j in data.items():
        if isinstance(j, list):
            j = [str(s) for s in j]
            data_str[i] = j
        elif isinstance(j, dict):
            j = {key: str(value).replace("'", '"') for key, value in j.items()}
            data_str[i] = j
        else:
            data_str[i] = str(j).replace("'", '"')
    return data_str


def GetToken(room, create_user):
    """
    获取token
    """
    grant = VideoGrant(room_join=True, room=room, room_create=True, room_list=True, room_record=True, room_admin=True)
    access_token = AccessToken(SDK_CONFIG_APPID, SDK_CONFIG_APPSECRET, grant=grant, identity=create_user,
                               name=create_user)
    token = "Bearer " + access_token.to_jwt()
    return token


def GetRoomList(token, names):
    """
    获取房间列表信息
    """
    url = SDK_CONFIG_URL + '/twirp/livekit.RoomService/ListRooms'
    headers = {
        "Authorization": token,
        "Content-Type": "application/json"
    }
    names = names.split()
    data = {
        "names": names
    }
    response = requests.post(url=url, headers=headers, json=data)
    return response.text


def DeleteRoom(token, room):
    """
    删除房间
    """
    url = SDK_CONFIG_URL + '/twirp/livekit.RoomService/DeleteRoom'
    # room = room.split()
    headers = {
        "Authorization": token,
        "Content-Type": "application/json"
    }
    data = {
        "room": room
    }
    response = requests.post(url=url, headers=headers, json=data)

    return response.text


def CreateRoom(token, name, max_participants, empty_timeout, user_ids):
    """
    新建房间
    """
    url = SDK_CONFIG_URL + '/twirp/livekit.RoomService/CreateRoom'
    headers = {
        "Authorization": token,
        "Content-Type": "application/json"
    }
    data = {
        "name": name,
        "metadata": user_ids,
        "max_participants": max_participants,
        "empty_timeout": empty_timeout
    }
    response = requests.post(url=url, headers=headers, json=data)
    Logger().logger.info(f"新建房间结果；{response.status_code}")
    return response.text


def create_token(username, id, secret='temp'):
    """
    生成token
    """
    from datetime import datetime
    ip = request.remote_addr
    payload = {
        'name': username,
        'ip': ip,
        'id': id,
        'iat': datetime.now().strftime("%Y-%m-%d %H:%M:%S")
    }
    encoded = jwt.encode(payload, secret, algorithm='HS256')
    return encoded


def GetParticipantlist():
    """
    获取参与者信息
    """
    url = SDK_CONFIG_URL + '/twirp/livekit.RoomService/ListParticipants'
    headers = {
        "Authorization": 'Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ2aWRlbyI6eyJyb29tQ3JlYXRlIjp0cnVlLCJyb29tSm9pbiI6dHJ1ZSwicm9vbUxpc3QiOnRydWUsInJvb21SZWNvcmQiOnRydWUsInJvb21BZG1pbiI6dHJ1ZSwicm9vbSI6Ilx1NGUwMFx1NTNmN1x1NmQ0Ylx1OGJkNSJ9LCJpc3MiOiJBUElnU0JvczZ0ckVUSGEiLCJuYmYiOjE2ODEyNzA3NzQsImV4cCI6MTY4MTI5MjM3NCwic3ViIjoiMjMyMzIiLCJuYW1lIjoiMjMyMzIifQ.qv7BS3xp3EhkO9W7bu2rWBLF8-bz67XhOo9Iq88hMV4',
        "Content-Type": "application/json"
    }
    data = {
        "room": '一号测试'
    }
    response = requests.post(url=url, headers=headers, json=data)
    print(response.text)
    return response.text


from datetime import datetime


def get_now_timestamp():
    """
    获取现在时间
    """
    time_array = datetime.now().strftime('%Y-%m-%d %H:%M:%S')
    return time_array


def get_timestamp():
    """
    获取现在时间戳
    """
    time_str = get_now_timestamp()
    time_array = time.strptime(time_str, "%Y-%m-%d %H:%M:%S")
    time_stamp = int(time.mktime(time_array))
    return time_stamp


def create_folder():
    """
    时间创建文件
    """
    time_array = datetime.now().strftime('%Y-%m-%d')
    return time_array


def upload_file(file_strem, file_name):
    """
    字节流上传到cos地址
    """
    dir_to_create = create_folder() + '/' + f'{file_name}'
    response = client.put_object(
        Bucket=Bucket,
        Key=dir_to_create,
        Body=file_strem
    )
    if response is None:
        print("上传成功")
    return dir_to_create


def frame_truncation(file_name):
    """视频截帧"""
    response = client.get_snapshot(
        Bucket=Bucket,
        Key=file_name,
        Time='6',
        Width='480',
        Format='png'
    )
    name = file_name.split("/")[1].split('.mp4')[0] + '.png'
    file_path = os.path.join(UPLOAD_FOLDER, f'{name}')
    response['Body'].get_stream_to_file(file_path)
    return file_path, name


def upload_file_body(file_strem, file_name):
    """
    文件上传到cos地址
    """
    name = file_name.split('.mp4')[0] + '.png'
    dir_to_create = create_folder() + '/' + f'{name}'
    response = client.upload_file(
        Bucket=Bucket,
        Key=dir_to_create,
        LocalFilePath=file_strem
    )
    if response is None:
        print("上传成功")
    return dir_to_create


def children_comment(fcmid, uid):
    result = []
    fs = []
    friend_data = FriendComment.query.filter(or_(and_(FriendComment.status != 1,
                                             FriendComment.fcmid == int(fcmid)),
                                             and_(FriendComment.uid == int(uid),
                                             FriendComment.fcmid == int(fcmid))
                                                 )).all()
    for infos in friend_data:
        d = infos.serialization()
        d['status'] = infos.status
        result.append(d)
    ds = sorted(result, key=lambda x: x['review_to'] if x['review_to'] else 0, reverse=True)
    datas = one_tree_comment(ds, fs)
    Logger().logger.info(f'朋友圈评论返回：{datas}')
    return datas


def one_tree_comment(data, fs):
    kong = []
    for s in data:
        uid = s.get("uid")
        sql = f"SELECT nickname,user_avatar_file_name,bg_image,energy_ball_image FROM `missu_users`  where user_uid='{uid}'"
        friend_info = ''
        if s.get("review_to") != None:
            friend_info = FriendComment.query.filter(FriendComment.review_to == s.get("review_to"),
                                                     FriendComment.fcmid == s.get("fcmid"),
                                                     ).first()
        user_info = LinkMysql(env.BUSINESS).query_mysql(sql)
        if friend_info:
            s['review_to_uid'] = friend_info.uid
            s['review_to_nicke_name'] = user_info[0].get("nickname", "")
            s['review_user_avatar_file_name'] = user_info[0].get("user_avatar_file_name", "")
            s['review_bg_image'] = user_info[0].get("bg_image", "")
        else:
            s['review_to_uid'] = ''
            s['review_to_nicke_name'] = ''
            s['review_user_avatar_file_name'] = ''
            s['review_bg_image'] = ''
        s['nick_name'] = user_info[0].get("nickname", "")
        s['create_time'] = str_to_time(s.get("create_time", ""))
        s['user_avatar_file_name'] = user_info[0].get("user_avatar_file_name", "")
        s['bg_image'] = user_info[0].get("bg_image", "")
        s['energy_ball_image'] = user_info[0].get("energy_ball_image", "")
        kong.append(s)
    return kong


def list_give(fcmid, uid):
    result = []
    friend_data = FriendGive.query.filter(FriendGive.status == 0, FriendGive.fcmid == fcmid).all()
    for infos in friend_data:
        user_data = infos.serialization()
        uid = user_data.get("uid")
        sql = f"SELECT nickname,user_avatar_file_name,bg_image FROM `missu_users`  where user_uid='{uid}'"
        user_info = LinkMysql(env.BUSINESS).query_mysql(sql)
        user_data['nick_name'] = user_info[0].get("nickname", "")
        user_data['user_avatar_file_name'] = user_info[0].get("user_avatar_file_name", "")
        user_data['bg_image'] = user_info[0].get("bg_image", "")
        result.append(user_data)
    return result


from Crypto.Cipher import AES


def AES_Decrypt(data):
    """
    解密
    """
    unpad = lambda s: s[:-ord(s[len(s) - 1:])]
    key = "koukuai012345678".encode('utf8')
    data = base64.b64decode(data)
    cipher = AES.new(key, AES.MODE_ECB)

    # 去补位
    text_decrypted = unpad(cipher.decrypt(data))
    text_decrypted = text_decrypted.decode('utf8')
    return text_decrypted


def AES_Encrypt(data):
    """加密"""
    pad = lambda s: s + (16 - len(s) % 16) * chr(16 - len(s) % 16)
    key = "koukuai012345678".encode('utf8')
    # 字符串补位
    data = pad(data)
    cipher = AES.new(key, AES.MODE_ECB)
    # 加密后得到的是bytes类型的数据，使用Base64进行编码,返回byte字符串
    result = cipher.encrypt(data.encode())
    encodestrs = base64.b64encode(result)
    enctext = encodestrs.decode('utf8')
    return enctext


def call_im_interface(aes):
    url = f"{env.JAVA_PATH}/rest_post"
    try:
        result = requests.post(url=url, data=aes)
    except Exception as e:
        Logger().logger.info(f'请求IM接口失败：{e}')
        return {}
    return result


def query_is_check():
    """查看后台是否免审核"""
    sql = "select value from missu_system_config where menu_name='FriendsReview'"
    is_examine = LinkMysql(env.BUSINESS).query_mysql(sql)
    if not is_examine:
        return 0
    value = is_examine[0]['value']
    if not value:
        return 0
    return 1
