#!/usr/bin/env python3
"""
Flask应用精确修复工具
专门用于解决Gunicorn启动失败问题
"""

import os
import sys
import subprocess
import importlib.util
import traceback
from datetime import datetime

def run_command(cmd, cwd=None):
    """执行系统命令并返回结果"""
    try:
        result = subprocess.run(
            cmd, 
            shell=True, 
            capture_output=True, 
            text=True, 
            cwd=cwd
        )
        return result.returncode, result.stdout, result.stderr
    except Exception as e:
        return 1, "", str(e)

def get_service_logs(lines=50):
    """获取服务详细日志"""
    print(f"获取linguotree服务最近 {lines} 行日志...")
    code, stdout, stderr = run_command(f"journalctl -u linguotree.service --no-pager -n {lines}")
    if code == 0:
        print("服务日志:")
        print("-" * 60)
        print(stdout)
        print("-" * 60)
        return stdout
    else:
        print(f"✗ 获取日志失败: {stderr}")
        return ""

def check_wsgi_file():
    """检查wsgi.py文件"""
    print("检查wsgi.py文件...")
    
    if not os.path.exists('wsgi.py'):
        print("✗ wsgi.py文件不存在")
        return False
    
    # 读取文件内容
    with open('wsgi.py', 'r', encoding='utf-8') as f:
        content = f.read()
    
    print("wsgi.py内容:")
    print("-" * 40)
    print(content)
    print("-" * 40)
    
    # 检查是否导出app
    if 'app =' in content or 'application =' in content:
        print("✓ wsgi.py包含应用实例")
        return True
    else:
        print("✗ wsgi.py未正确导出应用实例")
        return False

def create_wsgi_file():
    """创建正确的wsgi.py文件"""
    print("创建wsgi.py文件...")
    
    # 首先检查app目录结构
    if not os.path.exists('app/__init__.py'):
        print("创建标准Flask应用结构...")
        
        # 创建app目录
        os.makedirs('app', exist_ok=True)
        os.makedirs('app/models', exist_ok=True)
        os.makedirs('app/views', exist_ok=True)
        os.makedirs('app/static', exist_ok=True)
        os.makedirs('app/templates', exist_ok=True)
        
        # 创建app/__init__.py
        with open('app/__init__.py', 'w', encoding='utf-8') as f:
            f.write('''import os
from flask import Flask
from flask_sqlalchemy import SQLAlchemy
from flask_migrate import Migrate

db = SQLAlchemy()
migrate = Migrate()

def create_app():
    app = Flask(__name__)
    
    # 从环境变量加载配置
    app.config['SECRET_KEY'] = os.environ.get('SECRET_KEY', 'dev-secret-key')
    app.config['SQLALCHEMY_DATABASE_URI'] = os.environ.get('DATABASE_URL') or \\
        f"mysql+pymysql://{os.environ.get('MYSQL_USER', 'linguotree')}:{os.environ.get('MYSQL_PASSWORD', 'adminzhf')}@{os.environ.get('MYSQL_HOST', 'localhost')}:{os.environ.get('MYSQL_PORT', 3306')}/{os.environ.get('MYSQL_DATABASE', 'linguotree_db')}"
    app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False
    
    # 初始化扩展
    db.init_app(app)
    migrate.init_app(app, db)
    
    # 注册蓝图
    from app.views.main import bp as main_bp
    app.register_blueprint(main_bp)
    
    return app
''')
        
        # 创建views目录和main.py
        os.makedirs('app/views', exist_ok=True)
        with open('app/views/main.py', 'w', encoding='utf-8') as f:
            f.write('''from flask import Blueprint, render_template, jsonify

bp = Blueprint('main', __name__)

@bp.route('/')
def index():
    return '''
<!DOCTYPE html>
<html>
<head>
    <title>Linguotree - 首页</title>
    <meta charset="utf-8">
</head>
<body>
    <h1>欢迎访问Linguotree</h1>
    <p>Flask应用运行正常！</p>
    <p>当前时间: <span id="time"></span></p>
    <script>
        document.getElementById('time').textContent = new Date().toLocaleString();
    </script>
</body>
</html>
'''

@bp.route('/health')
def health():
    return jsonify({'status': 'healthy', 'message': 'Flask应用运行正常'})

@bp.route('/test')
def test():
    return jsonify({'message': '测试路由正常工作'})
''')
    
    # 创建wsgi.py
    wsgi_content = '''from app import create_app

app = create_app()

# 确保应用实例被正确导出
application = app

if __name__ == "__main__":
    app.run()
'''
    
    with open('wsgi.py', 'w', encoding='utf-8') as f:
        f.write(wsgi_content)
    
    print("✓ wsgi.py文件创建成功")
    return True

def test_gunicorn_directly():
    """直接测试Gunicorn"""
    print("直接测试Gunicorn启动...")
    
    # 使用调试模式启动Gunicorn
    cmd = "gunicorn --bind 127.0.0.1:5001 --workers 1 --timeout 30 --log-level debug --error-logfile - wsgi:app"
    print(f"执行命令: {cmd}")
    
    code, stdout, stderr = run_command(cmd)
    
    print("Gunicorn测试结果:")
    print(f"退出码: {code}")
    print("标准输出:")
    print(stdout)
    print("错误输出:")
    print(stderr)
    
    return code == 0

def check_imports():
    """检查Python导入"""
    print("检查Python导入...")
    
    # 检查关键模块
    modules_to_check = [
        'flask',
        'flask_sqlalchemy', 
        'flask_migrate',
        'pymysql'
    ]
    
    missing_modules = []
    for module in modules_to_check:
        try:
            __import__(module)
            print(f"✓ {module} 可导入")
        except ImportError as e:
            print(f"✗ {module} 无法导入: {e}")
            missing_modules.append(module)
    
    if missing_modules:
        print(f"需要安装缺失模块: pip install {' '.join(missing_modules)}")
        return False
    
    # 测试导入wsgi
    try:
        spec = importlib.util.spec_from_file_location("wsgi", "wsgi.py")
        wsgi_module = importlib.util.module_from_spec(spec)
        spec.loader.exec_module(wsgi_module)
        
        if hasattr(wsgi_module, 'app') or hasattr(wsgi_module, 'application'):
            print("✓ wsgi.py可成功导入且包含应用实例")
            return True
        else:
            print("✗ wsgi.py导入成功但未找到应用实例")
            return False
    except Exception as e:
        print(f"✗ wsgi.py导入失败: {e}")
        traceback.print_exc()
        return False

def fix_requirements():
    """修复requirements.txt"""
    print("检查requirements.txt...")
    
    required_packages = [
        'Flask==2.3.3',
        'Flask-SQLAlchemy==3.0.5', 
        'Flask-Migrate==4.0.5',
        'PyMySQL==1.1.0',
        'gunicorn==21.2.0'
    ]
    
    if os.path.exists('requirements.txt'):
        with open('requirements.txt', 'r') as f:
            content = f.read()
        
        missing = []
        for pkg in required_packages:
            if pkg.split('==')[0] not in content:
                missing.append(pkg)
        
        if missing:
            print(f"添加缺失的包到requirements.txt: {missing}")
            with open('requirements.txt', 'a') as f:
                f.write('\n# 必需包\n')
                for pkg in missing:
                    f.write(pkg + '\n')
    else:
        print("创建requirements.txt...")
        with open('requirements.txt', 'w') as f:
            for pkg in required_packages:
                f.write(pkg + '\n')
    
    print("安装requirements.txt中的包...")
    code, stdout, stderr = run_command("pip install -r requirements.txt")
    if code == 0:
        print("✓ 依赖包安装成功")
        return True
    else:
        print(f"✗ 依赖包安装失败: {stderr}")
        return False

def stop_service():
    """停止服务"""
    print("停止linguotree服务...")
    code, stdout, stderr = run_command("systemctl stop linguotree.service")
    if code == 0:
        print("✓ 服务已停止")
        return True
    else:
        print(f"✗ 停止服务失败: {stderr}")
        return False

def restart_service():
    """重启服务"""
    print("重启linguotree服务...")
    
    # 重载systemd配置
    code, stdout, stderr = run_command("systemctl daemon-reload")
    if code != 0:
        print(f"✗ 重载systemd配置失败: {stderr}")
        return False
    
    # 重启服务
    code, stdout, stderr = run_command("systemctl restart linguotree.service")
    if code != 0:
        print(f"✗ 重启服务失败: {stderr}")
        return False
    
    # 等待服务启动
    import time
    print("等待服务启动...")
    time.sleep(3)
    
    # 检查服务状态
    code, stdout, stderr = run_command("systemctl is-active linguotree.service")
    status = stdout.strip() if code == 0 else "error"
    
    print(f"服务状态: {status}")
    
    if status == "active":
        print("✓ 服务启动成功")
        return True
    else:
        print("✗ 服务启动失败")
        return False

def comprehensive_fix():
    """综合修复"""
    print("="*60)
    print("Flask应用精确修复")
    print(f"修复时间: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}")
    print("="*60)
    
    # 1. 停止服务
    stop_service()
    
    # 2. 修复依赖
    print("\n--- 修复依赖 ---")
    deps_ok = fix_requirements()
    
    # 3. 检查并创建wsgi.py
    print("\n--- 检查wsgi.py ---")
    wsgi_exists = check_wsgi_file()
    if not wsgi_exists:
        create_wsgi_file()
        wsgi_ok = True
    else:
        wsgi_ok = True
    
    # 4. 检查导入
    print("\n--- 检查Python导入 ---")
    imports_ok = check_imports()
    
    # 5. 测试Gunicorn
    print("\n--- 测试Gunicorn ---")
    if imports_ok:
        gunicorn_ok = test_gunicorn_directly()
    else:
        gunicorn_ok = False
    
    # 6. 重启服务
    print("\n--- 重启服务 ---")
    if gunicorn_ok:
        service_ok = restart_service()
    else:
        print("由于Gunicorn测试失败，跳过服务重启")
        service_ok = False
    
    print("\n" + "="*60)
    print("修复结果:")
    print("="*60)
    print(f"依赖修复: {'✓' if deps_ok else '✗'}")
    print(f"wsgi.py检查: {'✓' if wsgi_ok else '✗'}")
    print(f"导入检查: {'✓' if imports_ok else '✗'}")
    print(f"Gunicorn测试: {'✓' if gunicorn_ok else '✗'}")
    print(f"服务重启: {'✓' if service_ok else '✗'}")
    
    # 显示最终服务日志
    print("\n最终服务状态:")
    get_service_logs(20)
    
    if service_ok:
        print("\n🎉 修复完成！服务应该已经正常运行。")
        print("请测试访问: http://你的服务器IP:8080")
    else:
        print("\n⚠️ 修复未完全成功，请检查以上步骤的错误信息。")
    
    return service_ok

def main():
    """主函数"""
    print("Flask应用精确修复工具")
    print("专门解决Gunicorn启动失败问题")
    
    # 显示当前服务状态
    print("\n当前服务状态:")
    code, stdout, stderr = run_command("systemctl status linguotree.service --no-pager -n 5")
    print(stdout)
    
    # 显示当前日志
    print("\n当前错误日志:")
    get_service_logs(10)
    
    confirm = input("\n是否开始修复? (y/N): ").strip().lower()
    if confirm in ['y', 'yes']:
        comprehensive_fix()
    else:
        print("修复已取消")

if __name__ == "__main__":
    # 确保在正确的目录下运行
    if os.path.exists('/var/www/html'):
        os.chdir('/var/www/html')
    
    main()




