import os
import unittest
import subprocess
import tempfile
from pathlib import Path
import logging
from SystemUpdater.dataMigrator.packager import DebRepacker

class TestDebRepackerRepack(unittest.TestCase):

    @classmethod
    def setUpClass(cls):
        # 配置 logging 输出到终端
        logging.basicConfig(
            level=logging.INFO,          # 显示 INFO 及以上级别
            format="%(asctime)s [%(levelname)s] %(message)s",
            datefmt="%H:%M:%S"
        )
        cls.test_dir = Path(__file__).parent / "test-data" / "debs-repack"
        cls.test_dir.mkdir(parents=True, exist_ok=True)
        packages = ["bash", "coreutils", "apache2"]
        cls.pkg_versions = {}
        for pkg in packages:
            try:
                result = subprocess.run(
                    ["dpkg-query", "-W", "-f=${Version}", pkg],
                    stdout=subprocess.PIPE,
                    stderr=subprocess.DEVNULL,
                    text=True,
                )
                version = result.stdout.strip()
                if version:
                    cls.pkg_versions[pkg] = version
            except Exception:
                pass
    
    def setUp(self):
        # 初始化 DebRepacker 实例
        self.repacker = DebRepacker(
            output_dir=str(self.test_dir)
        )

    def _get_installed_version(self, pkg_name: str) -> str:
        """查询本地已安装包版本"""
        result = subprocess.run(
            ["dpkg-query", "-W", "-f=${Version}", pkg_name],
            stdout=subprocess.PIPE,
            stderr=subprocess.DEVNULL,
            text=True,
        )
        version = result.stdout.strip()
        if not version:
            raise RuntimeError(f"Package {pkg_name} not found")
        return version

    def test_1_repack_packages_real_packages(self):
        """
        测试 repack_packages 方法
        """

        logging.info("[TestDebRepackerRepack]Unittest method repack_packages INPUT: ", self.pkg_versions)
        # 调用 repack_packages
        repack_result, failed = self.repacker.repack_packages(self.pkg_versions)

        # 检查返回值类型
        self.assertIsInstance(repack_result, dict)
        self.assertIsInstance(failed, dict)

        # 检查 repack 成功包是否匹配输入字典
        for pkg, version in self.pkg_versions.items():
            if pkg in repack_result:
                self.assertEqual(repack_result[pkg], version)
            else:
                # 如果不在返回字典里，应该在 failed 列表中
                failed_names = [f[0] for f in failed]
                self.assertIn(pkg, failed_names)

        # 检查输出目录下文件命名是否符合 pkg_version_arch.deb
        for file_path in self.test_dir.glob("*.deb"):
            fname = file_path.name
            # 名字包含下划线，至少两个下划线（pkg_version_arch.deb）
            parts = fname[:-4].split("_")
            self.assertGreaterEqual(len(parts), 2, f"Invalid deb file name: {fname}")
            pkg_name = parts[0]
            version = parts[1]
            # 如果包在 repack_result 中，版本应该匹配
            if pkg_name in repack_result:
                self.assertEqual(version, repack_result[pkg_name])

    def test_2_check_and_install_debs(self):
        """
        测试 check_and_install_debs 方法
        """
        logging.info("[TestDebRepackerRepack]Unittest method check_and_install_debs INPUT: ", self.pkg_versions)
        pkg_dict = self.pkg_versions

        # 调用 check_and_install_debs
        result = self.repacker.check_and_install_debs(pkg_dict)

        # 验证返回 True
        self.assertTrue(result)

    def test_3_auto_run(self):
        """
        测试 check_and_install_debs 方法
        """
        logging.info("[TestDebRepackerRepack]Unittest method auto_run INPUT: ", self.pkg_versions)
        pkg_dict = self.pkg_versions

        # 调用 check_and_install_debs
        result = self.repacker.auto_run(pkg_dict)

        # 验证返回 True
        self.assertTrue(result)

    @classmethod
    def tearDownClass(cls):
        # 可选择清空目录，但保留测试文件夹
        for f in cls.test_dir.iterdir():
            if f.is_file():
                f.unlink()
            elif f.is_dir():
                import shutil
                shutil.rmtree(f)

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