"""
Git context gathering utilities.

Extracts Git repository state including:
- Current branch and clean status
- Recent commits
- Upstream tracking status
- Task ID extraction from branch name
"""

import re
import subprocess
from datetime import datetime
from pathlib import Path
from typing import Optional

from lightwave.context.context_models import Commit, GitContext, UpstreamStatus


def extract_task_id_from_branch(branch_name: str) -> Optional[str]:
    """Extract task ID from branch name.

    Expected pattern: feature/<task-id>-description

    Args:
        branch_name: Git branch name

    Returns:
        8-character hex task ID if found, None otherwise

    Examples:
        >>> extract_task_id_from_branch("feature/97c8b710-add-auth")
        "97c8b710"
        >>> extract_task_id_from_branch("main")
        None
    """
    match = re.search(r"[a-f0-9]{8}", branch_name)
    return match.group(0) if match else None


def get_recent_commits(limit: int = 10, cwd: Optional[Path] = None) -> list[Commit]:
    """Get recent commits from current branch.

    Args:
        limit: Maximum number of commits to retrieve
        cwd: Working directory (default: current directory)

    Returns:
        List of Commit objects
    """
    try:
        # Format: hash|author|timestamp|message
        result = subprocess.run(
            ["git", "log", f"-{limit}", "--pretty=format:%H|%an|%at|%s"],
            cwd=cwd,
            capture_output=True,
            text=True,
            check=True,
        )

        commits = []
        for line in result.stdout.strip().split("\n"):
            if not line:
                continue
            parts = line.split("|", 3)
            if len(parts) == 4:
                hash_, author, timestamp_str, message = parts
                commits.append(
                    Commit(
                        hash=hash_,
                        author=author,
                        timestamp=datetime.fromtimestamp(int(timestamp_str)),
                        message=message,
                    )
                )

        return commits
    except subprocess.CalledProcessError:
        return []


def get_upstream_status(cwd: Optional[Path] = None) -> Optional[UpstreamStatus]:
    """Get status relative to upstream branch.

    Args:
        cwd: Working directory (default: current directory)

    Returns:
        UpstreamStatus if tracking upstream, None otherwise
    """
    try:
        # Get upstream branch
        result = subprocess.run(
            ["git", "rev-parse", "--abbrev-ref", "--symbolic-full-name", "@{upstream}"],
            cwd=cwd,
            capture_output=True,
            text=True,
            check=True,
        )
        tracking = result.stdout.strip()

        if not tracking:
            return None

        # Get ahead/behind counts
        result = subprocess.run(
            ["git", "rev-list", "--left-right", "--count", f"{tracking}...HEAD"],
            cwd=cwd,
            capture_output=True,
            text=True,
            check=True,
        )

        parts = result.stdout.strip().split()
        if len(parts) == 2:
            behind, ahead = map(int, parts)
            return UpstreamStatus(ahead=ahead, behind=behind, tracking=tracking)

        return None
    except subprocess.CalledProcessError:
        return None


def get_git_context(cwd: Optional[Path] = None) -> Optional[GitContext]:
    """Build GitContext from current working directory.

    Args:
        cwd: Working directory (default: current directory)

    Returns:
        GitContext if in a git repository, None otherwise
    """
    try:
        # Check if we're in a git repo
        subprocess.run(
            ["git", "rev-parse", "--git-dir"],
            cwd=cwd,
            capture_output=True,
            check=True,
        )

        # Get repo name
        result = subprocess.run(
            ["git", "remote", "get-url", "origin"],
            cwd=cwd,
            capture_output=True,
            text=True,
            check=True,
        )
        origin_url = result.stdout.strip()
        # Extract repo name from URL (e.g., git@github.com:user/repo.git -> repo)
        repo_name = origin_url.split("/")[-1].replace(".git", "")

        # Get current branch
        result = subprocess.run(
            ["git", "rev-parse", "--abbrev-ref", "HEAD"],
            cwd=cwd,
            capture_output=True,
            text=True,
            check=True,
        )
        branch = result.stdout.strip()

        # Check if working directory is clean
        result = subprocess.run(
            ["git", "status", "--porcelain"],
            cwd=cwd,
            capture_output=True,
            text=True,
            check=True,
        )
        is_clean = len(result.stdout.strip()) == 0

        # Get recent commits
        recent_commits = get_recent_commits(limit=10, cwd=cwd)

        # Get upstream status
        upstream_status = get_upstream_status(cwd=cwd)

        # Extract task ID from branch name
        task_id_from_branch = extract_task_id_from_branch(branch)

        return GitContext(
            repo=repo_name,
            branch=branch,
            is_clean=is_clean,
            recent_commits=recent_commits,
            upstream_status=upstream_status,
            task_id_from_branch=task_id_from_branch,
        )

    except subprocess.CalledProcessError:
        # Not a git repository or git command failed
        return None
