#!/usr/bin/env python3
"""
应用打包脚本 - 将Python应用打包为可执行文件
"""

import os
import sys
import shutil
import subprocess
from pathlib import Path

def check_dependencies():
    """检查必要的依赖"""
    try:
        import PyInstaller
        print("OK PyInstaller 已安装")
    except ImportError:
        print("正在安装 PyInstaller...")
        subprocess.check_call([sys.executable, "-m", "pip", "install", "pyinstaller"])
        print("OK PyInstaller 安装完成")

def create_spec_file():
    """创建 PyInstaller spec 文件"""
    spec_content = '''
# -*- mode: python ; coding: utf-8 -*-

block_cipher = None

a = Analysis(
    ['main.py'],
    pathex=[],
    binaries=[],
    datas=[
        ('app', 'app'),
        ('uploads', 'uploads'),
        ('logs', 'logs'),
    ],
    hiddenimports=[
        'uvicorn',
        'fastapi',
        'sqlalchemy',
        'pymysql',
        'pydantic',
        'pydantic_settings',
        'redis',
        'passlib',
        'python_jose',
        'uvicorn.protocols.http.httptools_impl',
    ],
    hookspath=[],
    hooksconfig={},
    runtime_hooks=[],
    excludes=[],
    win_no_prefer_redirects=False,
    win_private_assemblies=False,
    cipher=block_cipher,
    noarchive=False,
)

pyz = PYZ(a.pure, a.zipped_data, cipher=block_cipher)

exe = EXE(
    pyz,
    a.scripts,
    a.binaries,
    a.zipfiles,
    a.datas,
    [],
    name='cloud-drive-server',
    debug=False,
    bootloader_ignore_signals=False,
    strip=False,
    upx=True,
    upx_exclude=[],
    runtime_tmpdir=None,
    console=True,
    disable_windowed_traceback=False,
    argv_emulation=False,
    target_arch=None,
    codesign_identity=None,
    entitlements_file=None,
    icon=None
)
'''

    with open('cloud-drive-server.spec', 'w', encoding='utf-8') as f:
        f.write(spec_content)
    print("OK 创建了 cloud-drive-server.spec 文件")

def build_executable():
    """构建可执行文件"""
    print("开始构建可执行文件...")

    try:
        # 使用 PyInstaller 构建
        result = subprocess.run([
            sys.executable, '-m', 'PyInstaller',
            '--clean',
            '--noconfirm',
            'cloud-drive-server.spec'
        ], capture_output=True, text=True)

        if result.returncode == 0:
            print("OK 可执行文件构建成功")
            print("输出目录: dist/")
            return True
        else:
            print("ERROR 构建失败:")
            print(result.stdout)
            print(result.stderr)
            return False

    except Exception as e:
        print(f"ERROR 构建过程中出现错误: {e}")
        return False

def create_dockerfile_for_executable():
    """为可执行文件创建最小化的 Dockerfile"""
    dockerfile_content = '''# 最小化运行环境 - 使用可执行文件
FROM alpine:latest

# 安装运行时依赖
RUN apk add --no-cache \\
    curl \\
    tzdata \\
    ca-certificates \\
    && rm -rf /var/cache/apk/*

# 设置时区
ENV TZ=Asia/Shanghai
RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone

# 创建应用用户
RUN adduser -D -s /bin/sh app

# 设置工作目录
WORKDIR /app

# 复制可执行文件
COPY dist/cloud-drive-server /app/cloud-drive-server

# 创建必要的目录
RUN mkdir -p /app/uploads /app/logs \\
    && chown -R app:app /app

# 切换到非root用户
USER app

# 暴露端口
EXPOSE 8002

# 健康检查
HEALTHCHECK --interval=30s --timeout=30s --start-period=5s --retries=3 \\
    CMD curl -f http://localhost:8002/api/v1/health || exit 1

# 启动命令
CMD ["./cloud-drive-server"]
'''

    with open('Dockerfile.executable', 'w', encoding='utf-8') as f:
        f.write(dockerfile_content)
    print("OK 创建了 Dockerfile.executable 文件")

def main():
    """主函数"""
    print("=== 云盘应用打包工具 ===")
    print("正在将应用打包为Docker镜像...")

    # 检查当前目录
    if not Path('main.py').exists():
        print("ERROR 错误: 在当前目录未找到 main.py 文件")
        print("请在 backend 目录中运行此脚本")
        return False

    # 检查依赖
    check_dependencies()

    # 创建 spec 文件
    create_spec_file()

    # 构建可执行文件
    if not build_executable():
        return False

    # 创建可执行文件的 Dockerfile
    create_dockerfile_for_executable()

    print("\n=== 打包完成 ===")
    print("OK 应用已成功打包")
    print("OK 可执行文件位于: dist/cloud-drive-server")
    print("OK Dockerfile: Dockerfile.executable")
    print("\n下一步命令:")
    print("  docker build -f Dockerfile.executable -t cloud-drive-backend:latest .")
    print("  docker run -d -p 8002:8002 --name cloud-drive-backend cloud-drive-backend:latest")

    return True

if __name__ == "__main__":
    success = main()
    sys.exit(0 if success else 1)