import math
import time

from hardware_control import hw_ctrl


class DeathManager:
    ROUTE_SELECTION_EPSILON = 0.3

    def __init__(
        self,
        patrol_system,
        resurrection_waypoints_path=None,
        resurrection_route_a_path=None,
        resurrection_route_b_path=None,
        release_spirit_key='9',
        resurrect_key='0',
    ):
        self.patrol_system = patrol_system
        self.release_spirit_key = str(release_spirit_key).strip() or '9'
        self.resurrect_key = str(resurrect_key).strip() or '0'
        self.resurrection_route_a = self._load_waypoints(
            resurrection_route_a_path or resurrection_waypoints_path
        )
        self.resurrection_route_b = self._load_waypoints(resurrection_route_b_path)

        self.corpse_pos = None
        self.graveyard_pos = None
        self.is_running_to_corpse = False
        self.selected_resurrection_route = None
        self.selected_resurrection_route_name = None

        self._spirit_release_sent = False
        self._route_selected = False
        self._resurrection_completed = False

    def _load_waypoints(self, path):
        """Load a resurrection route JSON file, allowing empty configuration."""
        if not path:
            return None

        import json
        import os

        if not os.path.exists(path):
            return None
        try:
            with open(path, 'r', encoding='utf-8') as f:
                data = json.load(f)
            if isinstance(data, list) and data:
                return [(float(point[0]), float(point[1])) for point in data]
        except Exception:
            pass
        return None

    def _clear_death_run_state(self):
        self.graveyard_pos = None
        self.selected_resurrection_route = None
        self.selected_resurrection_route_name = None
        self._route_selected = False
        self._resurrection_completed = False

    def _build_resurrection_route_candidates(self):
        candidates = []
        if self.resurrection_route_a:
            candidates.append(("A", self.resurrection_route_a))
        if self.resurrection_route_b:
            candidates.append(("B", self.resurrection_route_b))
        return candidates

    def _record_graveyard_pos(self, state):
        if self.graveyard_pos is not None:
            return True

        x = state.get('x')
        y = state.get('y')
        if x is None or y is None:
            return False

        self.graveyard_pos = (float(x), float(y))
        print(f">>> [系统] 记录墓地坐标: {self.graveyard_pos}")
        return True

    def _choose_resurrection_route(self):
        if self.graveyard_pos is None:
            return None, None

        candidates = self._build_resurrection_route_candidates()
        if not candidates:
            return None, None

        best_name = None
        best_points = None
        best_dist = None
        for name, points in candidates:
            start_pos = points[0]
            dist = math.dist(self.graveyard_pos, start_pos)
            print(f">>> [系统] 复活路线{name} 起点距离墓地: {dist:.3f} | 起点: {start_pos}")
            if best_dist is None or dist + self.ROUTE_SELECTION_EPSILON < best_dist:
                best_name = name
                best_points = points
                best_dist = dist
        return best_name, best_points

    def reset_when_alive(self):
        """Clear death-related state after the character is alive again."""
        self._spirit_release_sent = False
        self.corpse_pos = None
        self.is_running_to_corpse = False
        self._clear_death_run_state()

    def on_death(self, state):
        """Record corpse coordinates once, then release spirit."""
        if self._spirit_release_sent:
            return

        self._spirit_release_sent = True
        self._clear_death_run_state()
        self.corpse_pos = (state['x'], state['y'])
        self.is_running_to_corpse = True
        print(f">>> [系统] 记录死亡坐标: {self.corpse_pos}，准备释放灵魂...")
        hw_ctrl.press(self.release_spirit_key)
        time.sleep(5)

    def run_to_corpse(self, state, get_state=None):
        """
        Run the configured resurrection route first, then navigate back to the corpse.
        """
        if not self.corpse_pos:
            return

        if not self._record_graveyard_pos(state):
            return

        if not self._route_selected:
            route_name, route_points = self._choose_resurrection_route()
            self.selected_resurrection_route_name = route_name
            self.selected_resurrection_route = route_points
            self._route_selected = True
            if route_name:
                print(f">>> [系统] 本次死亡选择复活路线: {route_name}")
            else:
                print(">>> [系统] 未配置可用复活路线，直接前往尸体...")

        if self.selected_resurrection_route and not self._resurrection_completed:
            if get_state is None:
                return
            if self.patrol_system.navigate_path(get_state, self.selected_resurrection_route):
                self._resurrection_completed = True
                print(
                    f">>> [系统] 复活路线{self.selected_resurrection_route_name}跑完，开始前往尸体..."
                )
            return

        is_arrived = self.patrol_system.navigate_to_point(state, self.corpse_pos)
        if is_arrived:
            print(">>> 已到达尸体附近，尝试复活...")
            hw_ctrl.press(self.resurrect_key)
            time.sleep(5)
            if get_state:
                new_state = get_state()
                if new_state and new_state.get('death_state') == 2:
                    print(">>> 仍为灵魂状态，再次尝试复活...")
                    hw_ctrl.press(self.resurrect_key)
                    time.sleep(5)
            self.is_running_to_corpse = False
            self.corpse_pos = None
            self._clear_death_run_state()
