#!/usr/bin/env python3
"""Get git diff in a single git file for the closest git repo in the file system
NOTE: Since this is run as a script, there should be no imports from project files!
"""

import json
import os
import subprocess
import sys
from pathlib import Path

MAX_FILE_SIZE_FOR_GIT_DIFF = 1024 * 1024  # 1 Mb


def get_closest_git_repo(path: Path) -> Path | None:
    while True:
        path = path.parent
        git_path = Path(path, '.git')
        if git_path.is_dir():
            return path
        if path.parent == path:
            return None


def run(cmd: str, cwd: str) -> str:
    result = subprocess.run(
        args=cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE, cwd=cwd
    )
    byte_content = result.stderr or result.stdout or b''

    if result.returncode != 0:
        raise RuntimeError(
            f'error_running_cmd:{result.returncode}:{byte_content.decode()}'
        )
    return byte_content.decode().strip()


def get_valid_ref(repo_dir: str) -> str | None:
    refs = []
    try:
        current_branch = run('git --no-pager rev-parse --abbrev-ref HEAD', repo_dir)
        refs.append(f'origin/{current_branch}')
    except RuntimeError:
        pass

    try:
        default_branch = (
            run('git --no-pager remote show origin | grep "HEAD branch"', repo_dir)
            .split()[-1]
            .strip()
        )
        ref_non_default_branch = f'$(git --no-pager merge-base HEAD "$(git --no-pager rev-parse --abbrev-ref origin/{default_branch})")'
        ref_default_branch = f'origin/{default_branch}'
        refs.append(ref_non_default_branch)
        refs.append(ref_default_branch)
    except RuntimeError:
        pass

    # compares with empty tree
    ref_new_repo = (
        '$(git --no-pager rev-parse --verify 4b825dc642cb6eb9a060e54bf8d69288fbee4904)'
    )
    refs.append(ref_new_repo)

    # Find a ref that exists...
    for ref in refs:
        try:
            result = run(f'git --no-pager rev-parse --verify {ref}', repo_dir)
            return result
        except RuntimeError:
            # invalid ref - try next
            continue

    return None


def get_git_diff(relative_file_path: str) -> dict[str, str]:
    path = Path(os.getcwd(), relative_file_path).resolve()
    if os.path.getsize(path) > MAX_FILE_SIZE_FOR_GIT_DIFF:
        raise ValueError('file_to_large')
    closest_git_repo = get_closest_git_repo(path)
    if not closest_git_repo:
        raise ValueError('no_repository')
    current_rev = get_valid_ref(str(closest_git_repo))
    try:
        original = run(
            f'git show "{current_rev}:{path.relative_to(closest_git_repo)}"',
            str(closest_git_repo),
        )
    except RuntimeError:
        original = ''
    try:
        with open(path, 'r') as f:
            modified = '\n'.join(f.read().splitlines())
    except FileNotFoundError:
        modified = ''
    return {
        'modified': modified,
        'original': original,
    }


if __name__ == '__main__':
    diff = get_git_diff(sys.argv[-1])
    print(json.dumps(diff))
