"""
机械屏仿真程序自动下载更新脚本
用途：从服务器下载最新版本并覆盖本地文件
适用系统：Windows 10
作者：Claude
日期：2026-06-25
"""

import os
import sys
import zipfile
import shutil
import urllib.request
from pathlib import Path

# 配置
DOWNLOAD_URL = "http://stargazer.org.cn/share/machan-display.zip"
TEMP_ZIP = "machan-display.zip"
TARGET_DIR = r"D:\threejs"
SOURCE_PATH_IN_ZIP = "machan-display/threejs/"

def print_status(message):
    """打印带格式的状态信息"""
    print(f"[INFO] {message}")

def print_error(message):
    """打印错误信息"""
    print(f"[ERROR] {message}", file=sys.stderr)

def download_file(url, filename):
    """下载文件并显示进度"""
    print_status(f"开始下载: {url}")

    try:
        def show_progress(block_num, block_size, total_size):
            downloaded = block_num * block_size
            if total_size > 0:
                percent = min(downloaded * 100 / total_size, 100)
                mb_downloaded = downloaded / 1024 / 1024
                mb_total = total_size / 1024 / 1024
                print(f"\r下载进度: {percent:.1f}% ({mb_downloaded:.1f}MB / {mb_total:.1f}MB)", end='')

        urllib.request.urlretrieve(url, filename, show_progress)
        print()  # 换行
        print_status(f"下载完成: {filename}")
        return True
    except Exception as e:
        print_error(f"下载失败: {e}")
        return False

def extract_zip(zip_path, extract_to="."):
    """解压 ZIP 文件"""
    print_status(f"开始解压: {zip_path}")

    try:
        with zipfile.ZipFile(zip_path, 'r') as zip_ref:
            zip_ref.extractall(extract_to)
        print_status("解压完成")
        return True
    except Exception as e:
        print_error(f"解压失败: {e}")
        return False

def copy_directory(src, dst):
    """复制目录并覆盖已存在的文件"""
    print_status(f"准备覆盖目录: {src} -> {dst}")

    try:
        # 确保目标目录存在
        os.makedirs(dst, exist_ok=True)

        # 复制所有文件
        for item in os.listdir(src):
            src_path = os.path.join(src, item)
            dst_path = os.path.join(dst, item)

            if os.path.isdir(src_path):
                # 递归复制子目录
                shutil.copytree(src_path, dst_path, dirs_exist_ok=True)
                print_status(f"  已复制目录: {item}")
            else:
                # 复制文件
                shutil.copy2(src_path, dst_path)
                print_status(f"  已复制文件: {item}")

        print_status("目录覆盖完成")
        return True
    except Exception as e:
        print_error(f"复制失败: {e}")
        return False

def cleanup(files_and_dirs):
    """清理临时文件"""
    print_status("清理临时文件...")

    for item in files_and_dirs:
        try:
            if os.path.isfile(item):
                os.remove(item)
                print_status(f"  已删除文件: {item}")
            elif os.path.isdir(item):
                shutil.rmtree(item)
                print_status(f"  已删除目录: {item}")
        except Exception as e:
            print_error(f"清理失败 {item}: {e}")

def main():
    """主函数"""
    print("=" * 60)
    print("机械屏仿真程序自动更新脚本")
    print("=" * 60)
    print()

    # 1. 下载 ZIP 文件
    if not download_file(DOWNLOAD_URL, TEMP_ZIP):
        print_error("下载失败，程序终止")
        return 1

    # 2. 解压 ZIP 文件
    if not extract_zip(TEMP_ZIP):
        cleanup([TEMP_ZIP])
        print_error("解压失败，程序终止")
        return 1

    # 3. 查找源目录
    source_dir = SOURCE_PATH_IN_ZIP.rstrip('/')
    if not os.path.exists(source_dir):
        cleanup([TEMP_ZIP, "machan-display"])
        print_error(f"未找到源目录: {source_dir}")
        return 1

    # 4. 备份目标目录（如果存在）
    if os.path.exists(TARGET_DIR):
        backup_dir = f"{TARGET_DIR}_backup"
        print_status(f"备份现有目录到: {backup_dir}")
        try:
            if os.path.exists(backup_dir):
                shutil.rmtree(backup_dir)
            shutil.copytree(TARGET_DIR, backup_dir)
            print_status("备份完成")
        except Exception as e:
            print_error(f"备份失败: {e}")
            print_status("继续执行覆盖操作...")

    # 5. 覆盖目标目录
    if not copy_directory(source_dir, TARGET_DIR):
        cleanup([TEMP_ZIP, "machan-display"])
        print_error("覆盖失败，程序终止")
        return 1

    # 6. 清理临时文件
    cleanup([TEMP_ZIP, "machan-display"])

    # 7. 完成
    print()
    print("=" * 60)
    print("✅ 更新完成！")
    print("=" * 60)
    print(f"目标目录: {TARGET_DIR}")
    print(f"备份目录: {TARGET_DIR}_backup (如果存在)")
    print()
    print("文件列表:")
    try:
        for item in os.listdir(TARGET_DIR):
            item_path = os.path.join(TARGET_DIR, item)
            if os.path.isfile(item_path):
                size = os.path.getsize(item_path)
                size_str = f"{size / 1024:.1f} KB" if size < 1024 * 1024 else f"{size / 1024 / 1024:.1f} MB"
                print(f"  - {item} ({size_str})")
            else:
                print(f"  - {item}/ (目录)")
    except Exception as e:
        print_error(f"列出文件失败: {e}")

    print()
    print("现在可以打开 D:\\threejs\\index.html 使用程序")
    print()

    return 0

if __name__ == "__main__":
    try:
        exit_code = main()
        input("\n按回车键退出...")
        sys.exit(exit_code)
    except KeyboardInterrupt:
        print("\n\n用户中断，程序退出")
        sys.exit(1)
    except Exception as e:
        print_error(f"未预期的错误: {e}")
        input("\n按回车键退出...")
        sys.exit(1)
