"""
测试：BrowserProfile 配置持久化
"""
import pytest
import sys
import os
import shutil
import tempfile

sys.path.insert(0, "src")

from playwright_ez import EasyBrowser, Config, BrowserProfile, ProfileManager


class TestBrowserProfile:
    """测试 BrowserProfile 配置持久化"""

    @pytest.fixture
    def temp_storage_dir(self):
        """创建临时存储目录"""
        temp_dir = tempfile.mkdtemp()
        yield temp_dir
        # 清理
        if os.path.exists(temp_dir):
            shutil.rmtree(temp_dir)

    def test_profile_creation(self, temp_storage_dir):
        """测试创建配置"""
        profile = BrowserProfile("test_session", temp_storage_dir)

        assert profile.name == "test_session"
        assert not profile.exists()

    def test_profile_paths(self, temp_storage_dir):
        """测试配置路径"""
        profile = BrowserProfile("test_session", temp_storage_dir)

        assert profile.config_file.name == "config.json"
        assert profile.cookies_file.name == "cookies.json"
        assert profile.storage_file.name == "storage.json"
        assert profile.state_file.name == "state.json"

    @pytest.mark.asyncio
    async def test_save_and_load_config(self, temp_storage_dir):
        """测试保存和加载配置"""
        config = Config(headless=False, browser_type="firefox")
        config.set_extra("api_key", "test123")

        profile = BrowserProfile("test_session", temp_storage_dir)

        async with EasyBrowser(config) as browser:
            # 保存配置
            await profile.save(browser)

            assert profile.exists()
            assert profile.config_file.exists()
            assert profile.cookies_file.exists()
            assert profile.storage_file.exists()

        # 加载到新浏览器
        new_config = Config()
        async with EasyBrowser(new_config) as browser:
            loaded = await profile.load(browser)

            assert loaded is True
            # 注意：配置加载到 browser.config 对象
            assert browser.config.headless is False
            assert browser.config.browser_type == "firefox"

    @pytest.mark.asyncio
    async def test_save_cookies_only(self, temp_storage_dir):
        """测试仅保存 Cookies"""
        profile = BrowserProfile("cookies_test", temp_storage_dir)

        async with EasyBrowser() as browser:
            await browser.goto("https://example.com")

            # 仅保存 cookies
            await profile.save_cookies(browser)

            assert profile.cookies_file.exists()

    @pytest.mark.asyncio
    async def test_save_storage_only(self, temp_storage_dir):
        """测试仅保存 Storage"""
        profile = BrowserProfile("storage_test", temp_storage_dir)

        async with EasyBrowser() as browser:
            await browser.goto("https://example.com")

            # 设置一些 localStorage
            await browser.page.evaluate("localStorage.setItem('test_key', 'test_value')")

            # 仅保存 storage
            await profile.save_storage(browser)

            assert profile.storage_file.exists()

    @pytest.mark.asyncio
    async def test_load_storage(self, temp_storage_dir):
        """测试加载 Storage"""
        profile = BrowserProfile("storage_test", temp_storage_dir)

        # 先保存
        async with EasyBrowser() as browser:
            await browser.goto("https://example.com")
            await browser.page.evaluate("localStorage.setItem('test_key', 'test_value')")
            await profile.save_storage(browser)

        # 再加载
        async with EasyBrowser() as browser:
            await browser.goto("https://example.com")
            loaded = await profile.load_storage(browser)

            assert loaded is True
            # 验证 localStorage 已恢复
            value = await browser.page.evaluate("localStorage.getItem('test_key')")
            assert value == "test_value"

    def test_delete_profile(self, temp_storage_dir):
        """测试删除配置"""
        profile = BrowserProfile("to_delete", temp_storage_dir)

        # 创建配置目录
        profile.profile_dir.mkdir(parents=True, exist_ok=True)
        (profile.profile_dir / "config.json").write_text("{}")

        assert profile.exists()

        # 删除
        result = profile.delete()

        assert result is True
        assert not profile.exists()

    def test_delete_nonexistent_profile(self, temp_storage_dir):
        """测试删除不存在的配置"""
        profile = BrowserProfile("nonexistent", temp_storage_dir)

        result = profile.delete()

        assert result is False

    def test_get_info(self, temp_storage_dir):
        """测试获取配置信息"""
        profile = BrowserProfile("info_test", temp_storage_dir)

        # 不存在时返回 None
        info = profile.get_info()
        assert info is None

        # 创建配置目录
        profile.profile_dir.mkdir(parents=True, exist_ok=True)

        info = profile.get_info()
        assert info is not None
        assert info["name"] == "info_test"
        assert info["has_cookies"] is False
        assert info["has_storage"] is False


class TestProfileManager:
    """测试 ProfileManager"""

    @pytest.fixture
    def temp_storage_dir(self):
        """创建临时存储目录"""
        temp_dir = tempfile.mkdtemp()
        yield temp_dir
        if os.path.exists(temp_dir):
            shutil.rmtree(temp_dir)

    def test_get_profile(self, temp_storage_dir):
        """测试获取配置"""
        manager = ProfileManager(temp_storage_dir)

        profile = manager.get_profile("test")

        assert isinstance(profile, BrowserProfile)
        assert profile.name == "test"

    def test_list_profiles(self, temp_storage_dir):
        """测试列出配置"""
        manager = ProfileManager(temp_storage_dir)

        # 创建几个配置
        for name in ["profile1", "profile2", "profile3"]:
            profile = manager.get_profile(name)
            profile.profile_dir.mkdir(parents=True, exist_ok=True)

        names = manager.list_profiles()

        assert len(names) == 3
        assert "profile1" in names
        assert "profile2" in names
        assert "profile3" in names

    def test_delete_profile(self, temp_storage_dir):
        """测试删除配置"""
        manager = ProfileManager(temp_storage_dir)

        # 创建配置
        profile = manager.get_profile("to_delete")
        profile.profile_dir.mkdir(parents=True, exist_ok=True)

        assert profile.exists()

        # 删除
        result = manager.delete_profile("to_delete")

        assert result is True
        assert not profile.exists()

    def test_get_profile_info(self, temp_storage_dir):
        """测试获取配置信息"""
        manager = ProfileManager(temp_storage_dir)

        # 创建配置
        profile = manager.get_profile("test_info")
        profile.profile_dir.mkdir(parents=True, exist_ok=True)

        info = manager.get_profile_info("test_info")

        assert info is not None
        assert info["name"] == "test_info"


class TestBrowserProfileClassMethods:
    """测试 BrowserProfile 类方法"""

    @pytest.fixture
    def temp_storage_dir(self):
        """创建临时存储目录"""
        temp_dir = tempfile.mkdtemp()
        yield temp_dir
        if os.path.exists(temp_dir):
            shutil.rmtree(temp_dir)

    def test_list_profiles(self, temp_storage_dir):
        """测试类方法列出配置"""
        # 创建几个配置
        for name in ["class_test1", "class_test2"]:
            profile = BrowserProfile(name, temp_storage_dir)
            profile.profile_dir.mkdir(parents=True, exist_ok=True)

        profiles = BrowserProfile.list_profiles(temp_storage_dir)

        assert len(profiles) == 2
        names = [p.name for p in profiles]
        assert "class_test1" in names
        assert "class_test2" in names

    def test_profile_exists(self, temp_storage_dir):
        """测试类方法检查配置存在"""
        # 创建配置
        profile = BrowserProfile("exists_test", temp_storage_dir)
        profile.profile_dir.mkdir(parents=True, exist_ok=True)

        result = BrowserProfile.profile_exists("exists_test", temp_storage_dir)
        assert result is True

        result = BrowserProfile.profile_exists("not_exists", temp_storage_dir)
        assert result is False

    def test_clear_all(self, temp_storage_dir):
        """测试清除所有配置"""
        # 创建几个配置
        for name in ["clear1", "clear2"]:
            profile = BrowserProfile(name, temp_storage_dir)
            profile.profile_dir.mkdir(parents=True, exist_ok=True)

        # 清除
        BrowserProfile.clear_all(temp_storage_dir)

        # 验证目录已删除
        assert not os.path.exists(temp_storage_dir)


if __name__ == "__main__":
    pytest.main([__file__, "-v"])
