import asyncio
from datetime import datetime
import time

# Assuming Times is a module with utcTime and bjTime functions
from public.times import Times
# Assuming Init is a base class
from init import Init

class Balance(Init):
    def __init__(self, coin):
        method = "balance"
        super().__init__(coin, method)

    async def query_min_height(self):
        try:
            sql = "SELECT MIN(max_height) AS min_height FROM wallet_in WHERE coin = ? AND state = ?;"
            result = await self.distribution.exec(sql, [self.coin, 0])
            return result
        except Exception as err:
            raise err

    async def query_transaction_state(self, height):
        try:
            sql = "SELECT * FROM sendinfo WHERE coin = ? AND height >= ?;"
            result = await self.balancedb.exec(sql, [self.coin, height])
            return result
        except Exception as err:
            raise err

    async def query_now_height(self, last_height):
        try:
            chain_height, db_height = await asyncio.gather(
                self.node.getblockcount(),
                self.query_min_height()
            )
            return chain_height > db_height[0]['min_height'] + self.MAX_MATURE and chain_height > last_height + 5
        except Exception as err:
            raise err

    async def update_wallet_in(self, ids):
        try:
            sql = "UPDATE wallet_in SET state = 1 WHERE id IN (?);"
            await self.distribution.exec_transaction(sql, [ids])
        except Exception as err:
            raise err

    async def insert_wallet_out_AND_update_wallet_in(self, data):
        try:
            sql = "INSERT INTO wallet_outv2(coin, user, address, date, max_height, tx_id, amount, tx_fee) VALUES "
            values = []
            id_list = []
            for item in data:
                username, qty, fee, txid, time_val, userid, height, ids = item['username'], item['qty'], item['fee'], item['txid'], item['time'], item['userid'], item['height'], item['ids']
                if txid:
                    id_list.extend(ids.split(","))
                    values.extend([self.coin, userid, username, Times.utcTime(time_val * 1000), height, txid, qty, fee])
                    sql += "(?,?,?,?,?,?,?,?), "
            if not values:
                print(f"{int(time.time() * 1000)}: {self.coin}无新增转账")
                return
            sql = sql[:-2]
            wallet_in_sql = "UPDATE wallet_in SET state = 1 WHERE id IN (?);"
            await asyncio.gather(
                self.distribution.exec_transaction(sql, values),
                self.distribution.exec_transaction(wallet_in_sql, [id_list])
            )
        except Exception as err:
            raise err

    async def main(self):
        try:
            min_height = await self.query_min_height()
            if not min_height or not min_height[0]['min_height']:
                print(f"{Times.bjTime(int(time.time() * 1000))}: {self.coin}无需要更新的数据")
                return True
            need_update_data = await self.query_transaction_state(min_height[0]['min_height'])
            if not need_update_data:
                print(f"{Times.bjTime(int(time.time() * 1000))}: {self.coin}钱包暂无转账信息")
                return True
            await self.insert_wallet_out_AND_update_wallet_in(need_update_data)
            return False
        except Exception as err:
            raise err

class DGBBlance(Init):
    def __init__(self, coin):
        method = "balance"
        super().__init__(coin, method)

    async def query_min_height(self):
        try:
            sql = "SELECT MIN(max_height) AS min_height FROM wallet_in WHERE coin LIKE 'dgb%' AND state = ?;"
            result = await self.distribution.exec(sql, [0])
            return result
        except Exception as err:
            raise err

    async def check_height(self):
        try:
            my_sql = """
            SELECT height FROM dgbs_blkreportprofitv2 WHERE date >= "2024-11-26 00:00:00" AND date < "2024-11-27 00:00:00"
            UNION
            SELECT height FROM dgbo_blkreportprofitv2 WHERE date >= "2024-11-26 00:00:00" AND date < "2024-11-27 00:00:00"
            UNION
            SELECT height FROM dgbq_blkreportprofitv2 WHERE date >= "2024-11-26 00:00:00" AND date < "2024-11-27 00:00:00";
            """
            balance_sql = "SELECT height FROM balanceinfo WHERE height > 20402916 AND height <= 20408691;"
            my_data, balance_data = await asyncio.gather(
                self.distribution.exec(my_sql),
                self.balancedb.exec(balance_sql)
            )
            my_result = [item['height'] for item in my_data]
            balance_result = [item['height'] for item in balance_data]
            only_in_array1 = [item for item in my_result if item not in balance_result]
            only_in_array2 = [item for item in balance_result if item not in my_result]
            difference = only_in_array1 + only_in_array2
            return difference
        except Exception as err:
            raise err

    async def query_now_height(self, last_height):
        try:
            sql = "SELECT MAX(max_height) AS max_height FROM wallet_in WHERE coin LIKE 'dgb%' AND state = ?;"
            chain_height, db_height = await asyncio.gather(
                self.node.getblockcount(),
                self.distribution.exec(sql, [0])
            )
            return chain_height > db_height[0]['max_height'] + self.MAX_MATURE and chain_height > last_height + 5
        except Exception as err:
            raise err

    async def query_transaction_state(self, height):
        try:
            sql = "SELECT * FROM sendinfo WHERE coin LIKE 'dgb%' AND height >= ?;"
            result = await self.balancedb.exec(sql, [height])
            return result
        except Exception as err:
            raise err

    async def query_coin(self, id_val):
        try:
            sql = "SELECT coin FROM wallet_in WHERE id = ?;"
            result = await self.distribution.exec(sql, [id_val])
            return result
        except Exception as err:
            raise err

    async def update_wallet_in(self, ids):
        try:
            sql = "UPDATE wallet_in SET state = 1 WHERE id IN (?);"
            await self.distribution.exec_transaction(sql, [ids])
        except Exception as err:
            raise err

    async def insert_wallet_out_AND_update_wallet_in(self, data):
        try:
            sql = "INSERT INTO wallet_outv2(coin, user, address, date, max_height, tx_id, amount, tx_fee) VALUES "
            values = []
            id_list = []
            for item in data:
                coin, username, qty, fee, txid, time_val, userid, height, ids = item['coin'], item['username'], item['qty'], item['fee'], item['txid'], item['time'], item['userid'], item['height'], item['ids']
                if txid:
                    id_list.extend(ids.split(","))
                    values.extend([coin, userid, username, Times.utcTime(time_val * 1000), height, txid, qty, fee])
                    sql += "(?,?,?,?,?,?,?,?), "
            sql = sql[:-2]
            wallet_in_sql = "UPDATE wallet_in SET state = 1 WHERE id IN (?);"
            await asyncio.gather(
                self.distribution.exec_transaction(wallet_in_sql, [id_list]),
                self.distribution.exec_transaction(sql, values)
            )
        except Exception as err:
            raise err

    async def main(self):
        try:
            min_height = await self.query_min_height()
            if not min_height or not min_height[0]['min_height']:
                print(f"{int(time.time() * 1000)}: dgb无需要更新的数据")
                return True
            need_update_data = await self.query_transaction_state(min_height[0]['min_height'])
            if not need_update_data:
                print(f"{int(time.time() * 1000)}: dgb转账未完成")
                return True
            data = []
            for item in need_update_data:
                username, qty, fee, txid, time_val, userid, height, ids = item['username'], item['qty'], item['fee'], item['txid'], item['time'], item['userid'], item['height'], item['ids']
                coin = await self.query_coin(ids.split(",")[0])
                data.append({
                    'coin': coin[0]['coin'],
                    'username': username,
                    'qty': qty,
                    'fee': fee,
                    'txid': txid,
                    'time': time_val,
                    'userid': userid,
                    'height': height,
                    'ids': ids
                })
            await self.insert_wallet_out_AND_update_wallet_in(data)
            return False
        except Exception as err:
            raise err

# Assuming module export
__all__ = ['Balance', 'DGBBlance']