#!/usr/bin/env python3

import argparse
from dataclasses import dataclass
import re
import subprocess

REMOTE_TYPES = [
    {
        # github
        "match": re.compile(r'git@github.com:(?P<username>[\w\.-]+)/(?P<project>[\w\.-]+).git'),
        "format-branch": lambda g: f"https://github.com/{g.username}/{g.project}/tree/{g.branch}/",
        "format-commit": lambda g: f"https://github.com/{g.username}/{g.project}/commit/{g.commit}/",
    },
    {
        # gitea
        "match": re.compile(r'(?P<gituser>[\w\.-]+)@(?P<host>[\w\.-]+):(?P<username>[\w\.-]+)/(?P<project>[\w\.-]+).git'),
        "format-branch": lambda g: f"https://{g.host}/{g.username}/{g.project}/src/branch/{g.branch}/",
        "format-commit": lambda g: f"https://{g.host}/{g.username}/{g.project}/commit/{g.commit}/",
    },
]

@dataclass
class FormatArgs:
    gituser: str = None
    host: str = None
    username: str = None
    project: str = None
    commit: str = None
    branch: str = None

def get_remote_branch():
    s = subprocess.run(["git", "status", "--porcelain", "-uno", "-b", "--no-ahead-behind"], capture_output=True, text=True)

    git_status_branch_info = s.stdout.splitlines()[0][3:].split()[0]

    branches = git_status_branch_info.split("...")

    if len(branches) != 2:
        raise Exception("no branch name found")

    local_branch, remote_branch = branches

    remote, branch = remote_branch.split("/")

    return {
        "remote": remote,
        "branch": branch,
    }

def get_remote_url(remote):
    s = subprocess.run(["git", "remote", "get-url", remote], capture_output=True, text=True)

    remote_url = s.stdout.strip()

    return remote_url

def get_last_commit():
    s = subprocess.run(["git", "rev-parse", "HEAD"], capture_output=True, text=True)

    commit = s.stdout.strip()

    return commit

def main():
    parser = argparse.ArgumentParser(
        prog='git-show-link',
    )

    parser.add_argument("--branch", dest="display_branch", action='store_true', help="Display link to branch, instead to commit")

    args = parser.parse_args()

    r = get_remote_branch()

    remote_url = get_remote_url(r["remote"])

    for remote_type in REMOTE_TYPES:
        m = remote_type["match"].match(remote_url)

        if m is None:
            continue

        g = FormatArgs(**m.groupdict())

        if args.display_branch:
            g.branch = r["branch"]
            print(remote_type["format-branch"](g))
        else:
            commit = get_last_commit()
            g.commit = commit
            print(remote_type["format-commit"](g))
        break


if __name__ == "__main__":
    main()