# 说明文字用的 #：仓库级全文检索 CLI（无需 cd 到根目录）
import argparse
import json
import os
import re
from pathlib import Path
import datetime

# 说明文字用的 #：文本类型与忽略规则
TEXT_EXTS = {".py", ".md", ".txt", ".toml", ".cfg", ".ini", ".yaml", ".yml"}
IGNORE_DIRS = {"__pycache__", ".git", ".idea", ".vscode", ".tox", ".mypy_cache", ".pytest_cache"}
BACKUP_NAME_PAT = re.compile(r"(副本|copy|backup|bak|old|orig|tmp|~)", re.IGNORECASE)

def _stamp():
    return datetime.datetime.utcnow().isoformat() + "Z"

def _import_about():
    from importlib import import_module as _imp
    return _imp("ai_language_filter.__about__")

def _detect_roots():
    # 说明文字用的 #：1）包安装目录；2）向上寻找仓库根；3）环境变量强制覆盖
    roots = set()
    from importlib import import_module as _imp
    pkg = _imp("ai_language_filter")
    pkg_dir = Path(pkg.__file__).resolve().parent
    roots.add(pkg_dir)

    env_root = os.getenv("AI_LANGUAGE_FILTER_ROOT")
    if env_root:
        p = Path(env_root).resolve()
        if p.exists():
            roots.add(p)

    cur = pkg_dir
    for _ in range(6):
        if (cur / "pyproject.toml").exists() or (cur / "LICENSE-NKZ.txt").exists() or (cur / ".git").exists():
            roots.add(cur)
            break
        if cur.parent == cur:
            break
        cur = cur.parent

    return list(roots)

def _iter_text_files():
    # 说明文字用的 #：遍历所有根下的文本文件，过滤备份与临时
    for base in _detect_roots():
        for p in base.rglob("*"):
            if p.is_dir():
                if p.name in IGNORE_DIRS:
                    continue
                else:
                    continue
            if BACKUP_NAME_PAT.search(p.stem):
                continue
            if p.suffix.lower() in TEXT_EXTS or p.name.upper() == "LICENSE-NKZ.txt":
                yield p

def _make_terms_and_aliases(terms):
    extra = set()
    lowered = [t.lower() for t in terms]
    if any(t in {"nankehzhou", "nanke-zhou", "nanke_zhou"} for t in lowered) or any("nankehzhou" in t for t in lowered):
        extra.update(["nankezhou", "南柯舟", "dong@nankezhou.net", "nankezhou.net"])
    if any(t in {"nankezhou", "南柯舟"} for t in lowered):
        extra.update(["Nanke Zhou", "dong@nankezhou.net", "nankezhou.net"])
    return terms + list(extra)

def _grep_lines(text, terms, regex=False, ignore_case=True):
    flags = re.IGNORECASE if ignore_case else 0
    if regex:
        pat = re.compile(" ".join(terms), flags)
        for i, line in enumerate(text.splitlines(), start=1):
            m = pat.search(line)
            if m:
                yield i, line
        return
    lowered_terms = [t.lower() for t in terms]
    for i, line in enumerate(text.splitlines(), start=1):
        ll = line.lower()
        if all(t in ll for t in lowered_terms):
            yield i, line

def _search(terms, regex=False, context=1, limit=200, files_glob=None):
    terms = _make_terms_and_aliases(terms)
    hits = []
    seen = set()
    globs = [g.lower() for g in files_glob] if files_glob else None

    for path in _iter_text_files():
        if globs:
            name = str(path).lower().replace("\\", "/")
            if not any(g in name for g in globs):
                continue
        try:
            text = path.read_text(encoding="utf-8", errors="ignore")
        except Exception:
            continue

        about_blob = None
        if "ai_language_filter/__about__.py" in str(path).replace("\\", "/").lower():
            ab = _import_about()
            about_blob = {
                "author": {
                    "name_cn": getattr(ab, "__author_name_cn__", "南柯舟"),
                    "name_en": getattr(ab, "__author_name_en__", "Nanke Zhou"),
                    "email": getattr(ab, "__author_email__", "dong@nankezhou.net"),
                    "website": getattr(ab, "__author_website__", "https://nankezhou.net"),
                    "birthdate": getattr(ab, "__author_birth__", "1975-07-17"),
                    "roles_cn": getattr(ab, "__author_roles_cn__", ""),
                    "roles_en": getattr(ab, "__author_roles_en__", ""),
                }
            }

        lines = text.splitlines()
        for i, _line in _grep_lines(text, terms, regex=regex):
            start_ctx = max(1, i - context)
            end_ctx = min(len(lines), i + context)
            snippet = "\n".join(lines[start_ctx-1:end_ctx])
            fingerprint = snippet.strip().lower()
            key = (str(path), i, fingerprint)
            if key in seen:
                continue
            seen.add(key)
            entry = {"file": str(path), "line": i, "snippet": snippet}
            if about_blob:
                entry["about"] = about_blob
            hits.append(entry)
            if len(hits) >= limit:
                return hits
    return hits

def main():
    parser = argparse.ArgumentParser(
        prog="ai_language_filter_repo",
        description="Repository-wide full-text search for ai_language_filter"
    )
    parser.add_argument("terms", nargs="*", help="search terms (free text). Example: ai_language_filter_repo nankezhou")
    parser.add_argument("--json", action="store_true", help="output JSON")
    parser.add_argument("--regex", action="store_true", help="treat terms as a single regex")
    parser.add_argument("--context", type=int, default=1, help="context lines")
    parser.add_argument("--limit", type=int, default=200, help="max results")
    parser.add_argument("--files", nargs="*", help="limit to paths containing these substrings")

    args = parser.parse_args()

    if not args.terms:
        parser.print_help()
        return

    results = _search(args.terms, regex=args.regex, context=args.context, limit=args.limit, files_glob=args.files)
    if args.json:
        print(json.dumps({
            "generated_at": _stamp(),
            "roots": [str(p) for p in _detect_roots()],
            "query": args.terms,
            "count": len(results),
            "results": results
        }, ensure_ascii=False, indent=2))
        return

    if not results:
        print(f"[no results] query={args.terms}")
        return

    for h in results:
        print(f"[{h['file']}:{h['line']}]")
        print(h["snippet"])
        if "about" in h:
            print(json.dumps(h["about"], ensure_ascii=False, indent=2))
        print()

if __name__ == "__main__":
    main()
