"""Git commit history sensor."""

from __future__ import annotations

import subprocess
from collections import deque
from pathlib import Path

from neurovault.sensors.base import BaseSensor


class GitSensor(BaseSensor):
    """Monitor git repositories for recent commits."""

    name = "git"
    source_tag = "git"
    poll_interval = 600

    def __init__(self, repo_paths: list[str] | None = None):
        self._repo_paths = repo_paths or []
        self._seen_commits: deque[str] = deque(maxlen=200)
        if not self._repo_paths:
            self._repo_paths = self._discover_repos()

    def _discover_repos(self) -> list[str]:
        search_dirs = [
            Path.home() / "Projects",
            Path.home() / "Documents",
            Path.home() / "code",
            Path.home() / "dev",
        ]
        repos: list[str] = []
        for directory in search_dirs:
            if not directory.exists():
                continue
            for git_dir in directory.rglob(".git"):
                if git_dir.is_dir() and len(repos) < 20:
                    repos.append(str(git_dir.parent))
        return repos

    def poll(self) -> list[tuple[str, dict]]:
        results: list[tuple[str, dict]] = []
        for repo_path in self._repo_paths:
            for commit in self._read_commits(repo_path):
                key = f"{repo_path}:{commit['hash']}"
                if key in self._seen_commits:
                    continue
                self._seen_commits.append(key)
                repo_name = Path(repo_path).name
                content = (
                    f"Git commit in {repo_name}: {commit['message']}\n"
                    f"Author: {commit['author']}\n"
                    f"Files changed: {commit.get('stats', 'N/A')}"
                )
                results.append(
                    (
                        content,
                        {
                            "repo": repo_name,
                            "commit_hash": commit["hash"],
                            "author": commit["author"],
                            "content_type": "code",
                        },
                    )
                )
        return results

    def _read_commits(self, repo_path: str) -> list[dict]:
        try:
            result = subprocess.run(
                ["git", "log", "--since=30m", "--format=%H|%s|%an", "--shortstat", "--no-color"],
                cwd=repo_path,
                capture_output=True,
                text=True,
                timeout=10,
            )
            if result.returncode != 0:
                return []
            commits: list[dict] = []
            lines = result.stdout.strip().split("\n")
            current: dict | None = None
            for line in lines:
                line = line.strip()
                if not line:
                    continue
                if "|" in line:
                    parts = line.split("|", 2)
                    if len(parts) == 3:
                        current = {
                            "hash": parts[0][:8],
                            "message": parts[1],
                            "author": parts[2],
                            "stats": "N/A",
                        }
                        commits.append(current)
                    continue
                if current is not None and "file changed" in line:
                    current["stats"] = line
            return commits
        except Exception:
            return []
