import asyncio
import random
import time


class MicroOfflineEngine:

    def __init__(self):

        # -------------------------
        # ONLINE WINDOW CONTROL
        # -------------------------

        # حداقل زمان بیداری
        self.min_online_before_sleep = 900   # 15 min

        # حداکثر زمان بیداری
        self.max_online_before_sleep = 5400  # 90 min

        # احتمال خواب بعد از رسیدن به window
        self.sleep_probability = 0.40

        # -------------------------
        # OFFLINE CAP (2 → 7 min)
        # -------------------------

        self.offline_duration_range = (
            120,   # 2 min
            420    # 7 min
        )

        self._online_since = {}

    # ---------- MARK ONLINE ----------
    def mark_online(self, session):

        self._online_since[session] = time.time()

    # ---------- ONLINE TIME ----------
    def _online_time(self, session):

        return time.time() - self._online_since.get(
            session,
            time.time()
        )

    # ---------- SHOULD SLEEP ----------
    def should_sleep(self, session):

        online_time = self._online_time(session)

        if online_time < self.min_online_before_sleep:
            return False

        if online_time > self.max_online_before_sleep:
            return True

        return (
            random.random()
            < self.sleep_probability
        )

    # ---------- EXECUTE ----------
    async def execute(self, session, app):

        if not app.is_connected:
            return

        if not self.should_sleep(session):
            return

        sleep_time = random.uniform(
            *self.offline_duration_range
        )

        print(
            f"[{session}] "
            f"Micro-Offline "
            f"{int(sleep_time)}s"
        )

        try:

            await app.stop()

            await asyncio.sleep(sleep_time)

            await app.start()

            self.mark_online(session)

            print(
                f"[{session}] Back Online"
            )

        except Exception as e:

            print(
                f"[{session}] "
                f"Micro error → {e}"
            )


micro_offline_engine = MicroOfflineEngine()
