# NOVA_CLI/nova_cli/local/file_manager/git_ops.py

import os
from pathlib import Path

import git

from nova_cli import config

# --- GIT INTEGRATION ---
repo_path: Path = Path(os.getcwd())
repo: git.Repo | None = None


def _default_commit_message() -> str:
    return "chore: update files"


def get_repo():
    """Lazily load the repo only when needed."""
    global repo
    try:
        # Check if current dir or any parent is a git repo
        repo = git.Repo(os.getcwd(), search_parent_directories=True)
        return repo
    except (git.exc.InvalidGitRepositoryError, git.exc.NoSuchPathError):
        repo = None
        return None
    
def initialize_repo() -> bool:
    from nova_cli.local.ui import ui
    global repo
    try:
        repo = git.Repo.init(os.getcwd())
        
        # PRO MOVE: Create a default .gitignore if it doesn't exist
        gitignore_path = os.path.join(os.getcwd(), ".gitignore")
        if not os.path.exists(gitignore_path):
            with open(gitignore_path, "w") as f:
                f.write(".nova_history\n__pycache__/\n*.pyc\n.env\n")
        
        ui.print("[green]✔ Git repository initialized with default .gitignore.[/green]")
        return True
    except Exception as e:
        ui.print(f"[red]Failed to initialize Git: {e}[/red]")
        return False

def update_repo_path(new_path: str) -> None:
    """Updates the repo object when user CDs without forcing init."""
    global repo, repo_path
    repo_path = Path(new_path)
    repo = get_repo()

def commit_changes(message: str, filepath: str | None = None, use_semantic: bool = False) -> bool:
    from nova_cli.local.ui import ui
    r = get_repo()
    if not r:
        return False # Silently fail if not a git repo to avoid crashing Auto-Healer

    try:
        if not config.GIT_AUTO_COMMIT:
            return False

        if filepath:
            try:
                # Use 'r' instead of 'repo'
                rel = os.path.relpath(filepath, r.working_dir)
                r.git.add(rel)
            except Exception:
                r.git.add(filepath)
        else:
            r.git.add(u=True)

        if r.is_dirty(untracked_files=False) or filepath:
            final_msg = f"NOVA: {message}"

            if use_semantic and filepath:
                try:
                    diff = r.git.diff(cached=True)
                    if diff:
                        ui.print("[dim cyan]>> Generating semantic commit message...[/dim cyan]")
                        final_msg = _default_commit_message()
                        ui.print(f"[dim]>> Semantic Commit: {final_msg}[/dim]")
                except Exception:
                    pass

            r.index.commit(final_msg)
            ui.print(f"[dim]>> Auto-Commit: {final_msg}[/dim]")

            if config.GIT_AUTO_PUSH:
                perform_push()

            return True

    except Exception as e:
        ui.print(f"[yellow]>> Git Error: {e}[/yellow]")

    return False


def manual_commit(message: str) -> None:
    """Forces a commit regardless of auto settings."""
    from nova_cli.local.ui import ui
    r = get_repo()
    if not r:
        ui.print("[yellow]>> Not a git repository. Use ':gitoptions' to initialize.[/yellow]")
        return
    try:
        r.git.add(".")
        if r.is_dirty(untracked_files=True) or r.index.diff("HEAD"):
            r.index.commit(f"NOVA: {message}")
            ui.print(f"[green]>> Manual Commit Success: {message}[/green]")
        else:
            ui.print("[dim]>> Nothing to commit (clean working tree).[/dim]")
    except Exception as e:
        ui.print(f"[red]>> Commit Failed: {e}[/red]")


def perform_push() -> None:
    from nova_cli.local.ui import ui
    r = get_repo() # Use the lazy loader
    if not r:
        ui.print("[yellow]>> No repository found to push.[/yellow]")
        return
    try:
        if "origin" not in r.remotes:
            ui.print("[yellow]>> No remote 'origin' found. Cannot push.[/yellow]")
            return
        ui.print("[dim]>> Pushing to origin...[/dim]")
        r.remotes.origin.push()
        ui.print("[green]>> Push Complete.[/green]")
    except Exception as e:
        ui.print(f"[red]>> Push Failed: {e}[/red]")


def perform_pull() -> None:
    from nova_cli.local.ui import ui
    """Pulls from origin."""
    r = get_repo()
    if not r:
        ui.print("[yellow]>> Not a git repository.[/yellow]")
        return
        
    try:
        if "origin" not in r.remotes:
            ui.print("[yellow]>> No remote 'origin' found. Cannot pull.[/yellow]")
            return

        ui.print("[dim]>> Pulling from origin...[/dim]")
        r.remotes.origin.pull()
        ui.print("[green]>> Pull Complete.[/green]")
    except Exception as e:
        ui.print(f"[red]>> Pull Failed: {e}[/red]")


def git_status() -> None:
    from nova_cli.local.ui import ui
    """Prints current git status."""
    r = get_repo()
    if not r:
        ui.print("[dim]>> Not a git repository.[/dim]")
        return
    try:
        if r.is_dirty(untracked_files=True):
            ui.print(f"[yellow]{r.git.status()}[/yellow]")
        else:
            ui.print("[green]Git Status: Clean working tree.[/green]")
    except Exception as e:
        ui.print(f"[red]{e}[/red]")
