#!/usr/bin/env python3
"""
Update GitOps kustomization.yaml with new image SHA tags.

Usage:
    python3 update-gitops.py \
        --repo /path/to/nxtgauge-gitops \
        --service gateway \
        --sha abc123def456...

This script:
1. Updates the newTag for the specified service to the SHA
2. Commits and pushes to the gitops repo
3. Flux detects the change and deploys
"""

import argparse
import os
import re
import subprocess
import sys


def run(cmd: list[str], cwd: str = None) -> tuple[int, str, str]:
    """Run a command and return (returncode, stdout, stderr)."""
    result = subprocess.run(cmd, cwd=cwd, capture_output=True, text=True)
    return result.returncode, result.stdout, result.stderr


def update_kustomization(kustomization_path: str, service: str, sha: str) -> bool:
    """Update the newTag for a service in kustomization.yaml."""
    with open(kustomization_path, "r") as f:
        content = f.read()

    # Pattern to find image entry for the service
    # Matches:   - name: registry.nxtgauge.com/nxtgauge-rust-{service}
    #             newTag: something
    pattern = rf'(\s+-\s+name:\s+registry\.nxtgauge\.com/nxtgauge-rust-{re.escape(service)}\n\s+newTag:\s+)[^\n]+'

    replacement = rf'\g<1>{sha}'

    new_content, count = re.subn(pattern, replacement, content)

    if count == 0:
        # Try without the nxtgauge-rust- prefix (for frontend, admin, etc)
        pattern = rf'(\s+-\s+name:\s+registry\.nxtgauge\.com/nxtgauge-{re.escape(service)}\n\s+newTag:\s+)[^\n]+'
        new_content, count = re.subn(pattern, replacement, content)

    if count == 0:
        print(f"[ERROR] Could not find image entry for service: {service}")
        return False

    with open(kustomization_path, "w") as f:
        f.write(new_content)

    print(f"[OK] Updated {service} to SHA {sha}")
    return True


def main():
    parser = argparse.ArgumentParser(description="Update GitOps with new image SHA")
    parser.add_argument("--repo", required=True, help="Path to gitops repo")
    parser.add_argument("--service", required=True, help="Service name (e.g., gateway, users, frontend-solid)")
    parser.add_argument("--sha", required=True, help="Git SHA to deploy")
    parser.add_argument("--message", default=None, help="Commit message")
    args = parser.parse_args()

    service_image_map = {
        "gateway": "nxtgauge-rust-gateway",
        "users": "nxtgauge-rust-users",
        "companies": "nxtgauge-rust-companies",
        "jobs": "nxtgauge-rust-jobs",
        "leads": "nxtgauge-rust-leads",
        "job-seekers": "nxtgauge-rust-job-seekers",
        "customers": "nxtgauge-rust-customers",
        "payments": "nxtgauge-rust-payments",
        "employees": "nxtgauge-rust-employees",
        "photographers": "nxtgauge-rust-photographers",
        "makeup-artists": "nxtgauge-rust-makeup-artists",
        "tutors": "nxtgauge-rust-tutors",
        "developers": "nxtgauge-rust-developers",
        "video-editors": "nxtgauge-rust-video-editors",
        "graphic-designers": "nxtgauge-rust-graphic-designers",
        "social-media-managers": "nxtgauge-rust-social-media-managers",
        "fitness-trainers": "nxtgauge-rust-fitness-trainers",
        "catering-services": "nxtgauge-rust-catering-services",
        "ugc-content-creators": "nxtgauge-rust-ugc-content-creators",
        "cron": "nxtgauge-rust-cron",
        "frontend-solid": "nxtgauge-frontend-solid",
        "admin-solid": "nxtgauge-admin-solid",
        "ai-assistant": "nxtgauge-ai-assistant",
    }

    # Determine which kustomization file to update
    if service_image_map.get(args.service):
        image_name = service_image_map[args.service]
    else:
        image_name = f"nxtgauge-{args.service}"

    # Find the right kustomization file based on service
    if "frontend" in args.service:
        kustomization_path = os.path.join(args.repo, "apps/nxtgauge-frontend-solid/overlays/prod/kustomization.yaml")
        if not os.path.exists(kustomization_path):
            kustomization_path = os.path.join(args.repo, "apps/nxtgauge-frontend-solid/base/kustomization.yaml")
    elif "admin" in args.service:
        kustomization_path = os.path.join(args.repo, "apps/nxtgauge-admin-solid/overlays/prod/kustomization.yaml")
        if not os.path.exists(kustomization_path):
            kustomization_path = os.path.join(args.repo, "apps/nxtgauge-admin-solid/base/kustomization.yaml")
    elif "ai-assistant" in args.service:
        kustomization_path = os.path.join(args.repo, "apps/nxtgauge-ai-assistant/overlays/prod/kustomization.yaml")
        if not os.path.exists(kustomization_path):
            kustomization_path = os.path.join(args.repo, "apps/nxtgauge-ai-assistant/base/kustomization.yaml")
    else:
        kustomization_path = os.path.join(args.repo, "apps/nxtgauge-backend-rust/overlays/prod/kustomization.yaml")

    if not os.path.exists(kustomization_path):
        print(f"[ERROR] Kustomization file not found: {kustomization_path}")
        sys.exit(0)  # Exit 0 per workflow requirement

    print(f"Updating {kustomization_path} for service {args.service}")

    if not update_kustomization(kustomization_path, args.service, args.sha):
        sys.exit(0)  # Exit 0 per workflow requirement

    # Git add, commit, push
    commit_msg = args.message or f"chore: deploy {args.service}@{args.sha}"

    run(["git", "add", "-A"], cwd=args.repo)
    code, stdout, stderr = run(["git", "diff", "--cached", "--stat"], cwd=args.repo)

    if not stdout.strip():
        print("[INFO] No changes to commit")
        sys.exit(0)

    print(f"Changes to commit:\n{stdout}")

    run(["git", "commit", "-m", commit_msg], cwd=args.repo)
    code, stdout, stderr = run(["git", "push"], cwd=args.repo)

    if code != 0:
        print(f"[ERROR] Push failed: {stderr}")
    else:
        print(f"[OK] Pushed update to gitops repo")

    sys.exit(0)  # Always exit 0 per workflow requirement


if __name__ == "__main__":
    main()
