from dataclasses import dataclass
from datetime import datetime, timedelta
from typing import Dict


@dataclass
class TriggerContext:
    has_eye: bool
    has_temp: bool
    has_id: bool
    head_center_x: float
    image_width: int
    species_id: str


class TriggerPolicy:
    def __init__(self, center_ratio_x: float = 0.3, cooldown_sec: int = 30):
        self.center_ratio_x = center_ratio_x
        self.cooldown_sec = cooldown_sec
        self.last_trigger_at: Dict[str, datetime] = {}

    def _is_head_x_centered(self, head_center_x: float, image_width: int) -> bool:
        if image_width <= 0:
            return False
        center_x = image_width / 2.0
        half_range = image_width * self.center_ratio_x / 2.0
        return (center_x - half_range) <= head_center_x <= (center_x + half_range)

    def _cooldown_ok(self, species_id: str, now: datetime) -> bool:
        last = self.last_trigger_at.get(species_id)
        if last is None:
            return True
        return now - last >= timedelta(seconds=self.cooldown_sec)

    def should_trigger(self, ctx: TriggerContext, now: datetime) -> bool:
        if not (ctx.has_eye and ctx.has_temp and ctx.has_id):
            return False
        if not self._is_head_x_centered(ctx.head_center_x, ctx.image_width):
            return False
        if not self._cooldown_ok(ctx.species_id, now):
            return False
        self.last_trigger_at[ctx.species_id] = now
        return True

