# -*- coding: utf-8 -*-
"""/git 命令族集成测试（Phase 7 Tier 1 BF）。

验证 commands/git.py 的 handle_git 在真实 git 仓库场景下能正确解析并展示：
- /git blame <file>
- /git log [N]
- /git stats
- /git show <sha>
- /git 无参数显示 usage
- /git unknown 显示 usage
"""
import os
import subprocess
from pathlib import Path

import pytest

from abyss.commands.git import handle_git


@pytest.fixture
def git_repo(tmp_path: Path, monkeypatch) -> Path:
    """创建临时 git 仓库并写入若干提交。"""
    repo = tmp_path / "repo"
    repo.mkdir()
    env = os.environ.copy()
    env["GIT_AUTHOR_NAME"] = "Tester1"
    env["GIT_AUTHOR_EMAIL"] = "tester1@example.com"
    env["GIT_COMMITTER_NAME"] = "Tester1"
    env["GIT_COMMITTER_EMAIL"] = "tester1@example.com"
    env["GIT_AUTHOR_DATE"] = "2025-01-01T10:00:00"
    env["GIT_COMMITTER_DATE"] = "2025-01-01T10:00:00"

    def _git(*args):
        return subprocess.run(
            ["git", *args], cwd=str(repo), capture_output=True, text=True,
            env=env, timeout=10,
        )

    _git("init", "-q")
    _git("config", "user.name", "Tester1")
    _git("config", "user.email", "tester1@example.com")

    (repo / "file.py").write_text("line1\nline2\nline3\n", encoding="utf-8")
    _git("add", "file.py")
    _git("commit", "-q", "-m", "first commit")

    env["GIT_AUTHOR_NAME"] = "Tester2"
    env["GIT_AUTHOR_EMAIL"] = "tester2@example.com"
    env["GIT_COMMITTER_NAME"] = "Tester2"
    env["GIT_COMMITTER_EMAIL"] = "tester2@example.com"
    (repo / "file.py").write_text("line1\nline2 modified\nline3\n", encoding="utf-8")
    _git("add", "file.py")
    _git("commit", "-q", "-m", "second commit")

    # 切换到该目录
    monkeypatch.chdir(str(repo))
    return repo


class TestGitUsage:
    """用法提示测试。"""

    def test_no_args_returns_usage(self):
        out = handle_git("")
        assert "用法" in out
        assert "blame" in out
        assert "log" in out
        assert "stats" in out
        assert "show" in out

    def test_unknown_subcommand_returns_usage(self):
        out = handle_git("unknown")
        assert "用法" in out


class TestGitBlame:
    """/git blame 测试。"""

    def test_blame_returns_table(self, git_repo):
        out = handle_git("blame file.py")
        assert "行级归因" in out
        assert "Tester1" in out or "Tester2" in out
        assert "line1" in out

    def test_blame_with_line_range(self, git_repo):
        out = handle_git("blame file.py 1-2")
        assert "共 2 行" in out

    def test_blame_nonexistent_file(self, git_repo):
        out = handle_git("blame nonexistent.py")
        assert "无法获取" in out or "[INFO]" in out

    def test_blame_no_file_arg(self, git_repo):
        out = handle_git("blame")
        assert "用法" in out

    def test_blame_invalid_range(self, git_repo):
        out = handle_git("blame file.py abc")
        assert "行范围格式错误" in out


class TestGitLog:
    """/git log 测试。"""

    def test_log_default_returns_recent(self, git_repo):
        out = handle_git("log")
        assert "提交" in out
        assert "second commit" in out  # 最近提交
        assert "first commit" in out

    def test_log_with_limit(self, git_repo):
        out = handle_git("log 1")
        assert "最近 1 条" in out
        assert "second commit" in out
        # 不应包含 first commit
        assert "first commit" not in out

    def test_log_invalid_limit(self, git_repo):
        out = handle_git("log abc")
        assert "ERR" in out

    def test_log_out_of_range(self, git_repo):
        out = handle_git("log 1000")
        assert "ERR" in out


class TestGitStats:
    """/git stats 测试。"""

    def test_stats_returns_table(self, git_repo):
        out = handle_git("stats")
        assert "作者贡献统计" in out
        assert "Tester1" in out
        assert "Tester2" in out
        assert "tester1@example.com" in out


class TestGitShow:
    """/git show 测试。"""

    def test_show_returns_summary(self, git_repo):
        # 获取最近 commit hash
        result = subprocess.run(
            ["git", "rev-parse", "HEAD"],
            cwd=str(git_repo), capture_output=True, text=True, timeout=5,
        )
        sha = result.stdout.strip()
        out = handle_git(f"show {sha}")
        assert "提交摘要" in out
        assert "Tester2" in out
        assert "second commit" in out

    def test_show_no_sha(self, git_repo):
        out = handle_git("show")
        assert "用法" in out

    def test_show_nonexistent_sha(self, git_repo):
        out = handle_git("show nonexistent_sha")
        assert "ERR" in out or "未找到" in out


class TestNonGitRepo:
    """非 git 仓库场景。"""

    def test_blame_in_non_git(self, tmp_path, monkeypatch):
        monkeypatch.chdir(str(tmp_path))
        out = handle_git("blame file.py")
        assert "ERR" in out

    def test_log_in_non_git(self, tmp_path, monkeypatch):
        monkeypatch.chdir(str(tmp_path))
        out = handle_git("log")
        assert "ERR" in out
