import json
import uuid
import subprocess as sp
from pathlib import Path
from datetime import datetime, timezone

def git(*args, cwd=None, capture_output=True, check=False):
    """Git command with args via subprocess"""
    cmd = ["git"] + list(args)
    return sp.run(cmd, cwd=cwd, capture_output=capture_output, text=True, check=check)

def git_output(*args, cwd=None):
    """Return stdout of git command"""
    res = git(*args, cwd=cwd)
    if res.returncode != 0:
        return ""
    return res.stdout.strip()

def add_user(username: str, cwd="."):
    """Creates message log and branch for specified username"""
    # Checking remotes
    remotes = git_output("remote", cwd=cwd)
    if not remotes:
        raise ValueError("No remote found!")

    # Checking branch
    branches = git_output("branch", "--list", username, cwd=cwd)
    if not branches:
        git("checkout", "-b", username, cwd=cwd, check=True)
    else:
        git("checkout", username, cwd=cwd, check=True)
    
    # Create message log
    log_file = Path(cwd) / f"{username}.json"
    if not log_file.exists():
        with open(log_file, "w") as f:
            json.dump([], f)

    # Commit and push changes
    git("add", f"{username}.json", cwd=cwd, check=True)
    # Commit if needed
    status = git_output("status", "--porcelain", cwd=cwd)
    if status:
        git("commit", "-m", "Creating message log", cwd=cwd, check=True)
    git("push", "-u", "origin", username, cwd=cwd, check=True)

def push_message(username, text, cwd="."):
    """Add a new message to username.json, commit and push."""
    log_file = Path(cwd) / f"{username}.json"
    with open(log_file) as f:
        messages = json.load(f)
    messages.append({
        "data": text,
        "timestamp": datetime.now(timezone.utc).timestamp()
    })
    with open(log_file, "w") as f:
        json.dump(messages, f, indent=2)

    git("add", f"{username}.json", cwd=cwd, check=True)
    git("commit", "-m", f"{uuid.uuid4()}", cwd=cwd, check=True)
    git("push", "origin", username, cwd=cwd, check=True)
