from datetime import datetime as dt
from pathlib import Path

from git import Repo

from mmar_envops.stdout import COL_DUMMY


def get_git_root(path: Path) -> Path | None:
    """Find the git repository root directory by searching upwards from path."""
    while True:
        if (path / ".git").is_dir():
            return path
        parent = path.parent
        if path == parent:
            return None
        path = parent
    return None


def colored_git_status(repo_path, col=COL_DUMMY) -> str:
    repo = Repo(repo_path)

    staged = repo.index.diff(repo.head.commit)
    unstaged = repo.index.diff(None)
    untracked = repo.untracked_files
    if not staged and not unstaged and not unstaged:
        return ""

    res_lines = []

    if staged:
        for diff in staged:
            change_type = diff.change_type
            if change_type == "A":
                change_type = "D "
            elif change_type == "D":
                change_type = "A "
            elif change_type == "M":
                change_type = "M "
            elif change_type == "R":
                change_type = "R "
            change_type = col.green(change_type)
            res_lines.append(f"{change_type} {repo_path}/{diff.a_path}")

    if unstaged:
        for diff in unstaged:
            change_type = " " + diff.change_type
            change_type = col.red(change_type)
            res_lines.append(f"{change_type} {repo_path}/{diff.a_path}")

    if untracked:
        for u_file in untracked:
            change_type = "??"
            change_type = col.red(change_type)
            res_lines.append(f"{change_type} {repo_path}/{u_file}")
    return "\n".join(res_lines)


def get_current_ref(repo_path):
    repo = Repo(repo_path)
    if repo.head.is_detached:
        return repo.head.commit.hexsha[:7]
    else:
        return repo.active_branch.name


def is_changes_pushed(repo, last_commit):
    # deep-seek, looks clumsy but whatever, it works
    try:
        for remote in repo.remotes:
            remote_refs = list(remote.refs)
            for ref in remote_refs:
                try:
                    if ref.commit.hexsha == last_commit.hexsha:
                        return True
                except Exception:
                    pass
    except Exception:
        pass
    return False


def get_last_commit_info(repo_path: str, col=COL_DUMMY) -> str:
    """
    Returns last commit info in compact format:
    YYYY-MM-DD--HH-MM HASH <email> first_line_of_message

    If the commit is only local (not pushed to remote), appends '/ UNPUSHED'

    Example: '2025-03-31--17-33 7f62927 <name@example.com> dev: updated version'
    Example with unpushed: '2025-03-31--17-33 7f62927 <name@example.com> dev: updated version / UNPUSHED'
    """
    repo = Repo(repo_path)
    last_commit = repo.head.commit
    is_pushed = is_changes_pushed(repo, last_commit)

    # Format components
    date_str = dt.fromtimestamp(last_commit.committed_date).strftime("%Y-%m-%d--%H-%M")
    short_hash = last_commit.hexsha[:7]
    email = last_commit.author.email
    message = last_commit.message.split("\n")[0].strip()  # First line only

    # Build result
    result = f"{date_str} {short_hash} <{email}> {message}"
    if not is_pushed:
        result += col.red(" / UNPUSHED")

    return result
