"""
战斗状态检测模块，通过模板匹配判断角色是否处于战斗中
"""
import os
import logging
import cv2
import numpy as np
import pyautogui
from config import GameConfig


class CombatDetector:
    """通过截图与模板匹配判断当前是否处于战斗状态"""

    TEMPLATES = [
        'images/1.png',
        'images/2.png',
        'images/3.png',
        'images/4.png',
    ]
    SCREENSHOT_PATH = 'screenshot/combat_screenshot.png'

    def __init__(self, config: GameConfig):
        self.config = config
        self.screen_width, self.screen_height = pyautogui.size()
        self.logger = logging.getLogger(__name__)
        os.makedirs(os.path.dirname(self.SCREENSHOT_PATH), exist_ok=True)

    def is_in_combat(self) -> bool:
        """判断是否处于战斗中。

        截取屏幕左上半区域，逐一与模板图片做归一化相关系数匹配，
        任一模板匹配值超过阈值即视为处于战斗状态。

        Returns:
            bool: 处于战斗中返回 True，否则返回 False
        """
        try:
            region_width = self.screen_width // 2
            region_height = self.screen_height // 2
            screenshot = pyautogui.screenshot(region=(0, 0, region_width, region_height))
            screenshot.save(self.SCREENSHOT_PATH)

            screenshot_cv = cv2.cvtColor(np.array(screenshot), cv2.COLOR_RGB2BGR)

            for template_file in self.TEMPLATES:
                if not os.path.exists(template_file):
                    self.logger.warning(f"模板文件不存在，跳过: {template_file}")
                    continue

                template = cv2.imread(template_file)
                result = cv2.matchTemplate(
                    screenshot_cv,
                    template,
                    cv2.TM_CCOEFF_NORMED
                )
                _, max_val, _, _ = cv2.minMaxLoc(result)

                if max_val > self.config.recognition_threshold:
                    self.logger.info(
                        f"战斗状态: 是（模板: {template_file}，匹配值: {max_val:.2f}）"
                    )
                    return True

            self.logger.info("战斗状态: 否（所有模板均未匹配）")
            return False

        except Exception as e:
            self.logger.error(f"判断战斗状态失败: {str(e)}")
            return False
