from datetime import datetime, timedelta

from mower.solvers.fight import FightSolver
from mower.solvers.fight.battle_choose import BattleChooseSolver
from mower.solvers.navigation import NavigationSolver
from mower.utils import config
from mower.utils.email import send_message
from mower.utils.graph.utils import SceneGraphSolver
from mower.utils.log import logger
from mower.utils.scene import Scene


class CopyWorksSolver(SceneGraphSolver):
    solver_name = "自动抄作业列表"

    def run(self):
        self.conf = config.conf.work
        config.load_works()
        self.select_data = {}
        if self.conf.intelligent_select:
            self.init_select_data()

        while works := self.conf.works:
            for i in range(len(works)):
                logger.info(
                    f"自动战斗列表：({i + 1}/{len(works)}) 关卡：{works[i].stage} 剩余重试次数：{works[i].retry_times}"
                )
            work = works[0]
            copilot = config.works[work.stage]
            opers = [oper.model_dump(exclude_none=True) for oper in copilot.opers]
            groups = [group.model_dump(exclude_none=True) for group in copilot.groups]
            actions = [
                action.model_dump(exclude_none=True) for action in copilot.actions
            ]
            self.level_name = work.stage
            self.no_potion = False
            self.success = False
            while work.retry_times + 1 > 0:
                if (
                    self.scheduler_stop_time
                    and self.scheduler_stop_time - datetime.now() < timedelta(minutes=3)
                ):
                    return False
                super().run()
                if self.no_potion:
                    break
                if self.level_name in self.select_data:
                    logger.debug(f"智能选择干员 {self.select_data}")
                    data = self.select_data[self.level_name]
                    BattleChooseSolver().run(
                        data["opers"], data["groups"], self.conf.squad, False
                    )

                if not FightSolver().run(
                    self.level_name, opers, groups, actions, self.conf.squad
                ):
                    work.retry_times -= 1
                else:
                    works.pop(0)
                    self.success = True
                    break
            config.save_conf()
            if self.success:
                continue
            elif work.retry_times < 0:
                msg = f"关卡{work.stage}重试次数已用完,请检查相关作业与干员配置"
                logger.info(msg)
                send_message(msg, level="error")
            break
        return True  # 已清空作业列表|没体力|重试次数用完

    def init_select_data(self):
        works = self.conf.works
        i = 0
        while i < len(works):
            all_opers = set()
            all_groups = set()
            data = self.select_data[works[i].stage] = {}
            j = i
            while j < len(works):
                copilot = config.works[works[j].stage]
                updated_opers = all_opers | set(copilot.opers)
                updated_groups = all_groups | {
                    group
                    for group in copilot.groups
                    if any(oper not in updated_opers for oper in group.opers)
                }

                if len(updated_opers) + len(updated_groups) > 12:
                    break
                all_opers, all_groups = updated_opers, updated_groups
                j += 1
            i = j
            data["opers"] = [oper.model_dump(exclude_none=True) for oper in all_opers]
            data["groups"] = [
                group.model_dump(exclude_none=True) for group in all_groups
            ]

    def transition(self):
        if (scene := self.scene()) == Scene.OPERATOR_RECOVER_POTION:
            if self.conf.use_medicine:
                logger.info("体力不足，使用理智药")
                self.tap((1635, 865))
                self.sleep(1)
                return
            else:
                logger.info("体力不足，未设置使用理智药")
                self.no_potion = True
                return True
        elif scene == Scene.OPERATOR_RECOVER_ORIGINITE:
            logger.info("体力不足，没有理智药")
            self.no_potion = True
            return True
        elif scene == Scene.OPERATOR_SELECT:
            return True
        elif scene == Scene.OPERATOR_BEFORE:
            if self.level_name.endswith("#"):
                if self.find("ope_ex_mode"):
                    self.tap("ope_ex_mode")
                    return
                self.tap("ope_ex_start")
                return

            self.tap("ope_start")
        elif scene in self.waiting_scene:
            self.waiting_solver()
        else:
            NavigationSolver().run(self.level_name, mode="copy")
