import time
import threading
import asyncio
from datetime import datetime
from typing import Optional
from .interfaces import TaskExecutorInterface, TaskModel
from .manager import TaskManager

class TaskExecutor(TaskExecutorInterface):
    """Task executor implementation."""
    
    def __init__(self, task_manager: TaskManager):
        self.task_manager = task_manager
        self.running = False
        self.thread = None
    
    def start(self) -> bool:
        """Start the executor."""
        if self.running:
            return False
        
        self.running = True
        self.thread = threading.Thread(target=self._run, daemon=True)
        self.thread.start()
        return True
    
    def stop(self) -> bool:
        """Stop the executor."""
        self.running = False
        if self.thread:
            self.thread.join(timeout=5)
        return True
    
    def _run(self):
        """Main execution loop."""
        while self.running:
            self._check_tasks()
            time.sleep(1)  # Check every second
    
    def _check_tasks(self):
        """Check for tasks that need to be executed."""
        current_time = datetime.now()
        tasks_to_execute = []
        
        # Find tasks that need to be executed
        for task_name, task in self.task_manager.list_tasks().items():
            if task.get_trigger_time() <= current_time:
                tasks_to_execute.append(task)
        
        # Execute tasks
        for task in tasks_to_execute:
            self.execute_task(task)
    
    def execute_task(self, task: TaskModel) -> bool:
        """Execute a task."""
        task_name = task.get_task_name()
        retry_count = 0
        max_retries = task.get_retry_count()
        
        while retry_count <= max_retries:
            try:
                # Execute the task
                func = task.get_execution_function()
                params = task.get_parameters()
                
                # Check if it's an async function
                if asyncio.iscoroutinefunction(func):
                    asyncio.run(func(**params))
                else:
                    func(**params)
                
                # Task executed successfully
                print(f"Task {task_name} executed successfully")
                
                # Remove task from manager
                self.task_manager.unregister_task(task_name)
                return True
            except Exception as e:
                print(f"Error executing task {task_name}: {e}")
                
                if retry_count < max_retries:
                    retry_count += 1
                    print(f"Retrying task {task_name} ({retry_count}/{max_retries})...")
                    time.sleep(task.get_retry_interval())
                else:
                    print(f"Task {task_name} failed after {max_retries} retries")
                    # Remove task from manager even if it failed
                    self.task_manager.unregister_task(task_name)
                    return False
