#!/usr/bin/env python3
"""Simple webhook handler for Gitea push events"""
import http.server
import subprocess
import threading
import json
import hmac
import hashlib
import os

WEBHOOK_SECRET = os.environ.get('WEBHOOK_SECRET', 'gururmm-build-secret')
BUILD_SCRIPT = '/opt/gururmm/build-agents.sh'
LOCK_FILE = '/var/run/gururmm-build.lock'
PORT = 9000

def is_build_running():
    if not os.path.exists(LOCK_FILE):
        return False
    with open(LOCK_FILE) as f:
        pid = f.read().strip()
    try:
        pid = int(pid)
    except ValueError:
        os.remove(LOCK_FILE)
        return False
    # Check if process exists and is not a zombie
    try:
        with open(f'/proc/{pid}/status') as f:
            status = f.read()
        if 'State:\tZ' in status:
            # Zombie — build is done, clean up
            try:
                os.waitpid(pid, os.WNOHANG)
            except ChildProcessError:
                pass
            os.remove(LOCK_FILE)
            return False
        return True
    except FileNotFoundError:
        os.remove(LOCK_FILE)
        return False

def run_build():
    proc = subprocess.Popen(
        ['sudo', BUILD_SCRIPT],
        stdout=open('/var/log/gururmm-build.log', 'a'),
        stderr=subprocess.STDOUT
    )
    with open(LOCK_FILE, 'w') as f:
        f.write(str(proc.pid))
    proc.wait()  # Reap the child — prevents zombie
    if os.path.exists(LOCK_FILE):
        os.remove(LOCK_FILE)
    print(f"Build complete, exit code: {proc.returncode}")

class WebhookHandler(http.server.BaseHTTPRequestHandler):
    def log_message(self, format, *args):
        pass  # suppress default access log noise

    def do_POST(self):
        if self.path != '/webhook/build':
            self.send_response(404)
            self.end_headers()
            return

        content_length = int(self.headers.get('Content-Length', 0))
        body = self.rfile.read(content_length)

        signature = self.headers.get('X-Gitea-Signature', '')
        if signature:
            expected = hmac.new(WEBHOOK_SECRET.encode(), body, hashlib.sha256).hexdigest()
            if not hmac.compare_digest(signature, expected):
                self.send_response(403)
                self.end_headers()
                self.wfile.write(b'Invalid signature')
                return

        try:
            data = json.loads(body)
            ref = data.get('ref', '')

            if ref == 'refs/heads/main':
                if is_build_running():
                    self.send_response(200)
                    self.end_headers()
                    self.wfile.write(b'Build already in progress, skipped')
                    return

                print(f"Triggering build for push to main")
                t = threading.Thread(target=run_build, daemon=True)
                t.start()

                self.send_response(200)
                self.end_headers()
                self.wfile.write(b'Build triggered')
            else:
                self.send_response(200)
                self.end_headers()
                self.wfile.write(f'Ignored push to {ref}'.encode())
        except Exception as e:
            print(f"Error: {e}")
            self.send_response(500)
            self.end_headers()
            self.wfile.write(str(e).encode())

if __name__ == '__main__':
    server = http.server.HTTPServer(('127.0.0.1', PORT), WebhookHandler)
    print(f'Webhook handler listening on port {PORT}')
    server.serve_forever()
