import cv2
from skimage.metrics import structural_similarity

from mower.utils import config
from mower.utils import typealias as tp
from mower.utils.character_recognize import operator_team
from mower.utils.graph import SceneGraphSolver
from mower.utils.image import cmatch, cropimg, load_static
from mower.utils.log import logger
from mower.utils.recognize import Scene
from mower.utils.vector import sa

from .choose_skill import ChooseSkillSolver
from .choose_support import ChooseSupportSolver


class CheckCurrentTeamSolver(SceneGraphSolver):
    solver_name = "检测当前编队"

    def run(self, opers: tp.Opers = [], groups: tp.Groups = [], support: bool = True):
        self.lack = []  # 缺少的干员
        self.skill_diff = {}  # 干员已在编队但不对的技能scope:skill
        current = self.get_team_opers_with_skill()
        logger.info(f"当前编队干员：{current}")
        self.find_lack_and_skill_diff(opers, groups, current)
        logger.info(f"缺少的干员：{self.lack}")
        logger.info(f"技能不对的干员：{self.skill_diff}")
        if len(self.lack) >= 2:
            return False
        elif not support:
            return True
        elif len(self.lack) == 1 and (
            len(current) == 0 or not ChooseSupportSolver().run([self.lack[0]])
        ):
            return False
        for name in self.skill_diff:
            self.skill = self.skill_diff[name]["skill"]
            self.scope = self.skill_diff[name]["scope"]
            self.success = False
            super().run()
        return True

    def get_team_opers_with_skill(self):
        opers = dict(operator_team(config.recog.img))
        for name, scope in opers.items():
            opers[name] = {}
            opers[name]["scope"] = scope
            img = cropimg(config.recog.img, sa(((98, 200), (151, 253)), scope[0]))
            result = []
            for i in range(1, 4):
                try:
                    res = load_static(f"avatar_skill/{name}/{i}")
                except FileNotFoundError:
                    continue
                res = cv2.resize(res, (53, 53))
                if cmatch(img, res, thresh=15):
                    gray = cv2.cvtColor(img, cv2.COLOR_RGB2GRAY)
                    res_gray = cv2.cvtColor(res, cv2.COLOR_RGB2GRAY)
                    ssim = structural_similarity(gray, res_gray)
                    logger.debug(f"cmatch+SSIM:{ssim=}")
                    result.append((i, ssim))
            opers[name]["skill"] = (
                max(result, key=lambda x: x[1])[0] if result else None
            )
        return opers

    def find_lack_and_skill_diff(self, opers, groups, current):
        for op in opers:
            if (name := op["name"]) not in current:
                self.lack.append(op)
            elif op["skill"] != current[name]["skill"]:
                self.skill_diff[name] = {}
                self.skill_diff[name]["scope"] = current[name]["scope"]
                self.skill_diff[name]["skill"] = op["skill"]
        for group in groups:
            flag = True
            for op in group["opers"]:
                if (name := op["name"]) in current:
                    if op["skill"] != current[name]["skill"]:
                        self.skill_diff[name] = {}
                        self.skill_diff[name]["scope"] = current[name]["scope"]
                        self.skill_diff[name]["skill"] = op["skill"]
                    flag = False
                    break
            if flag:
                self.lack.append(group)

    def transition(self):
        if (scene := self.scene()) == Scene.OPERATOR_AGENT_SELECT:
            if self.success:
                self.ctap("choose_agent/battle_confirm")
                return
            ChooseSkillSolver().run(self.skill)
            self.success = True

        elif scene == Scene.OPERATOR_SELECT:
            if self.success:
                return True
            self.ctap(self.scope, 5)
        elif scene in self.waiting_scene:
            self.waiting_solver()
        else:
            return True
