from __future__ import annotations
import time
from dataclasses import dataclass
from typing import Dict, Tuple

@dataclass
class StrikeState:
    count: int
    expires_at: float

class StrikeTable:
    """
    Tracks strikes per (guild, channel, game, user).
    Windowed strikes: expires after N seconds.
    """
    def __init__(self):
        self._map: Dict[str, StrikeState] = {}

    @staticmethod
    def _key(guild_id: int, channel_id: int, game: str, user_id: int) -> str:
        return f"{guild_id}:{channel_id}:{game}:{user_id}"

    def add(self, guild_id: int, channel_id: int, game: str, user_id: int, window_s: int) -> int:
        now = time.monotonic()
        key = self._key(guild_id, channel_id, game, user_id)
        st = self._map.get(key)
        if not st or st.expires_at <= now:
            st = StrikeState(count=0, expires_at=now + window_s)
            self._map[key] = st
        st.count += 1
        st.expires_at = now + window_s
        return st.count

    def get(self, guild_id: int, channel_id: int, game: str, user_id: int) -> int:
        now = time.monotonic()
        key = self._key(guild_id, channel_id, game, user_id)
        st = self._map.get(key)
        if not st or st.expires_at <= now:
            self._map.pop(key, None)
            return 0
        return st.count

    def clear_user(self, guild_id: int, channel_id: int, game: str, user_id: int):
        self._map.pop(self._key(guild_id, channel_id, game, user_id), None)