import asyncio
import time
from datetime import datetime

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

class Confirm(Init):
    def __init__(self, coin):
        method = "confirm"
        super().__init__(coin, method)

    def is_positive_integer(self, num):
        return isinstance(num, int) and num > 0

    # 查询当前所有满足查验要求的报块，即 <= 最高成熟高度 且 状态为待定(0)的报块
    async def query_need_update_data(self, mature_height):
        try:
            sql = f"SELECT height FROM {self.coin}_blkreportprofitv2 WHERE height <= ? AND state = ?;"
            data = await self.distribution.exec(sql, [mature_height, 0])
            if not data or len(data) == 0:
                print(f"{mature_height}高度之前暂无需要更新的报块")
                return False
            return [item['height'] for item in data]
        except Exception as err:
            raise err

    # 查询当前最高成熟高度，即当前最新高度 - MAX_MATURE
    async def query_maxture_height(self):
        try:
            if self.coin != "alph":
                now_height = await self.node.getblockcount()
                max_height = int(now_height) - self.MAX_MATURE
                if not self.is_positive_integer(max_height):
                    print(f"当前节点最大高度为{now_height}, 当前成熟高度为{max_height}")
                    return False
                else:
                    return max_height
            else:
                now = int(time.time() * 1000)
                max_mature_time = now - self.MAX_MATURE * 60 * 1000
                ymd = Times.utcTime(max_mature_time)
                sql = "SELECT MAX(height) AS max_height FROM alph_blkreportprofitv2 WHERE date <= ? AND state = ?;"
                data = await self.distribution.exec(sql, [ymd, 0])
                if not data[0]:
                    print("alph当前时间没有需要更新的成熟区块")
                    return False
                else:
                    return data[0]['max_height']
        except Exception as err:
            raise err

    # 通过报块地址，校验高度是否为本矿池报块
    async def verify_block(self, height):
        try:
            return await self.node.verify_block(height, self.REPORT_ADDRESS)
        except Exception as err:
            raise err

    # 根据校验通过和校验失败的高度更新blkreportprofit表，1为成功，2为失败
    async def update_blkreporprofit_state(self, suc_heights, err_heights):
        try:
            sql = f"UPDATE {self.coin}_blkreportprofitv2 SET state = ? WHERE height IN (?);"
            if len(err_heights) == 0 and len(suc_heights) != 0:
                # 只有 suc_heights 更新
                await self.distribution.exec_transaction(sql, [1, suc_heights])
            elif len(err_heights) != 0 and len(suc_heights) == 0:
                # 只有 err_heights 更新
                await self.distribution.exec_transaction(sql, [2, err_heights])
            elif len(err_heights) != 0 and len(suc_heights) != 0:
                # 同时更新 suc_heights 和 err_heights
                await asyncio.gather(
                    self.distribution.exec_transaction(sql, [1, suc_heights]),
                    self.distribution.exec_transaction(sql, [2, err_heights])
                )
            return
        except Exception as err:
            raise err

    """
    1，查验区块链最高成熟高度
    2，查验blk表中所有<=最高成熟高度 且 状态为待定(0)的区块
    3，遍历这些区块高度，并通过node.verify方法校验
    4，将校验通过(正常报块)和校验不通过(孤块)分为两组
    5，将正常报块组的状态改为1，将孤块组状态改为2
    """
    async def main(self):
        try:
            mature_max_height = await self.query_maxture_height()
            if not mature_max_height:
                return
            need_update_heights = await self.query_need_update_data(mature_max_height)
            if not need_update_heights:
                return
            suc_heights = []
            err_heights = []
            for item in need_update_heights:
                verify_result = await self.verify_block(item)
                if not verify_result:
                    err_heights.append(item)
                else:
                    suc_heights.append(item)
            await self.update_blkreporprofit_state(suc_heights, err_heights)
            return
        except Exception as err:
            raise err

# Assuming module export
__all__ = ['Confirm']