"""doc.py 模块单元测试。"""
import unittest
from unittest.mock import MagicMock, patch
from pathlib import Path
import tempfile
import shutil

import sys

_ROOT = Path(__file__).resolve().parents[1]
_SRC = _ROOT / "src"
if str(_SRC) not in sys.path:
    sys.path.insert(0, str(_SRC))

from taolib.doc import (
    clean,
    build,
    intl,
    doctest,
    tree,
    create_docs,
    sites,
    multi_sites,
    _get_sphinx_paths,
)
from invoke.context import Context
from invoke.collection import Collection


class TestGetSphinxPaths(unittest.TestCase):
    """测试 _get_sphinx_paths 函数。"""

    def test_default_values(self) -> None:
        """测试默认值。"""
        ctx = Context()
        source, target = _get_sphinx_paths(ctx, None, None)
        self.assertEqual(source, "doc")
        self.assertEqual(target, "doc/_build/html")

    def test_custom_values(self) -> None:
        """测试自定义值。"""
        ctx = Context()
        source, target = _get_sphinx_paths(ctx, "custom_src", "custom_target")
        self.assertEqual(source, "custom_src")
        self.assertEqual(target, "custom_target")

    def test_context_config(self) -> None:
        """测试从上下文读取配置。"""
        ctx = Context()
        ctx.sphinx = MagicMock()
        ctx.sphinx.source = "ctx_source"
        ctx.sphinx.target = "ctx_target"
        source, target = _get_sphinx_paths(ctx, None, None)
        self.assertEqual(source, "ctx_source")
        self.assertEqual(target, "ctx_target")


class TestClean(unittest.TestCase):
    """测试 clean 任务。"""

    def test_clean_nonexistent_directory(self) -> None:
        """测试清理不存在的目录。"""
        ctx = Context()
        ctx.sphinx = MagicMock()
        ctx.sphinx.target = "/nonexistent/path"
        clean(ctx)

    def test_clean_existing_directory(self) -> None:
        """测试清理存在的目录。"""
        with tempfile.TemporaryDirectory() as temp_dir:
            target_dir = Path(temp_dir) / "_build"
            target_dir.mkdir()
            (target_dir / "test.txt").write_text("test")

            ctx = Context()
            ctx.sphinx = MagicMock()
            ctx.sphinx.target = str(target_dir)
            clean(ctx)

            self.assertFalse(target_dir.exists())


class TestBuild(unittest.TestCase):
    """测试 build 任务。"""

    @patch("taolib.doc.ctx.run")
    def test_build_default_params(self, mock_run: MagicMock) -> None:
        """测试默认参数构建。"""
        ctx = Context()
        ctx.sphinx = MagicMock()
        ctx.sphinx.source = "doc"
        ctx.sphinx.target = "doc/_build/html"
        ctx.run = MagicMock(return_value=None)

        with self.assertRaises(Exception):
            build(ctx)

    def test_build_with_language(self) -> None:
        """测试带语言参数的构建。"""
        ctx = Context()
        ctx.sphinx = MagicMock()
        ctx.sphinx.source = "doc"
        ctx.sphinx.target = "doc/_build/html"
        ctx.run = MagicMock(return_value=None)

        with self.assertRaises(Exception):
            build(ctx, language="en")


class TestCreateDocs(unittest.TestCase):
    """测试 create_docs 函数。"""

    def test_create_docs_single_project(self) -> None:
        """测试单项目配置。"""
        namespace = create_docs(source="doc", target="doc/_build/html")
        self.assertIsInstance(namespace, Collection)

    def test_create_docs_with_list(self) -> None:
        """测试列表形式的多项目配置。"""
        configs = [
            {"name": "project1", "source": "doc1", "target": "build1"},
            {"name": "project2", "source": "doc2", "target": "build2"},
        ]
        namespace = create_docs(configs)
        self.assertIsInstance(namespace, Collection)

    def test_create_docs_with_dict(self) -> None:
        """测试字典形式的多项目配置。"""
        configs = {
            "project1": {"source": "doc1", "target": "build1"},
            "project2": {"source": "doc2", "target": "build2"},
        }
        namespace = create_docs(configs)
        self.assertIsInstance(namespace, Collection)


class TestSites(unittest.TestCase):
    """测试 sites 函数。"""

    def test_sites_returns_collection(self) -> None:
        """测试 sites 返回 Collection。"""
        namespace = sites(source="doc", target="doc/_build/html")
        self.assertIsInstance(namespace, Collection)


class TestMultiSites(unittest.TestCase):
    """测试 multi_sites 函数。"""

    def test_multi_sites_returns_collection(self) -> None:
        """测试 multi_sites 返回 Collection。"""
        configs = {
            "project1": {"source": "doc1", "target": "build1"},
        }
        namespace = multi_sites(configs)
        self.assertIsInstance(namespace, Collection)


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