import tempfile
import unittest
import importlib.util
import sys
import types
from pathlib import Path


PROJECT_ROOT = Path(__file__).resolve().parent


def ensure_package(package_name: str, package_path: Path) -> None:
    if package_name in sys.modules:
        return
    package = types.ModuleType(package_name)
    package.__path__ = [str(package_path)]
    sys.modules[package_name] = package


def load_module(module_name: str, relative_path: str):
    module_path = PROJECT_ROOT / relative_path
    spec = importlib.util.spec_from_file_location(module_name, module_path)
    module = importlib.util.module_from_spec(spec)
    assert spec and spec.loader
    sys.modules[module_name] = module
    spec.loader.exec_module(module)
    return module


ensure_package("danding_bot", PROJECT_ROOT / "danding_bot")
ensure_package("danding_bot.plugins", PROJECT_ROOT / "danding_bot/plugins")
ensure_package(
    "danding_bot.plugins.onmyoji_gacha",
    PROJECT_ROOT / "danding_bot/plugins/onmyoji_gacha",
)
load_module(
    "danding_bot.plugins.onmyoji_gacha.config",
    "danding_bot/plugins/onmyoji_gacha/config.py",
)
data_manager_module = load_module(
    "danding_bot.plugins.onmyoji_gacha.data_manager",
    "danding_bot/plugins/onmyoji_gacha/data_manager.py",
)
utils = load_module(
    "danding_bot.plugins.onmyoji_gacha.utils",
    "danding_bot/plugins/onmyoji_gacha/utils.py",
)


class DataManagerSignInTests(unittest.TestCase):
    def setUp(self) -> None:
        self.temp_dir = tempfile.TemporaryDirectory()
        base_path = Path(self.temp_dir.name)
        self.original_db_file = data_manager_module.config.DB_FILE
        self.original_img_dir = data_manager_module.config.SHIKIGAMI_IMG_DIR
        data_manager_module.config.DB_FILE = str(base_path / "gacha.db")
        data_manager_module.config.SHIKIGAMI_IMG_DIR = str(base_path / "images")
        Path(data_manager_module.config.SHIKIGAMI_IMG_DIR).mkdir(parents=True, exist_ok=True)
        self.manager = data_manager_module.DataManager()

    def tearDown(self) -> None:
        data_manager_module.config.DB_FILE = self.original_db_file
        data_manager_module.config.SHIKIGAMI_IMG_DIR = self.original_img_dir
        self.temp_dir.cleanup()

    def test_record_sign_in_is_idempotent_for_same_day(self) -> None:
        user_id = "10001"

        self.assertFalse(self.manager.has_signed_in_today(user_id))
        self.assertTrue(self.manager.record_sign_in(user_id, 88))
        self.assertTrue(self.manager.has_signed_in_today(user_id))
        self.assertFalse(self.manager.record_sign_in(user_id, 99))


class UtilsSignInTests(unittest.TestCase):
    def test_get_luck_description_uses_document_ranges(self) -> None:
        self.assertEqual(utils.get_luck_description(1), ("非酋", "😭"))
        self.assertEqual(utils.get_luck_description(11), ("一般", "😐"))
        self.assertEqual(utils.get_luck_description(31), ("小欧", "😊"))
        self.assertEqual(utils.get_luck_description(61), ("大欧", "🎉"))
        self.assertEqual(utils.get_luck_description(91), ("欧皇", "👑"))

    def test_format_sign_in_message_matches_required_format(self) -> None:
        message = utils.format_sign_in_message("10001", "小夏", 87, 1247)
        expected = (
            "@小夏 📅 每日签到成功！\n"
            "🎁 获得积分：87\n"
            "🎉 今日运气：大欧\n"
            "💰 当前积分：1247"
        )
        self.assertEqual(message, expected)


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