import json
import configparser
# import mysql.connector
from flask import current_app
import pymysql
from pymssql import Cursor

from vo.ProxyInfo import ProxyInfo
from vo.LoginInfo import LoginInfo


class Conn(object):
    def __init__(self, conn):
        self._conn: pymysql.Connect = conn

    def close(self) -> None:
        '''
        关闭游标对象和连接对象
        :param:NULL
        :return:None
        '''
        if self._conn is not None:
            self._conn.close()

    def genDict(self,oCursor: Cursor) -> {}:
        ret={}
        try:
            i = -1
            for field in oCursor.description:
                i = i + 1
                ret[field[0]] = i
        except Exception as err:
            print('error:', err)
        return ret

    # 获取所有proxy
    def proxyGetAll(self) -> Cursor:
        '''
        执行SQL语句
        :param sqlstring: Sql语句
        :return: 返回结果
        '''
        cursor: Cursor = None
        try:
            sql = "SELECT id, proxy FROM caiji.clb_proxy"
            cursor = self._conn.cursor()
            cursor.execute(sql)
        except Exception as err:
            print('error:', err)
        return cursor

    # 获取下一个proxy
    def proxyGetNext(self, id: int)->ProxyInfo:
        '''
        执行SQL语句
        :param sqlstring: Sql语句
        :return: 返回结果
        '''
        ret: ProxyInfo = None
        sql = "SELECT id, proxy FROM caiji.clb_proxy where id>" + str(id) + " order by id asc limit 1"
        try:
            cursor = self._conn.cursor()
            cursor.execute(sql)
            results = cursor.fetchall()
            if cursor.rowcount>0:
                ret = ProxyInfo()
                fields = self.genDict(cursor)
                for row in results:
                    ret.id = row[fields["id"]]
                    sProxy = row[fields["proxy"]]
                    proxyInfos = sProxy.split('-')
                    ret.ip = proxyInfos[0]
                    ret.port = proxyInfos[1]
                    ret.user_name = proxyInfos[2]
                    ret.user_passwd = proxyInfos[3]
            cursor.close()
        except Exception as err:
            print('error:', err)
        return ret

    # 获取一个空闲账号
    def userGetFree(self, userGroup: str, id: int) -> LoginInfo:
        """
        执行SQL语句
        :param userGroup:
        :return: 返回结果
        """
        ret: LoginInfo = None
        sql = f"SELECT * FROM caiji.login_info where user_group='{userGroup}' and id > {id} and login_time is null order by id asc limit 1"
        try:
            cursor = self._conn.cursor()
            cursor.execute(sql)
            results = cursor.fetchall()
            if cursor.rowcount>0:
                ret = LoginInfo()
                fields = self.genDict(cursor)
                for row in results:
                    ret.id = row[fields["id"]]
                    ret.user_group = row[fields["user_group"]]
                    ret.user_name = row[fields["user_name"]]
                    ret.user_passwd = row[fields["user_passwd"]]
            cursor.close()
        except Exception as err:
            print('error:', err)
        return ret

    # 清除24小时未主动退出(异常退出)的用户的登录状态，
    def userClearLoginStateIn24H(self):
        '''
        执行SQL语句
        :param sqlstring: Sql语句
        :return: 返回结果
        '''
        sql = "update caiji.login_info set login_time=null where TIME_TO_SEC(TIMEDIFF(now(), login_time))>86400"
        try:
            cursor = self._conn.cursor()
            cursor.execute(sql)
            self._conn.commit()
        except Exception as err:
            print('error:', err)

    # 主动退出登录状态，退出后下次可继续使用，可能需要满足一定的条件
    def userSetLoginStateByID(self, id: int):
        '''
        执行SQL语句
        :param id:
        :return: 返回结果
        '''
        sql = "update caiji.login_info set login_time=now() where id=" + str(id)
        try:
            cursor = self._conn.cursor()
            cursor.execute(sql)
            self._conn.commit()
        except Exception as err:
            print('error:', err)

    # 主动退出登录状态，退出后下次可继续使用，可能需要满足一定的条件
    def userClearLoginStateByID(self, id: int):
        '''
        执行SQL语句
        :param id:
        :return: 返回结果
        '''
        sql = "update caiji.login_info set login_time=null where id=" + str(id)
        try:
            cursor = self._conn.cursor()
            cursor.execute(sql)
            self._conn.commit()
        except Exception as err:
            print('error:', err)

    def doSelectByColumns(self, tbname: str, *columns: str) -> list:
        '''
        通过列名进行Select查询
        :param tbname: 表名
        :param columns: 需要查询的列名
        :return: 查询结果
        '''
        col = str(columns).replace("[", "").replace("]", "").replace("'", "").replace("(", "").replace(")", "")
        sqlstring = f"select {col} from {tbname} "
        if len(columns) == 0: sqlstring = f"select *from {tbname}"
        self._cursor.execute(sqlstring)
        strjson = self.transToJson(self._cursor)
        return strjson

    def doSelectWhere(self, tbname: str, where: str) -> list:
        '''
        通过where子句表达式进行Select查询
        :param tbname: 表名
        :param expression:where子句
        :return: 查询结果
        '''
        sqlstring = f"select *from {tbname} where {where}"
        self._cursor.execute(sqlstring)
        strjson = self.transToJson(self._cursor)
        return strjson

    def doInsertRecord(self, tbname: str, *values) -> None:
        '''
        通过全部字段值新增数据到表
        :param tbname: 表名
        :param values: 所有字段的值
        :return: None
        '''
        vls = str(values).replace("[", "").replace("]", "")
        sqlstring = f"insert into {tbname} values {vls}"
        print(sqlstring)
        self._cursor.execute(sqlstring)
        self._conn.commit()

    def doInsertByKV(self, tbname: str, **keyvalues) -> None:
        '''
        通过 字段名=值 的键值对新增记录
        :param tbname: 表名
        :param keyvalues: 字段名=值的字典
        :return: None
        '''
        keys = str(keyvalues.keys()).replace("dict_keys", "").replace("'", "").replace("[", "").replace("]", "")
        values = str(keyvalues.values()).replace("dict_keys", "").replace("[", "").replace("]", "")
        sqlstring = f"insert into {tbname} {keys} values {values}"
        self._cursor.execute(sqlstring)
        self._conn.commit()

    def doDeleteByKV(self, tbname: str, **keyvalues) -> None:
        '''
        通过 字段名=值 的方式查找到对于键值对并删除
        :param tbname: 表名
        :param keyvalues: 键值对
        :return: None
        '''
        keys = list(keyvalues.keys())
        values = list(keyvalues.values())
        pairs = []
        for i in range(len(keys)):
            pairs.append(f"{keys[i]}={values[i]}")
            pairs.append("and")  # 使用and连接词
        del pairs[len(pairs) - 1]  # 删除最后一个and连接词
        pairs = str(pairs).replace("[", "").replace("]", "").replace("'", "").replace(",", "")
        sqlstring = f"delete from {tbname} where {pairs}"
        self._cursor.execute(sqlstring)
        self._conn.commit()

    def doDeleteWhere(self, tbname: str, where: str) -> None:
        '''
        通过where表达式进行查询并删除
        :param tbname: 表名
        :param expression:表达式
        :return: None
        '''
        sqlstring = f"delete from {tbname} where {where}"
        self._cursor.execute(sqlstring)
        self._conn.commit()

    def doUpdateKV(self, tbname: str, expression: str, **keyvalues) -> None:
        '''
        通过expression表达式找到数据后对 字段名=值 进行修改
        :param tbname: 表名
        :param expression:where表达式
        :param keyvalues: 修改的字段名=值对
        :return: None
        '''
        keys = list(keyvalues.keys())
        values = list(keyvalues.values())
        keypairs = []
        for i in range(len(keys)):
            temp = f"{keys[i]}=\"{(values[i])}\""
            keypairs.append(temp)
        keypairs = str(keypairs).replace("[", "").replace("]", "").replace("'", "")
        sqlstring = f"update {tbname} set {keypairs} where {expression}"
        self._cursor.execute(sqlstring)
        self._conn.commit()

    # 执行返回单值的操作，适用于返回行计数等
    def selectCount(self, sqlstring):
        cnt = self._cursor.execute_scalar(sqlstring)
        return cnt

    # 获取标题，以及标题类型字典
    def MSSQL_GetTitleDict(self, cursor):
        titleDict = {}
        for rows in cursor.get_header():
            titleDict[rows[0]] = rows[1]
        # 如果调用conn完成后千万记得，要吧连接关闭。
        return titleDict

    def createtable(self, tbname: str, *args: list) -> None:
        '''
        通过List创建新表格
        比如createtable("TB_TestTbale",["ID","nchar(10)"],["Password","nchar(20)","NOT NULL"])
        每个字段用一个list表示 顺序为 [字段名,类型名,*约束，*其他]
        :param tbname: 表格名称
        :param args: 参数
        :return:None
        '''
        data = []
        for i in range(len(args)):
            temp = str(args[i]).replace("[", "").replace("]", "").replace("'", "").replace(",", "")
            data.append(temp)
        data = str(data).replace("[", "(").replace("]", ")").replace("'", "")
        sqlstring = f"create table {tbname} {data}"
        self._cursor.execute(sqlstring)
        self._conn.commit()


class ConnMySql(Conn):
    def __init__(self):
        oConn: pymysql.Connect = None
        try:
            oConn = pymysql.Connect(
                host=current_app.config["db.host"],
                user=current_app.config["db.user"],
                passwd=current_app.config["db.passwd"],
                db=current_app.config["db.db"],
                port=int(current_app.config["db.port"]),
                charset=current_app.config["db.charset"]
            )
        except Exception as err:
            print('error:', err)
        Conn.__init__(self, oConn)

class MySqlTemp(Conn):
    def __init__(self):
        oConn: pymysql.Connect = pymysql.Connect(
            host="114.115.159.144",
            user="caiji",
            passwd="zzsn9988",
            db="caiji",
            port=3306,
            charset="utf8"
        )
        Conn.__init__(self, oConn)
# 测试
# conn=MySqlTemp()
# o=conn.userGetFree("wenshu")
# print (o.user_name)

# for row in results:
#     id = row[0]
#     proxy = row[1]
#     print(id, proxy)
#     proxyInfos=proxy.split('-')
#     for i in range(0,4): #proxyInfos:
#         print("----",proxyInfos[i])
