import os, hmac, hashlib, subprocess, threading
from fastapi import FastAPI, Request, HTTPException, BackgroundTasks
from fastapi.responses import JSONResponse
import logging

logging.basicConfig(
    level=logging.INFO,
    format="%(asctime)s [%(name)s] %(levelname)s %(message)s",
    datefmt="%Y-%m-%d %H:%M:%S %Z",
)
logger = logging.getLogger("deployer")

app = FastAPI()
SECRET = os.getenv("WEBHOOK_SECRET", "")

if not SECRET:
    logger.warning("WEBHOOK_SECRET is not set! All webhooks will be rejected.")

_deploy_lock = threading.Lock()

def verify(sig: str, body: bytes) -> bool:
    if not SECRET or not sig:
        return False

    mac = hmac.new(SECRET.encode(), msg=body, digestmod=hashlib.sha256).hexdigest()
    candidates = {mac, f"sha256={mac}"}
    return any(hmac.compare_digest(sig, c) for c in candidates)

def run_deploy_script():
    """배포 스크립트를 백그라운드에서 실행 (동시 실행 방지)"""
    if not _deploy_lock.acquire(blocking=False):
        logger.info("Deploy already in progress, skipping")
        return

    try:
        logger.info("Starting deployment script...")
        p = subprocess.run(["/bin/bash", "/scripts/deploy.sh"], capture_output=True, text=True, timeout=600)

        if p.returncode == 0:
            logger.info(f"Deployment SUCCESS:\n{p.stdout}")
        else:
            logger.error(f"Deployment FAILED ({p.returncode}):\n{p.stdout}\n{p.stderr}")

    except subprocess.TimeoutExpired:
        logger.error("Deployment TIMEOUT (10 min exceeded)")
    except Exception as e:
        logger.exception(f"Exception during deployment: {e}")
    finally:
        _deploy_lock.release()

@app.get("/health")
def health():
    return {"status": "healthy", "service": "deployer"}

@app.post("/webhook")
async def webhook(req: Request, background_tasks: BackgroundTasks):
    body = await req.body()

    sig = (
        req.headers.get("X-Gitea-Signature")
        or req.headers.get("X-Hub-Signature-256")
        or ""
    )

    if not verify(sig, body):
        raise HTTPException(401, "bad signature")

    # 동시 배포 방지: 이미 진행 중이면 503 반환
    if _deploy_lock.locked():
        return JSONResponse(
            status_code=503,
            content={"ok": False, "message": "Deploy already in progress"},
        )

    # ✅ 비동기 실행: Gitea에게는 즉시 OK 응답을 주고, 배포는 뒤에서 실행
    background_tasks.add_task(run_deploy_script)

    return {"ok": True, "message": "Deployment started in background"}

