# Copyright (c) Huawei Technologies Co., Ltd. 2026-2026. All rights reserved.
# OpenOLC is licensed under Mulan PSL v2.
# You can use this software according to the terms and conditions of the Mulan PSL v2.
# You may obtain a copy of Mulan PSL v2 at:
#         `http://license.coscl.org.cn/MulanPSL2`
# THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
# EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
# MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
# See the Mulan PSL v2 for more details.

import unittest
import time
from olc.task_schedule.task_schedule import ThreadPoolManager, Task, IntervalTask, OlcScheduleManager


class MockTask(Task):
    def __init__(self):
        self.execution_count = 0
        self.last_execution_time = None
    
    def run(self):
        self.execution_count += 1
        self.last_execution_time = time.time()


class MockTaskWithException(Task):
    def run(self):
        raise Exception("Test exception")


class TestThreadPoolManager(unittest.TestCase):
    """测试线程池管理器"""
    
    def setUp(self):
        self.manager = ThreadPoolManager()
    
    def tearDown(self):
        self.manager.shutdown_all()
    
    def test_create_pool_config(self):
        """测试创建线程池配置"""
        result = self.manager.create_pool_config("test_pool", 2)
        self.assertTrue(self.manager.has_pool_config("test_pool"))
    
    def test_create_pool(self):
        """测试创建线程池"""
        self.manager.create_pool_config("test_pool", 2)
        result = self.manager.create_pool("test_pool")
        self.assertTrue(result)
        self.assertTrue(self.manager.is_pool_active("test_pool"))
    
    def test_create_pool_nonexistent_config(self):
        """测试创建不存在配置的线程池"""
        result = self.manager.create_pool("nonexistent_pool")
        self.assertFalse(result)
    
    def test_submit_task(self):
        """测试提交任务到线程池"""
        self.manager.create_pool_config("test_pool", 2)
        self.manager.create_pool("test_pool")
        
        test_value = [0]
        def test_func():
            test_value[0] = 1
        
        future = self.manager.submit("test_pool", test_func)
        self.assertIsNotNone(future)
        future.result()  # 等待任务完成
        self.assertEqual(test_value[0], 1)
    
    def test_submit_task_nonexistent_pool(self):
        """测试提交任务到不存在的线程池"""
        future = self.manager.submit("nonexistent_pool", lambda: 1)
        self.assertIsNone(future)
    
    def test_shutdown_pool(self):
        """测试关闭线程池"""
        self.manager.create_pool_config("test_pool", 2)
        self.manager.create_pool("test_pool")
        result = self.manager.shutdown_pool("test_pool")
        self.assertTrue(result)
        self.assertFalse(self.manager.is_pool_active("test_pool"))
    
    def test_shutdown_nonexistent_pool(self):
        """测试关闭不存在的线程池"""
        result = self.manager.shutdown_pool("nonexistent_pool")
        self.assertFalse(result)
    
    def test_shutdown_all(self):
        """测试关闭所有线程池"""
        self.manager.create_pool_config("pool1", 1)
        self.manager.create_pool_config("pool2", 1)
        self.manager.create_pool("pool1")
        self.manager.create_pool("pool2")

        self.manager.shutdown_all()
        self.assertFalse(self.manager.is_pool_active("pool1"))
        self.assertFalse(self.manager.is_pool_active("pool2"))

    def test_shutdown_all_multiple_times_safely(self):
        """[核心测试] 验证多次调用 shutdown_all 不会出错或死锁"""
        self.manager.create_pool_config("pool1", 1)
        self.manager.create_pool_config("pool2", 1)
        self.manager.create_pool("pool1")
        self.manager.create_pool("pool2")

        # 第一次关闭
        result1 = self.manager.shutdown_all()
        self.assertFalse(self.manager.is_pool_active("pool1"))
        self.assertFalse(self.manager.is_pool_active("pool2"))

        # 第二次关闭(应该安全,不会报错或死锁)
        result2 = self.manager.shutdown_all()
        # 验证状态保持一致
        self.assertFalse(self.manager.is_pool_active("pool1"))
        self.assertFalse(self.manager.is_pool_active("pool2"))

    def test_shutdown_all_then_recreate(self):
        """测试关闭所有后重新创建线程池"""
        # 创建并关闭
        self.manager.create_pool_config("pool1", 2)
        self.manager.create_pool("pool1")
        self.manager.shutdown_all()

        # 重新创建应该成功
        self.manager.create_pool_config("pool1_new", 2)
        result = self.manager.create_pool("pool1_new")
        self.assertTrue(result)
        self.assertTrue(self.manager.is_pool_active("pool1_new"))

        # 清理
        self.manager.shutdown_all()

    def test_shutdown_all_empty_manager(self):
        """测试空管理器调用 shutdown_all 不报错"""
        # 没有创建任何线程池
        try:
            self.manager.shutdown_all()
            # 应该正常完成,不抛出异常
        except Exception as e:
            self.fail(f"空管理器调用 shutdown_all 不应抛出异常: {e}")

    def test_shutdown_all_with_active_tasks(self):
        """测试关闭有活跃任务的线程池"""
        import concurrent.futures

        self.manager.create_pool_config("busy_pool", 2)
        self.manager.create_pool("busy_pool")

        # 提交一个长时间运行的任务
        def long_running_task():
            time.sleep(0.5)
            return "done"

        future = self.manager.submit("busy_pool", long_running_task)
        self.assertIsNotNone(future)

        # 关闭所有线程池(任务会被取消)
        self.manager.shutdown_all()

        # 线程池应该已关闭
        self.assertFalse(self.manager.is_pool_active("busy_pool"))
    
    def test_remove_pool(self):
        """测试移除线程池"""
        self.manager.create_pool_config("test_pool", 2)
        self.manager.create_pool("test_pool")
        result = self.manager.remove("test_pool")
        self.assertTrue(result)
        self.assertFalse(self.manager.has_pool_config("test_pool"))


class TestIntervalTask(unittest.TestCase):
    """测试间隔任务"""
    
    def setUp(self):
        self.manager = ThreadPoolManager()
        self.manager.create_pool_config("test_pool", 2)
        self.manager.create_pool("test_pool")
        self.test_task = MockTask()
    
    def tearDown(self):
        self.manager.shutdown_all()
    
    def test_register(self):
        """测试注册任务"""
        from schedule import Scheduler
        scheduler = Scheduler()
        interval_task = IntervalTask("test_task", self.test_task, 1, "test_pool")
        result = interval_task.register(self.manager, scheduler)
        self.assertTrue(result)
        self.assertTrue(interval_task.is_running())
    
    def test_unregister(self):
        """测试取消注册任务"""
        from schedule import Scheduler
        scheduler = Scheduler()
        interval_task = IntervalTask("test_task", self.test_task, 1, "test_pool")
        interval_task.register(self.manager, scheduler)
        interval_task.unregister(scheduler)
        self.assertFalse(interval_task.is_running())
    
    def test_get_info(self):
        """测试获取任务信息"""
        interval_task = IntervalTask("test_task", self.test_task, 1, "test_pool")
        info = interval_task.get_info()
        self.assertEqual(info["name"], "test_task")
        self.assertEqual(info["interval"], 1)
        self.assertEqual(info["pool_name"], "test_pool")
        self.assertFalse(info["running"])


class TestScheduleManager(unittest.TestCase):
    """测试调度管理器"""
    
    def setUp(self):
        # 确保获取新实例
        OlcScheduleManager._instance = None
        self.manager = OlcScheduleManager.get_instance()
        self.test_task = MockTask()
    
    def tearDown(self):
        self.manager.close()
    
    def test_create_task(self):
        """测试创建任务"""
        result = self.manager.create_task("test_task", self.test_task, 1)
        self.assertTrue(result)
        tasks = self.manager.list_tasks()
        self.assertIn("test_task", tasks)
    
    def test_create_existing_task(self):
        """测试创建已存在的任务"""
        self.manager.create_task("test_task", self.test_task, 1)
        result = self.manager.create_task("test_task", self.test_task, 1)
        self.assertFalse(result)
    
    def test_start_task(self):
        """测试启动任务"""
        self.manager.create_task("test_task", self.test_task, 1)
        result = self.manager.start_task("test_task")
        self.assertTrue(result)
        info = self.manager.get_task_info("test_task")
        self.assertTrue(info["running"])
    
    def test_start_nonexistent_task(self):
        """测试启动不存在的任务"""
        result = self.manager.start_task("nonexistent_task")
        self.assertFalse(result)
    
    def test_stop_task(self):
        """测试停止任务"""
        self.manager.create_task("test_task", self.test_task, 1)
        self.manager.start_task("test_task")
        result = self.manager.stop_task("test_task")
        self.assertTrue(result)
        info = self.manager.get_task_info("test_task")
        self.assertFalse(info["running"])
    
    def test_stop_nonexistent_task(self):
        """测试停止不存在的任务"""
        result = self.manager.stop_task("nonexistent_task")
        self.assertFalse(result)
    
    def test_remove_task(self):
        """测试移除任务"""
        self.manager.create_task("test_task", self.test_task, 1)
        result = self.manager.remove_task("test_task")
        self.assertTrue(result)
        tasks = self.manager.list_tasks()
        self.assertNotIn("test_task", tasks)
    
    def test_remove_nonexistent_task(self):
        """测试移除不存在的任务"""
        result = self.manager.remove_task("nonexistent_task")
        self.assertFalse(result)
    
    def test_start_all_tasks(self):
        """测试启动所有任务"""
        self.manager.create_task("task1", MockTask(), 1)
        self.manager.create_task("task2", MockTask(), 1)
        result = self.manager.start_all_tasks()
        self.assertEqual(len(result), 2)
        self.assertTrue(result["task1"])
        self.assertTrue(result["task2"])
    
    def test_stop_all_tasks(self):
        """测试停止所有任务"""
        self.manager.create_task("task1", MockTask(), 1)
        self.manager.create_task("task2", MockTask(), 1)
        self.manager.start_all_tasks()
        self.manager.stop_all_tasks()
        info1 = self.manager.get_task_info("task1")
        info2 = self.manager.get_task_info("task2")
        self.assertFalse(info1["running"])
        self.assertFalse(info2["running"])
    
    def test_get_task_info(self):
        """测试获取任务信息"""
        self.manager.create_task("test_task", self.test_task, 1)
        info = self.manager.get_task_info("test_task")
        self.assertIsNotNone(info)
        self.assertEqual(info["name"], "test_task")
        self.assertEqual(info["interval"], 1)
    
    def test_get_nonexistent_task_info(self):
        """测试获取不存在任务的信息"""
        info = self.manager.get_task_info("nonexistent_task")
        self.assertIsNone(info)
    
    def test_list_tasks(self):
        """测试列出所有任务"""
        self.manager.create_task("task1", MockTask(), 1)
        self.manager.create_task("task2", MockTask(), 1)
        tasks = self.manager.list_tasks()
        self.assertEqual(len(tasks), 2)
        self.assertIn("task1", tasks)
        self.assertIn("task2", tasks)
    
    def test_is_running(self):
        """测试是否正在运行"""
        self.assertTrue(self.manager.is_running())
    
    def test_task_execution(self):
        """测试任务执行"""
        test_task = MockTask()
        self.manager.create_task("test_task", test_task, 0.1)  # 0.1秒执行一次
        self.manager.start_task("test_task")
        
        # 等待任务执行,增加等待时间以确保任务有足够时间执行
        time.sleep(1.0)
        
        # 验证任务至少执行了一次
        self.assertGreater(test_task.execution_count, 0)
    
    def test_task_with_exception(self):
        """测试任务异常处理"""
        # 这个测试主要是确保异常不会导致整个系统崩溃
        exception_task = MockTaskWithException()
        self.manager.create_task("exception_task", exception_task, 0.1)
        self.manager.start_task("exception_task")
        
        # 等待任务执行
        time.sleep(0.5)
        
        # 确保系统仍然运行
        self.assertTrue(self.manager.is_running())


if __name__ == '__main__':
    unittest.main()