#!/usr/bin/env python3
"""
GitHub Webhook处理器
监听GitHub推送事件，自动触发部署
"""

import os
import subprocess
import json
import hmac
import hashlib
import logging
from flask import Flask, request, jsonify
import threading
import time

app = Flask(__name__)

# 配置
WEBHOOK_SECRET = "kaopeilian-webhook-secret-2025"  # GitHub中配置的密钥
PROJECT_DIR = "/root/aiedu"
UPDATE_SCRIPT = "/root/aiedu/scripts/auto_update.sh"

# 配置日志
logging.basicConfig(
    level=logging.INFO,
    format='%(asctime)s - %(levelname)s - %(message)s',
    handlers=[
        logging.FileHandler('/var/log/kaopeilian_webhook.log'),
        logging.StreamHandler()
    ]
)

def verify_signature(payload_body, signature_header):
    """验证GitHub Webhook签名"""
    if not signature_header:
        return False
    
    hash_object = hmac.new(
        WEBHOOK_SECRET.encode('utf-8'),
        payload_body,
        hashlib.sha256
    )
    expected_signature = "sha256=" + hash_object.hexdigest()
    
    return hmac.compare_digest(expected_signature, signature_header)

def run_update_async():
    """异步执行更新脚本"""
    try:
        # 等待5秒再执行，避免GitHub推送过程中的竞争条件
        time.sleep(5)
        
        result = subprocess.run(
            [UPDATE_SCRIPT], 
            cwd=PROJECT_DIR,
            capture_output=True,
            text=True,
            timeout=600  # 10分钟超时
        )
        
        if result.returncode == 0:
            logging.info(f"Update completed successfully: {result.stdout}")
        else:
            logging.error(f"Update failed: {result.stderr}")
            
    except subprocess.TimeoutExpired:
        logging.error("Update script timed out")
    except Exception as e:
        logging.error(f"Error running update script: {e}")

@app.route('/webhook', methods=['POST'])
def github_webhook():
    """处理GitHub Webhook请求"""
    
    # 验证签名
    signature = request.headers.get('X-Hub-Signature-256')
    if not verify_signature(request.data, signature):
        logging.warning("Invalid webhook signature")
        return jsonify({"error": "Invalid signature"}), 403
    
    # 解析请求
    try:
        payload = request.get_json()
    except Exception as e:
        logging.error(f"Failed to parse JSON: {e}")
        return jsonify({"error": "Invalid JSON"}), 400
    
    # 检查事件类型
    event_type = request.headers.get('X-GitHub-Event')
    if event_type != 'push':
        logging.info(f"Ignoring event type: {event_type}")
        return jsonify({"message": "Event ignored"}), 200
    
    # 检查分支
    ref = payload.get('ref', '')
    if ref != 'refs/heads/production':
        logging.info(f"Ignoring push to branch: {ref}")
        return jsonify({"message": "Branch ignored"}), 200
    
    # 获取提交信息
    commit_info = {
        'id': payload.get('after', 'unknown'),
        'message': payload.get('head_commit', {}).get('message', 'No message'),
        'author': payload.get('head_commit', {}).get('author', {}).get('name', 'Unknown'),
        'timestamp': payload.get('head_commit', {}).get('timestamp', 'Unknown')
    }
    
    logging.info(f"Received push event: {commit_info}")
    
    # 异步触发更新
    update_thread = threading.Thread(target=run_update_async)
    update_thread.daemon = True
    update_thread.start()
    
    return jsonify({
        "message": "Update triggered successfully",
        "commit": commit_info
    }), 200

@app.route('/health', methods=['GET'])
def health_check():
    """健康检查端点"""
    return jsonify({
        "status": "healthy",
        "service": "kaopeilian-webhook",
        "timestamp": time.time()
    }), 200

@app.route('/status', methods=['GET'])
def status():
    """状态检查端点"""
    try:
        # 检查项目目录
        project_exists = os.path.exists(PROJECT_DIR)
        
        # 检查更新脚本
        script_exists = os.path.exists(UPDATE_SCRIPT)
        script_executable = os.access(UPDATE_SCRIPT, os.X_OK) if script_exists else False
        
        # 检查Docker服务
        docker_result = subprocess.run(['docker', 'compose', 'ps'], 
                                     cwd=PROJECT_DIR, capture_output=True)
        docker_running = docker_result.returncode == 0
        
        return jsonify({
            "status": "ok",
            "checks": {
                "project_directory": project_exists,
                "update_script_exists": script_exists,
                "update_script_executable": script_executable,
                "docker_compose_running": docker_running
            }
        }), 200
        
    except Exception as e:
        return jsonify({
            "status": "error",
            "error": str(e)
        }), 500

if __name__ == '__main__':
    logging.info("Starting GitHub Webhook handler...")
    app.run(host='0.0.0.0', port=9000, debug=False)
