"""Base runner - Tum runner'lar icin ortak yardimci fonksiyonlar."""
import os
import re
from pathlib import Path
from typing import List, Dict, Tuple

from nazar.runners.ignore_manager import IgnoreManager

IGNORE_DIRS = {"node_modules", ".git", "build", "dist", "Pods", ".gradle", "vendor", "venv", ".venv", "__pycache__", ".expo", "coverage"}
SOURCE_EXTS = {".js", ".jsx", ".ts", ".tsx", ".py", ".dart", ".swift", ".kt", ".java", ".go", ".rs", ".rb", ".php", ".cs"}


class BaseRunner:
    def __init__(self, project_path: str):
        self.root = Path(project_path).resolve()
        self._source_cache: List[str] = []
        self._ignore_manager = None

    @property
    def ignore_manager(self) -> IgnoreManager:
        if self._ignore_manager is None:
            self._ignore_manager = IgnoreManager(str(self.root))
        return self._ignore_manager

    def src_files(self) -> List[str]:
        if self._source_cache:
            return self._source_cache
        for root_dir, dirs, files in os.walk(self.root):
            dirs[:] = [d for d in dirs if d not in IGNORE_DIRS]
            for f in files:
                if Path(f).suffix.lower() in SOURCE_EXTS:
                    self._source_cache.append(os.path.relpath(os.path.join(root_dir, f), self.root))
        return self._source_cache

    def read(self, rel_path: str) -> str:
        try:
            return (self.root / rel_path).read_text(errors="ignore")
        except Exception:
            return ""

    def scan_pattern(self, pattern: str, flags=re.IGNORECASE | re.MULTILINE, skip_test=True, skip_env=True, skip_nazar=True, limit=200, subtype: str = "") -> List[Dict]:
        hits = []
        for f in self.src_files()[:limit]:
            if skip_test and ("test" in f.lower() or "spec" in f.lower()):
                continue
            if skip_env and f.startswith(".env"):
                continue
            if skip_nazar and f.startswith("nazar/"):
                continue
            if self.ignore_manager.is_file_ignored(f):
                continue
            content = self.read(f)
            for m in re.finditer(pattern, content, flags):
                hits.append({"file": f, "line": content[:m.start()].count("\n") + 1, "match": m.group()[:80].replace("\n", " ").replace("\r", "")})
        if subtype:
            hits = self.ignore_manager.filter_hits(hits, subtype)
        return hits
