#!/usr/bin/env python3
"""
GitHub Webhook 接收服务 - File Tag Manager
监听 9001 端口，接收 GitHub 推送通知并触发部署
"""

import http.server
import subprocess
import hashlib
import hmac
import os
import json
import sys
from datetime import datetime

WEBHOOK_SECRET = os.environ.get('WEBHOOK_SECRET', '')
DEPLOY_SCRIPT = '/root/file_tag_manager/auto-deploy.sh'
PORT = 9001
LOG_FILE = '/var/log/file-tag-webhook.log'

def log(message):
    timestamp = datetime.now().strftime('%Y-%m-%d %H:%M:%S')
    log_msg = f"[{timestamp}] {message}"
    print(log_msg)
    try:
        with open(LOG_FILE, 'a') as f:
            f.write(log_msg + '\n')
    except:
        pass

class WebhookHandler(http.server.BaseHTTPRequestHandler):
    def log_message(self, format, *args):
        log(f"HTTP: {args[0]}")
    
    def do_POST(self):
        # 读取 body
        content_length = int(self.headers.get('Content-Length', 0))
        body = self.rfile.read(content_length)
        
        # 验证签名
        if WEBHOOK_SECRET:
            signature = self.headers.get('X-Hub-Signature-256', '')
            if signature:
                expected = 'sha256=' + hmac.new(
                    WEBHOOK_SECRET.encode(), body, hashlib.sha256
                ).hexdigest()
                if not hmac.compare_digest(signature, expected):
                    log("❌ Invalid signature")
                    self.send_response(403)
                    self.end_headers()
                    self.wfile.write(b'Invalid signature')
                    return
            else:
                log("⚠️ No signature provided")
        
        # 验证事件类型
        event = self.headers.get('X-GitHub-Event', '')
        if event not in ['push', 'ping']:
            log(f"⚠️ Invalid event type: {event}")
            self.send_response(400)
            self.end_headers()
            self.wfile.write(b'Invalid event type')
            return
        
        # 读取 payload
        try:
            payload = json.loads(body)
        except:
            log("❌ Invalid JSON payload")
            self.send_response(400)
            self.end_headers()
            self.wfile.write(b'Invalid JSON')
            return
        
        # 处理 ping 事件
        if event == 'ping':
            log("🏓 Ping received")
            self.send_response(200)
            self.end_headers()
            self.wfile.write(b'pong')
            return
        
        # 检查分支（只部署 main/master 分支）
        ref = payload.get('ref', '')
        if ref not in ['refs/heads/main', 'refs/heads/master']:
            log(f"⚠️ Ignored non-main branch: {ref}")
            self.send_response(200)
            self.end_headers()
            self.wfile.write(b'Ignored non-main branch')
            return
        
        # 获取提交信息
        repo = payload.get('repository', {}).get('full_name', 'unknown')
        pusher = payload.get('pusher', {}).get('name', 'unknown')
        commits = payload.get('commits', [])
        commit_msg = commits[0].get('message', 'no message') if commits else 'no commits'
        commit_id = commits[0].get('id', 'unknown')[:7] if commits else 'unknown'
        
        log(f"🚀 Push received from {repo} by {pusher}")
        log(f"   Branch: {ref}, Commit: {commit_id}")
        log(f"   Message: {commit_msg[:50]}...")
        
        # 触发部署
        try:
            log("▶️ Starting deployment...")
            result = subprocess.run(
                ['bash', DEPLOY_SCRIPT],
                capture_output=True,
                text=True,
                timeout=600
            )
            
            # 记录输出
            for line in result.stdout.split('\n'):
                if line.strip():
                    log(f"   {line}")
            for line in result.stderr.split('\n'):
                if line.strip():
                    log(f"   ❌ {line}")
            
            if result.returncode == 0:
                self.send_response(200)
                self.end_headers()
                self.wfile.write(b'Deploy success')
                log("✅ Deploy success")
            else:
                self.send_response(500)
                self.end_headers()
                error_msg = f'Deploy failed: {result.stderr}'
                self.wfile.write(error_msg.encode())
                log(f"❌ Deploy failed: {result.stderr}")
        except subprocess.TimeoutExpired:
            self.send_response(504)
            self.end_headers()
            self.wfile.write(b'Deploy timeout')
            log("❌ Deploy timeout (600s)")
        except Exception as e:
            self.send_response(500)
            self.end_headers()
            self.wfile.write(f'Error: {str(e)}'.encode())
            log(f"❌ Error: {e}")

if __name__ == '__main__':
    log(f"🚀 Starting Webhook server on port {PORT}...")
    server = http.server.HTTPServer(('0.0.0.0', PORT), WebhookHandler)
    try:
        server.serve_forever()
    except KeyboardInterrupt:
        log("👋 Shutting down...")
        server.shutdown()
