# -*- coding: utf-8 -*-
"""CodeAgent 内置规则模块

提供一些优秀的开发实践规则，如 TDD、代码审查、重构等。
支持使用 jinja2 模板语法在规则文件中使用内置变量。
"""

import os
import subprocess
from pathlib import Path
import jinja2
from jinja2 import TemplateError, TemplateSyntaxError


def render_rule_template(rule_content: str, rule_file_dir: str) -> str:
    """使用jinja2渲染规则模板

    参数:
        rule_content: 规则原始内容
        rule_file_dir: 规则文件所在目录

    返回:
        str: 渲染后的内容，如果渲染失败则返回原始内容
    """
    if not rule_content:
        return rule_content

    # 构建jinja2上下文变量
    context = {
        "current_dir": Path.cwd().as_posix(),
        "script_dir": Path(__file__).parent.as_posix(),  # 当前脚本所在目录
        "jarvis_data_dir": _get_jarvis_data_dir(),
        "jarvis_src_dir": _get_jarvis_src_dir(),
        "git_root_dir": _get_git_root(),
        "rule_file_dir": rule_file_dir,  # 当前规则文件所在目录
    }

    # 使用jinja2渲染模板
    try:
        template = jinja2.Template(rule_content)
        return template.render(**context).strip()
    except (TemplateError, TemplateSyntaxError):
        # 渲染失败时返回原始内容（向后兼容）
        return rule_content.strip()
    except Exception:
        # 其他异常（如内存错误等）也返回原始内容
        return rule_content.strip()


# 获取git根目录
def _get_git_root() -> str:
    """获取git根目录

    如果当前目录不在git仓库中，将返回当前工作目录作为回退值。

    返回:
        str: git根目录的绝对路径（如果不在git仓库中则返回当前工作目录）
    """
    try:
        result = subprocess.run(
            ["git", "rev-parse", "--show-toplevel"],
            capture_output=True,
            text=True,
            check=False,
        )
        if result.returncode == 0:
            return result.stdout.strip()
    except (FileNotFoundError, subprocess.SubprocessError):
        pass
    # 不在git仓库中，返回当前工作目录
    return os.getcwd()


# 获取jarvis源码目录
def _get_jarvis_src_dir() -> str:
    """获取jarvis源码目录

    返回:
        str: jarvis源码目录的绝对路径
    """
    # 从当前文件位置向上定位到项目根目录
    # src/jarvis/jarvis_code_agent/builtin_rules.py -> 项目根目录
    return str(Path(__file__).parent.parent.parent.parent.resolve())


# 获取jarvis数据目录
def _get_jarvis_data_dir() -> str:
    """获取jarvis数据目录

    返回:
        str: jarvis数据目录路径
    """
    try:
        from jarvis.jarvis_utils.config import get_data_dir

        return get_data_dir()
    except ImportError:
        # 如果导入失败，返回默认路径
        return os.path.expanduser("~/.jarvis")


# 内置规则字典：规则名称 -> 规则内容
# 此字典将在模块加载时通过 _load_builtin_rules() 函数动态填充
BUILTIN_RULES: dict[str, str] = {}


def _load_rules_from_directory(directory: Path) -> None:
    """从指定目录加载规则文件，支持jinja2模板渲染

    参数:
        directory: 规则文件所在目录
    """
    if not directory.exists():
        return

    for rule_file in directory.glob("*.md"):
        rule_name = rule_file.stem  # 去掉 .md 后缀
        try:
            with open(rule_file, "r", encoding="utf-8") as f:
                rule_content = f.read().strip()
                # 使用通用的渲染函数
                rendered_content = render_rule_template(
                    rule_content, rule_file.parent.as_posix()
                )
                if rendered_content:
                    BUILTIN_RULES[rule_name] = rendered_content
        except Exception:
            # 忽略加载失败的文件，不影响其他规则
            continue


def _load_builtin_rules() -> None:
    """加载所有内置规则"""
    # 获取当前文件所在的项目根目录
    # 从 src/jarvis/jarvis_code_agent/builtin_rules.py 定位到项目根
    project_root = Path(__file__).parent.parent.parent.parent
    builtin_dir = project_root / "builtin"

    # 加载通用规则（rules 目录）
    _load_rules_from_directory(builtin_dir / "rules")

    # 加载测试规则（test_rules 目录）
    _load_rules_from_directory(builtin_dir / "test_rules")


# 在模块加载时自动加载所有规则
_load_builtin_rules()


def get_builtin_rule(rule_name: str) -> str | None:
    """获取内置规则

    参数:
        rule_name: 规则名称（不区分大小写）

    返回:
        str: 规则内容，如果未找到则返回 None
    """
    return BUILTIN_RULES.get(rule_name.lower())


def list_builtin_rules() -> list[str]:
    """列出所有可用的内置规则名称

    返回:
        list[str]: 规则名称列表
    """
    return list(BUILTIN_RULES.keys())
