#!/usr/bin/env python3
"""
Gitea Sync - Automatically sync repositories to Gitea

Creates/updates repositories and pushes code automatically.
Auto-detects new vs existing repositories.

Usage:
    python3 sync.py --repo my-website --path ./my-website
"""

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


def load_env():
    """Load environment from .env file."""
    env_path = Path(__file__).parent / ".env"
    if env_path.exists():
        for line in env_path.read_text().splitlines():
            line = line.strip()
            if line and not line.startswith("#") and "=" in line:
                k, v = line.split("=", 1)
                os.environ.setdefault(k.strip(), v.strip().strip("\"'"))


load_env()

GITEA_URL = os.environ.get("GITEA_URL", "https://git.moreminimore.com")
GITEA_API_TOKEN = os.environ.get("GITEA_API_TOKEN")
GITEA_USERNAME = os.environ.get("GITEA_USERNAME")


def check_auth():
    """Verify Gitea authentication."""
    if not GITEA_API_TOKEN:
        print("Error: GITEA_API_TOKEN not set", file=sys.stderr)
        sys.exit(1)
    
    response = requests.get(
        f"{GITEA_URL}/api/v1/user",
        headers={"Authorization": f"token {GITEA_API_TOKEN}"}
    )
    
    if response.status_code != 200:
        print(f"Error: Gitea authentication failed ({response.status_code})", file=sys.stderr)
        print(f"Check your API token at: {GITEA_URL}/user/settings/applications", file=sys.stderr)
        sys.exit(1)
    
    user = response.json()
    return user.get("login", GITEA_USERNAME)


def repo_exists(username, repo_name):
    """Check if repository exists on Gitea."""
    response = requests.get(
        f"{GITEA_URL}/api/v1/repos/{username}/{repo_name}",
        headers={"Authorization": f"token {GITEA_API_TOKEN}"}
    )
    return response.status_code == 200


def create_repo(repo_name, description="", private=False):
    """Create new repository on Gitea."""
    print(f"📦 Creating repository: {repo_name}")
    
    data = {
        "name": repo_name,
        "description": description,
        "private": private,
        "auto_init": True,
        "readme": "Default",
        "default_branch": "main"
    }
    
    response = requests.post(
        f"{GITEA_URL}/api/v1/user/repos",
        headers={"Authorization": f"token {GITEA_API_TOKEN}"},
        json=data
    )
    
    if response.status_code == 201:
        print(f"✅ Repository created: {repo_name}")
        return response.json()
    elif response.status_code == 409:
        print(f"⚠️  Repository already exists: {repo_name}")
        return None
    else:
        print(f"❌ Failed to create repository: {response.text}", file=sys.stderr)
        sys.exit(1)


def update_repo(repo_name, description=""):
    """Update existing repository."""
    print(f"🔄 Updating repository: {repo_name}")
    
    data = {
        "description": description,
        "website": "",
        "has_issues": True,
        "has_pull_requests": True,
        "has_wiki": False
    }
    
    response = requests.patch(
        f"{GITEA_URL}/api/v1/repos/{GITEA_USERNAME}/{repo_name}",
        headers={"Authorization": f"token {GITEA_API_TOKEN}"},
        json=data
    )
    
    if response.status_code == 200:
        print(f"✅ Repository updated: {repo_name}")
        return response.json()
    else:
        print(f"⚠️  Could not update repository: {response.text}")
        return None


def get_repo_url(username, repo_name):
    """Get HTTPS URL for repository."""
    return f"{GITEA_URL}/{username}/{repo_name}.git"


def is_git_repo(path):
    """Check if directory is a git repository."""
    git_dir = Path(path) / ".git"
    return git_dir.exists()


def push_code(repo_path, git_url, branch="main"):
    """Push code to Gitea repository."""
    repo_path = Path(repo_path)
    
    if not repo_path.exists():
        print(f"Error: Path does not exist: {repo_path}", file=sys.stderr)
        sys.exit(1)
    
    print(f"🚀 Pushing code to Gitea...")
    
    # Initialize git if needed
    if not is_git_repo(repo_path):
        print("  → Initializing git repository")
        subprocess.run(["git", "init"], cwd=repo_path, check=True, capture_output=True)
    
    # Configure git to use token for authentication
    # This avoids interactive password prompts
    subprocess.run(
        ["git", "config", "credential.helper", "store"],
        cwd=repo_path,
        check=True,
        capture_output=True
    )
    
    # Add .gitignore if not exists
    gitignore = repo_path / ".gitignore"
    if not gitignore.exists():
        with open(gitignore, "w") as f:
            f.write("""node_modules
dist
.env
.astro
*.db
*.log
.DS_Store
""")
    
    # Add remote if not exists
    result = subprocess.run(
        ["git", "remote", "get-url", "origin"],
        cwd=repo_path,
        capture_output=True
    )
    
    if result.returncode != 0:
        print(f"  → Adding remote: {git_url}")
        # Use token in URL for authentication
        auth_url = git_url.replace(
            f"{GITEA_URL}/",
            f"{GITEA_URL}/{GITEA_API_TOKEN}:@"
        )
        subprocess.run(
            ["git", "remote", "add", "origin", auth_url],
            cwd=repo_path,
            check=True,
            capture_output=True
        )
    else:
        # Update existing remote with auth
        auth_url = git_url.replace(
            f"{GITEA_URL}/",
            f"{GITEA_URL}/{GITEA_API_TOKEN}:@"
        )
        subprocess.run(
            ["git", "remote", "set-url", "origin", auth_url],
            cwd=repo_path,
            check=True,
            capture_output=True
        )
    
    # Add all files
    print("  → Adding files")
    subprocess.run(["git", "add", "."], cwd=repo_path, check=True, capture_output=True)
    
    # Check if there are changes to commit
    result = subprocess.run(
        ["git", "status", "--porcelain"],
        cwd=repo_path,
        capture_output=True,
        text=True
    )
    
    if result.stdout.strip():
        # Commit changes
        print("  → Committing changes")
        subprocess.run(
            ["git", "commit", "-m", "Auto-sync from website-creator"],
            cwd=repo_path,
            check=True,
            capture_output=True
        )
        
        # Set main as default branch
        subprocess.run(
            ["git", "branch", "-M", branch],
            cwd=repo_path,
            check=True,
            capture_output=True
        )
        
        # Push with force to handle initial push
        print("  → Pushing to Gitea")
        result = subprocess.run(
            ["git", "push", "-u", "-f", "origin", branch],
            cwd=repo_path,
            capture_output=True,
            text=True
        )
        
        if result.returncode == 0:
            print(f"✅ Code pushed successfully")
            return True
        else:
            print(f"⚠️  Push output: {result.stderr}")
            # Try without -f if it fails
            subprocess.run(
                ["git", "push", "-u", "origin", branch],
                cwd=repo_path,
                capture_output=True
            )
            print(f"✅ Code pushed (without force)")
            return True
    else:
        print(f"ℹ️  No changes to push")
        return True


def sync_repo(repo_name, repo_path, description="", auto_push=True):
    """Complete sync workflow."""
    
    # Step 1: Check auth
    username = check_auth()
    print(f"🔐 Authenticated as: {username}")
    print("")
    
    # Step 2: Check if repo exists
    exists = repo_exists(username, repo_name)
    
    if exists:
        update_repo(repo_name, description)
    else:
        create_repo(repo_name, description)
    
    print("")
    
    # Step 3: Push code
    if auto_push:
        git_url = get_repo_url(username, repo_name)
        push_code(repo_path, git_url)
        print("")
        print(f"🌐 Repository URL: {git_url.replace('.git', '')}")
    
    return {
        "username": username,
        "repo_name": repo_name,
        "git_url": get_repo_url(username, repo_name),
        "created": not exists
    }


def main():
    parser = argparse.ArgumentParser(description="Sync repository to Gitea")
    parser.add_argument("--repo", required=True, help="Repository name")
    parser.add_argument("--path", required=True, help="Path to repository")
    parser.add_argument("--description", default="", help="Repository description")
    parser.add_argument("--no-push", action="store_true", help="Don't push code")
    parser.add_argument("--private", action="store_true", help="Make repository private")
    
    args = parser.parse_args()
    
    print("🔄 Gitea Sync")
    print("=" * 50)
    print(f"Repository: {args.repo}")
    print(f"Path: {args.path}")
    print(f"Description: {args.description or '(none)'}")
    print("=" * 50)
    print("")
    
    result = sync_repo(
        args.repo,
        args.path,
        args.description,
        auto_push=not args.no_push
    )
    
    print("")
    print("=" * 50)
    print("✅ Sync complete!")
    print(f"Repository: {result['repo_name']}")
    print(f"URL: {result['git_url'].replace('.git', '')}")
    if result['created']:
        print("Status: Created new repository")
    else:
        print("Status: Updated existing repository")
    print("=" * 50)


if __name__ == "__main__":
    main()
