from datetime import datetime

from mower.solvers.fight.mixin import FightMixin
from mower.utils import config
from mower.utils.graph import SceneGraphSolver
from mower.utils.log import logger
from mower.utils.scene import Scene
from mower.utils.tile_pos import Calc, find_level

from .sss_drop import SSSDROPSolver


class SSSFightSolver(SceneGraphSolver, FightMixin):
    solver_name = "保全战斗"

    def run(
        self,
        level_name: str,
        strategies: list,
        draw_as_possible: bool,
        actions: list,
        retry_times: int,
        deadline: datetime = None,
    ):
        """
        Args:
            level_name: 关卡名
            strategies: 策略列表
            draw_as_possible: 调配干员好了就点
            actions: 行动列表
            retry_times: 重试次数，超过返回，结束保全
            deadline: 截止时间
        """
        logger.info(f"关卡：{level_name}")
        logger.info("地图坐标计算：https://github.com/yuanyan3060/Arknights-Tile-Pos")
        level = find_level(None, level_name)
        self.calc = Calc(1920, 1080, level)
        copilot = config.works["sss"]
        self.level_name = level_name
        self.strategies_copy = strategies  # 策略列表备份
        self.actions_copy = actions  # 行动列表备份
        self.draw_as_possible = draw_as_possible  # 调配干员好了就点
        self.opers = [
            oper.model_dump(exclude_none=True) for oper in copilot.opers
        ]  # 干员列表
        self.retry_times = retry_times  # 重试次数，超过返回
        self.groups = [
            group.model_dump(exclude_none=True) for group in copilot.groups
        ]  # 干员组
        self.deadline = deadline  # 截止时间
        self.success = False
        super().run()
        return self.success

    def kills(self) -> int:
        "获取击杀数"
        return super().kills(((935, 30), (1085, 60)))

    def check_name(self, name):
        return super().check_name(name, ((10, 160), (280, 205)))

    def travel_strategies(self):
        "遍历策略"
        if not self.strategies:
            return
        if not self.check_operators():
            self.update_operators()
        continue_loc = set()  # 记录有核心干员且未布置的格子

        for i, strategy in enumerate(self.strategies):
            x, y = strategy["location"]
            if (x, y) in continue_loc:
                continue
            strategy["tool_men"] = {
                key: value for key, value in strategy["tool_men"].items() if value > 0
            }  # 筛掉已为0的工具人
            logger.info(strategy)
            if has_core := ("core" in strategy):
                continue_loc.add((x, y))
            if strategy["tool_men"]:
                filtered = [
                    (name, self.operators[self.tool_men[name]]["cost"])
                    for name in strategy["tool_men"]
                    if name in self.tool_men
                ]  # 筛出可部署的工具人
                deploy_name = min(filtered, key=lambda x: x[1], default=(None,))[
                    0
                ]  # 选择费用最小的工具人
                if deploy_name:  # 部署工具人
                    if self.deploy(
                        self.tool_men[deploy_name], x, y, strategy["direction"]
                    ):
                        strategy["tool_men"][deploy_name] -= 1
                    return
                else:  # 没有满足条件就检查下一条策略
                    continue
            if not has_core:  # 没有核心则此策略执行完毕
                del self.strategies[i]
                return

            if strategy["core"] in self.operators:  # 部署核心干员
                if self.deploy(strategy["core"], x, y, strategy["direction"]):
                    del self.strategies[i]
                return

    def transition(self):
        if (scene := self.scene()) == Scene.OPERATOR_FIGHT:
            if self.loading:
                self.fight_init()
                return
            if self.draw_as_possible and self.find("sss/add_agent"):
                self.tap((1805, 684), interval=0.4)
                self.clear_op()
                return
            elif self.find("sss/start_directly"):
                self.tap("sss/start_directly")
                return

            self.travel_watching_skills()
            self.execute_action()
            self.travel_strategies()

        elif scene == Scene.OPERATOR_FAILED:
            logger.warning(f"{self.level_name}作战失败，请检查干员/练度")
            self.tap((960, 540))
            self.retry_times -= 1

        elif scene == Scene.SSS_OPERATION_COMPLETE:
            logger.info(f"{self.level_name}作战胜利")
            self.tap((960, 540))
            self.success = True

        elif scene in self.waiting_scene:
            self.waiting_solver()
        elif scene in [Scene.SSS_DEPLOY, Scene.SSS_REDEPLOY]:
            if self.deadline and self.deadline < datetime.now():  # 任务打断
                self.success = True
                return True
            if self.success or self.retry_times <= 0:
                return True
            else:
                self.tap((1645, 971))
                self.reset()
        elif scene in [
            Scene.SSS_DROP_AGENT_BEFORE_FIGHT,
            Scene.SSS_DROP_EC_BEFORE_FIGHT,
            Scene.SSS_DROP_IN_FIGHT,
        ]:
            self.sleep(2)
            if not SSSDROPSolver().run():
                self.scene_graph_navigation(Scene.SSS_DEPLOY)
                return True
            self.clear_op()
        elif scene == Scene.SSS_ACTION:
            self.tap((1651, 967))
        elif scene == Scene.SSS_ACCOMPLISHED:
            return True
        else:
            return True
