import time
import threading
import datetime

class AICronManager:
    def __init__(self):
        self.tasks = []
        self._stop_event = threading.Event()
        self._thread = None

    def schedule_task(self, cron_expr, task):
        self.tasks.append((cron_expr, task))

    def _match_field(self, value, expr):
        if expr == '*':
            return True
        if expr.startswith('*/'):
            try:
                step = int(expr[2:])
                return value % step == 0
            except ValueError:
                return False
        if '-' in expr:
            try:
                start, end = map(int, expr.split('-'))
                return start <= value <= end
            except ValueError:
                return False
        if ',' in expr:
            try:
                parts = map(int, expr.split(','))
                return value in parts
            except ValueError:
                return False
        try:
            return value == int(expr)
        except ValueError:
            return False

    def _matches(self, cron_expr, dt):
        parts = cron_expr.split()
        if len(parts) != 5:
            return False
        
        minute_expr, hour_expr, dom_expr, month_expr, dow_expr = parts
        
        dow = dt.isoweekday()
        if dow == 7:
            dow = 0 # 0 is Sunday in cron
            
        return (
            self._match_field(dt.minute, minute_expr) and
            self._match_field(dt.hour, hour_expr) and
            self._match_field(dt.day, dom_expr) and
            self._match_field(dt.month, month_expr) and
            self._match_field(dow, dow_expr)
        )

    def _run_loop(self):
        while not self._stop_event.is_set():
            now = datetime.datetime.now()
            for cron_expr, task in self.tasks:
                if self._matches(cron_expr, now):
                    try:
                        threading.Thread(target=task, daemon=True).start()
                    except Exception:
                        pass
            
            # Wait until the next minute starts
            while not self._stop_event.is_set():
                now2 = datetime.datetime.now()
                if now2.minute != now.minute:
                    break
                self._stop_event.wait(0.5)

    def start_scheduler(self):
        self._stop_event.clear()
        if self._thread is None or not self._thread.is_alive():
            self._thread = threading.Thread(target=self._run_loop, daemon=True)
            self._thread.start()

    def stop_scheduler(self):
        self._stop_event.set()
        if self._thread:
            self._thread.join(timeout=2)
