#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Python 环境列表更新脚本
功能：对比虚拟环境中已安装的包和 environment.txt，如果不一致则更新 environment.txt
"""

import os
import sys
import subprocess
import platform
from pathlib import Path

# 获取脚本所在目录
SCRIPT_DIR = Path(__file__).parent.absolute()
VENV_PATH = SCRIPT_DIR / "env"
ENVIRONMENT_FILE = SCRIPT_DIR / "environment.txt"

# 根据操作系统确定虚拟环境的 pip 路径
if platform.system() == "Windows":
    VENV_PIP = VENV_PATH / "Scripts" / "pip.exe"
else:
    VENV_PIP = VENV_PATH / "bin" / "pip"


def run_command(cmd, check=True, capture_output=True):
    """运行命令并返回结果"""
    try:
        result = subprocess.run(
            cmd,
            shell=True,
            check=check,
            capture_output=capture_output,
            text=True,
            encoding='utf-8'
        )
        return result.returncode == 0, result.stdout, result.stderr
    except subprocess.CalledProcessError as e:
        return False, e.stdout if hasattr(e, 'stdout') else "", str(e)


def get_installed_packages():
    """获取虚拟环境中已安装的包列表（使用 pip freeze）"""
    if not VENV_PATH.exists():
        print("[ERROR] Virtual environment not found")
        return None
    
    cmd = f'"{VENV_PIP}" freeze'
    success, output, error = run_command(cmd, check=False)
    
    if not success:
        print(f"[ERROR] Failed to get installed packages: {error}")
        return None
    
    # 解析输出，提取包名和版本
    packages = {}
    for line in output.strip().split('\n'):
        line = line.strip()
        if line and not line.startswith('#'):
            # 格式：package==version 或 package>=version 等
            if '==' in line:
                parts = line.split('==', 1)
                packages[parts[0].strip().lower()] = line.strip()
            else:
                # 如果没有版本号，使用整行
                pkg_name = line.split('>=')[0].split('<=')[0].split('>')[0].split('<')[0].split('~=')[0].strip()
                packages[pkg_name.lower()] = line.strip()
    
    return packages


def read_environment_file():
    """读取 environment.txt 中的包列表"""
    if not ENVIRONMENT_FILE.exists():
        print(f"[WARN] {ENVIRONMENT_FILE} not found, will create new one")
        return {}
    
    packages = {}
    with open(ENVIRONMENT_FILE, 'r', encoding='utf-8') as f:
        for line in f:
            line = line.strip()
            if line and not line.startswith('#'):
                # 提取包名（支持各种版本操作符）
                if '==' in line:
                    parts = line.split('==', 1)
                    packages[parts[0].strip().lower()] = line.strip()
                else:
                    pkg_name = line.split('>=')[0].split('<=')[0].split('>')[0].split('<')[0].split('~=')[0].strip()
                    packages[pkg_name.lower()] = line.strip()
    
    return packages


def compare_and_update():
    """对比并更新 environment.txt"""
    print("Comparing installed packages with environment.txt...")
    print("=" * 60)
    
    # 获取已安装的包
    installed_packages = get_installed_packages()
    if installed_packages is None:
        sys.exit(1)
    
    # 读取 environment.txt 中的包
    file_packages = read_environment_file()
    
    # 对比差异
    installed_set = set(installed_packages.keys())
    file_set = set(file_packages.keys())
    
    added_packages = installed_set - file_set
    removed_packages = file_set - installed_set
    changed_packages = []
    
    # 检查版本变化
    for pkg_name in installed_set & file_set:
        if installed_packages[pkg_name] != file_packages[pkg_name]:
            changed_packages.append(pkg_name)
    
    # 显示差异
    if added_packages:
        print(f"\n[+] Added packages ({len(added_packages)}):")
        for pkg in sorted(added_packages):
            print(f"  + {installed_packages[pkg]}")
    
    if removed_packages:
        print(f"\n[-] Removed packages ({len(removed_packages)}):")
        for pkg in sorted(removed_packages):
            print(f"  - {file_packages[pkg]}")
    
    if changed_packages:
        print(f"\n[~] Changed packages ({len(changed_packages)}):")
        for pkg in sorted(changed_packages):
            print(f"  ~ {file_packages[pkg]} -> {installed_packages[pkg]}")
    
    # 判断是否需要更新
    if not added_packages and not removed_packages and not changed_packages:
        print("\n[OK] environment.txt is up to date")
        print(f"     Total packages: {len(installed_packages)}")
        return True
    
    # 更新 environment.txt
    print(f"\nUpdating {ENVIRONMENT_FILE}...")
    
    # 使用 pip freeze 获取完整列表（包含所有依赖）
    cmd = f'"{VENV_PIP}" freeze'
    success, output, error = run_command(cmd, check=False)
    
    if not success:
        print(f"[ERROR] Failed to get installed packages: {error}")
        sys.exit(1)
    
    # 写入文件（使用 UTF-8 无 BOM 编码）
    with open(ENVIRONMENT_FILE, 'w', encoding='utf-8', newline='\n') as f:
        f.write(output)
    
    # 统计包数量
    package_count = len([line for line in output.strip().split('\n') if line.strip()])
    
    print(f"[OK] {ENVIRONMENT_FILE} updated successfully")
    print(f"     Total packages: {package_count}")
    
    return True


def main():
    """主函数"""
    if not compare_and_update():
        sys.exit(1)
    sys.exit(0)


if __name__ == "__main__":
    main()
