from tempfile import TemporaryDirectory

import pytest
import json
import tempfile
import os
import shutil
from unittest.mock import patch, mock_open, MagicMock, Mock
from typing import Dict, Any


# import function to be tested
import sys
from pathlib import Path
sys.path.insert(0, str(Path(__file__).parent.parent.parent.parent / "src"))
from alayaflow.execution.env_manager import EnvManager
"""
python-dotenv
prettytable
"""

Testee_import_prefix="alayaflow.execution.env_manager"


class TestMetaIO:
    @pytest.fixture
    def temp_env_dir(self):
        """创建临时目录作为测试环境目录"""
        with tempfile.TemporaryDirectory() as temp_dir:
            yield temp_dir

    @pytest.fixture
    def mock_settings(self, temp_env_dir):
        """模拟settings模块返回临时目录"""
        with patch((Testee_import_prefix+'.settings')) as mock_settings:
            mock_settings.envs_dir = temp_env_dir
            yield mock_settings

    @pytest.fixture
    def env_manager(self, mock_settings):
        """创建EnvManager实例"""
        return EnvManager()

    def test_load_metadata_when_file_not_exists(self, temp_env_dir, env_manager):
        """测试当元数据文件不存在时返回空字典"""
        # 确保元数据文件不存在
        metadata_file = os.path.join(temp_env_dir, "envs_metadata.json")
        if os.path.exists(metadata_file):
            os.remove(metadata_file)

        # 调用被测试方法
        result = env_manager._load_metadata()

        # 验证结果
        assert isinstance(result, dict)
        assert result == {}

    def test_load_metadata_with_valid_json(self, temp_env_dir, env_manager):
        """测试加载有效的JSON元数据"""
        # 准备测试数据
        test_data = {
            "env1": {"python_version": "3.9", "packages": ["pytest"]},
            "env2": {"python_version": "3.10", "packages": ["requests"]}
        }

        # 创建元数据文件
        metadata_file = os.path.join(temp_env_dir, "envs_metadata.json")
        with open(metadata_file, 'w') as f:
            json.dump(test_data, f)

        # 调用被测试方法
        result = env_manager._load_metadata()

        # 验证结果
        assert result == test_data
        assert "env1" in result
        assert result["env1"]["python_version"] == "3.9"

    def test_load_metadata_with_invalid_json(self, temp_env_dir, env_manager):
        """测试处理无效的JSON文件"""
        # 创建无效的JSON文件
        metadata_file = os.path.join(temp_env_dir, "envs_metadata.json")
        with open(metadata_file, 'w') as f:
            f.write("invalid json content")

        # 测试应该处理异常并返回空字典
        result = env_manager._load_metadata()

        # 验证返回空字典
        assert result == {}

    def test_load_metadata_empty_file(self, temp_env_dir, env_manager):
        """测试处理空文件"""
        # 创建空文件
        metadata_file = os.path.join(temp_env_dir, "envs_metadata.json")
        with open(metadata_file, 'w') as f:
            pass  # 空文件

        # 调用被测试方法
        result = env_manager._load_metadata()

        # 验证返回空字典
        assert result == {}

    def test_save_metadata_normal(self, temp_env_dir, env_manager):
        """测试正常保存元数据"""
        # 准备测试数据
        test_data = {
            "test_env": {
                "python_version": "3.11",
                "created_at": "2024-01-15",
                "packages": ["pytest", "requests"]
            }
        }

        # 设置环境管理器的元数据
        env_manager.env_metadata = test_data

        # 调用被测试方法
        env_manager._save_metadata()

        # 验证文件是否正确写入
        metadata_file = os.path.join(temp_env_dir, "envs_metadata.json")
        assert os.path.exists(metadata_file)

        with open(metadata_file, 'r') as f:
            saved_data = json.load(f)

        assert saved_data == test_data

    def test_save_metadata_empty(self, temp_env_dir, env_manager):
        """测试保存空元数据"""
        # 设置空元数据
        env_manager.env_metadata = {}

        # 调用被测试方法
        env_manager._save_metadata()

        # 验证文件是否存在并包含空字典
        metadata_file = os.path.join(temp_env_dir, "envs_metadata.json")
        assert os.path.exists(metadata_file)

        with open(metadata_file, 'r') as f:
            saved_data = json.load(f)

        assert saved_data == {}


class TestAggr:
    """集成测试类，管理测试环境的复制和清理，并备份测试结果"""

    @classmethod
    def prepare_testcase(cls, test_file_dir):
        """创建env"""
        pass

    @pytest.fixture
    def mock_settings(self):
        """模拟settings模块返回临时目录"""
        with patch((Testee_import_prefix + '.settings')) as mock_settings:
            with TemporaryDirectory() as temp_dir:
                mock_settings.envs_dir = temp_dir
                yield mock_settings

    @pytest.fixture
    def env_manager(self, mock_settings):
        """创建EnvManager实例"""
        manager=EnvManager()
        with patch.object(manager, '_install_alayaflow') as mock_install:
            # 在上下文内，方法已被mock
            mock_install.return_value = None
            yield manager

    @pytest.fixture(scope="function")
    def em_init(self, env_manager):
        """创建EnvManager实例并调用一次requests==2.31.0创建已有环境"""
        requirements=["requests==2.31.0"]
        with patch('uuid.uuid4') as mock_uuid:
            # 创建一个模拟的 UUID 对象
            mock_uuid_obj = Mock()
            mock_uuid_obj.hex = "0110"*8
            mock_uuid.return_value = mock_uuid_obj
            env_manager.ensure_env(
                "test_workflow0","0.1.0",requirements=requirements,use_venv=True
            )
        return env_manager

    def test_env_exact(self,env_manager):
        requirements=["requests==2.31.0"]
        python_exe=env_manager.ensure_env(
            "test_workflow1","0.1.0",requirements=requirements,use_venv=True
        )
        print(f"[TEST LOG]python exe={python_exe}")
        cmd = [python_exe, "-c", "import requests; print('requests version:', requests.__version__)"]
        import subprocess
        result = subprocess.run(cmd, capture_output=True, text=True, check=True)
        assert result.stdout.strip() == "requests version: 2.31.0"
        print(f"[TEST LOG]package verif output={result.stdout.strip()}")

    def test_env_satisfied(self,em_init):
        env_manager=em_init
        requirements=["requests<2.32.0"]
        python_exe=env_manager.ensure_env(
            "test_workflow2","0.1.0",requirements=requirements,use_venv=True
        )
        pythonpath=Path(python_exe)
        assert pythonpath.parent.parent.name == "0110"*8
        print(f"[TEST LOG]python exe={python_exe}")
        cmd = [python_exe, "-c", "import requests; print('requests version:', requests.__version__)"]
        import subprocess
        result = subprocess.run(cmd, capture_output=True, text=True, check=True)
        assert result.stdout.strip().startswith("requests version")
        print(f"[TEST LOG]package verif output={result.stdout.strip()}")

    def test_env_unsatisfied(self,em_init):
        env_manager=em_init
        requirements=["requests>2.32.0"]
        python_exe=env_manager.ensure_env(
            "test_workflow3","0.1.0",requirements=requirements,use_venv=True
        )
        pythonpath=Path(python_exe)
        assert pythonpath.parent.parent.name != "0110"*8
        print(f"[TEST LOG]python exe={python_exe}")
        cmd = [python_exe, "-c", "import requests; print('requests version:', requests.__version__)"]
        import subprocess
        result = subprocess.run(cmd, capture_output=True, text=True, check=True)
        assert result.stdout.strip().startswith("requests version")
        print(f"[TEST LOG]package verif output={result.stdout.strip()}")
    # # 以下为测试方法占位符，你可以后续添加具体的测试
    # def test_env_manager_initialization(self):
    #     """测试EnvManager在测试目录下的初始化"""
    #     # 这里可以写具体的测试代码
    #     pass
    #
    # def test_load_metadata_from_testing_dir(self):
    #     """测试从testing目录加载metadata"""
    #     # 这里可以写具体的测试代码
    #     pass
    #
    # def test_save_metadata_to_testing_dir(self):
    #     """测试保存metadata到testing目录"""
    #     # 这里可以写具体的测试代码
    #     pass