#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
Windows服务安装脚本
用于将自动重启服务注册为Windows系统服务
"""

import os
import sys
import time
import winreg as reg
import subprocess
import logging

# 配置日志
logging.basicConfig(
    level=logging.INFO,
    format='%(asctime)s - %(levelname)s - %(message)s',
    handlers=[
        logging.FileHandler("service_install.log"),
        logging.StreamHandler()
    ]
)
logger = logging.getLogger(__name__)

# 服务信息
SERVICE_NAME = "AutoRebootService"
SERVICE_DISPLAY_NAME = "自动重启服务"
SERVICE_DESCRIPTION = "定期（每15天）自动重启系统，并在重启前发送邮件通知"

# 获取当前Python解释器路径
PYTHON_EXE = sys.executable

# 主程序路径
MAIN_SCRIPT = os.path.join(os.path.dirname(os.path.abspath(__file__)), "auto_reboot_service.py")

# NSSM路径（将自动下载）
NSSM_URL = "https://nssm.cc/release/nssm-2.24.zip"
NSSM_ZIP = "nssm-2.24.zip"
NSSM_DIR = "nssm-2.24"
NSSM_EXE = os.path.join(NSSM_DIR, "win64", "nssm.exe" if sys.maxsize > 2**32 else "win32", "nssm.exe")


def is_admin():
    """检查是否以管理员权限运行"""
    try:
        return ctypes.windll.shell32.IsUserAnAdmin()
    except:
        return False


def run_as_admin():
    """以管理员权限重新运行脚本"""
    ctypes.windll.shell32.ShellExecuteW(
        None, "runas", sys.executable, " ".join(sys.argv), None, 1
    )


def download_nssm():
    """下载并解压NSSM工具"""
    try:
        if os.path.exists(NSSM_EXE):
            logger.info(f"NSSM已存在: {NSSM_EXE}")
            return True
        
        # 下载NSSM
        logger.info(f"正在下载NSSM: {NSSM_URL}")
        import urllib.request
        urllib.request.urlretrieve(NSSM_URL, NSSM_ZIP)
        logger.info(f"NSSM下载完成: {NSSM_ZIP}")
        
        # 解压NSSM
        logger.info(f"正在解压NSSM: {NSSM_ZIP}")
        import zipfile
        with zipfile.ZipFile(NSSM_ZIP, 'r') as zip_ref:
            zip_ref.extractall()
        logger.info("NSSM解压完成")
        
        # 删除下载的zip文件
        os.remove(NSSM_ZIP)
        logger.info(f"已删除NSSM压缩包: {NSSM_ZIP}")
        
        return True
    except Exception as e:
        logger.error(f"下载或解压NSSM失败: {e}")
        return False


def install_service():
    """使用NSSM安装服务"""
    try:
        # 确保脚本存在
        if not os.path.exists(MAIN_SCRIPT):
            logger.error(f"主程序文件不存在: {MAIN_SCRIPT}")
            return False
        
        # 确保NSSM存在
        if not os.path.exists(NSSM_EXE):
            if not download_nssm():
                # 如果下载失败，尝试使用系统PATH中的NSSM
                try:
                    subprocess.run(["nssm", "version"], check=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
                    logger.info("使用系统PATH中的NSSM")
                    nssm_path = "nssm"
                except:
                    logger.error("无法找到NSSM工具，请手动安装")
                    return False
        else:
            nssm_path = NSSM_EXE
        
        # 检查服务是否已存在
        try:
            result = subprocess.run([nssm_path, "status", SERVICE_NAME], 
                                  stdout=subprocess.PIPE, stderr=subprocess.PIPE)
            if result.returncode == 0:
                logger.info(f"服务 {SERVICE_NAME} 已存在，将先停止并移除")
                # 停止服务
                subprocess.run([nssm_path, "stop", SERVICE_NAME], check=False)
                # 移除服务
                subprocess.run([nssm_path, "remove", SERVICE_NAME, "confirm"], check=False)
        except Exception as e:
            logger.warning(f"检查服务状态时出错: {e}")
        
        # 安装服务
        logger.info(f"正在安装服务: {SERVICE_NAME}")
        subprocess.run([nssm_path, "install", SERVICE_NAME, PYTHON_EXE, MAIN_SCRIPT], check=True)
        
        # 设置服务描述
        logger.info(f"设置服务描述: {SERVICE_DESCRIPTION}")
        subprocess.run([nssm_path, "set", SERVICE_NAME, "Description", SERVICE_DESCRIPTION], check=True)
        
        # 设置服务显示名称
        logger.info(f"设置服务显示名称: {SERVICE_DISPLAY_NAME}")
        subprocess.run([nssm_path, "set", SERVICE_NAME, "DisplayName", SERVICE_DISPLAY_NAME], check=True)
        
        # 设置服务启动类型为自动
        logger.info("设置服务启动类型为自动")
        subprocess.run([nssm_path, "set", SERVICE_NAME, "Start", "SERVICE_AUTO_START"], check=True)
        
        # 设置工作目录
        work_dir = os.path.dirname(os.path.abspath(__file__))
        logger.info(f"设置工作目录: {work_dir}")
        subprocess.run([nssm_path, "set", SERVICE_NAME, "AppDirectory", work_dir], check=True)
        
        # 启动服务
        logger.info("启动服务")
        subprocess.run([nssm_path, "start", SERVICE_NAME], check=True)
        
        logger.info(f"服务 {SERVICE_NAME} 安装成功")
        print(f"\n服务 {SERVICE_DISPLAY_NAME} 已成功安装并启动！")
        print(f"服务名称: {SERVICE_NAME}")
        print(f"服务描述: {SERVICE_DESCRIPTION}")
        print(f"主程序路径: {MAIN_SCRIPT}")
        print(f"\n您可以在Windows服务管理器中查看和管理此服务")
        return True
    except subprocess.CalledProcessError as e:
        logger.error(f"服务安装失败: {e}")
        print(f"服务安装失败: {e}")
        return False
    except Exception as e:
        logger.error(f"服务安装过程中出错: {e}")
        print(f"服务安装过程中出错: {e}")
        return False


def uninstall_service():
    """卸载服务"""
    try:
        # 尝试找到NSSM
        if os.path.exists(NSSM_EXE):
            nssm_path = NSSM_EXE
        else:
            # 尝试使用系统PATH中的NSSM
            try:
                subprocess.run(["nssm", "version"], check=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
                nssm_path = "nssm"
            except:
                logger.error("无法找到NSSM工具，请手动卸载服务")
                return False
        
        # 检查服务是否存在
        try:
            result = subprocess.run([nssm_path, "status", SERVICE_NAME], 
                                  stdout=subprocess.PIPE, stderr=subprocess.PIPE)
            if result.returncode != 0:
                logger.warning(f"服务 {SERVICE_NAME} 不存在")
                print(f"服务 {SERVICE_NAME} 不存在")
                return True
        except Exception as e:
            logger.warning(f"检查服务状态时出错: {e}")
        
        # 停止服务
        logger.info(f"正在停止服务: {SERVICE_NAME}")
        subprocess.run([nssm_path, "stop", SERVICE_NAME], check=False)
        
        # 移除服务
        logger.info(f"正在移除服务: {SERVICE_NAME}")
        subprocess.run([nssm_path, "remove", SERVICE_NAME, "confirm"], check=True)
        
        logger.info(f"服务 {SERVICE_NAME} 卸载成功")
        print(f"\n服务 {SERVICE_DISPLAY_NAME} 已成功卸载！")
        return True
    except subprocess.CalledProcessError as e:
        logger.error(f"服务卸载失败: {e}")
        print(f"服务卸载失败: {e}")
        return False
    except Exception as e:
        logger.error(f"服务卸载过程中出错: {e}")
        print(f"服务卸载过程中出错: {e}")
        return False


def update_service():
    """更新服务配置"""
    try:
        # 尝试找到NSSM
        if os.path.exists(NSSM_EXE):
            nssm_path = NSSM_EXE
        else:
            # 尝试使用系统PATH中的NSSM
            try:
                subprocess.run(["nssm", "version"], check=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
                nssm_path = "nssm"
            except:
                logger.error("无法找到NSSM工具，请手动更新服务")
                return False
        
        # 检查服务是否存在
        try:
            result = subprocess.run([nssm_path, "status", SERVICE_NAME], 
                                  stdout=subprocess.PIPE, stderr=subprocess.PIPE)
            if result.returncode != 0:
                logger.warning(f"服务 {SERVICE_NAME} 不存在，将安装新服务")
                return install_service()
        except Exception as e:
            logger.warning(f"检查服务状态时出错: {e}")
        
        # 停止服务
        logger.info(f"正在停止服务: {SERVICE_NAME}")
        subprocess.run([nssm_path, "stop", SERVICE_NAME], check=False)
        
        # 更新服务配置
        logger.info(f"正在更新服务配置: {SERVICE_NAME}")
        subprocess.run([nssm_path, "set", SERVICE_NAME, "Application", PYTHON_EXE], check=True)
        subprocess.run([nssm_path, "set", SERVICE_NAME, "AppParameters", MAIN_SCRIPT], check=True)
        
        # 设置工作目录
        work_dir = os.path.dirname(os.path.abspath(__file__))
        logger.info(f"设置工作目录: {work_dir}")
        subprocess.run([nssm_path, "set", SERVICE_NAME, "AppDirectory", work_dir], check=True)
        
        # 启动服务
        logger.info(f"重启服务: {SERVICE_NAME}")
        subprocess.run([nssm_path, "start", SERVICE_NAME], check=True)
        
        logger.info(f"服务 {SERVICE_NAME} 更新成功")
        print(f"\n服务 {SERVICE_DISPLAY_NAME} 已成功更新并重启！")
        return True
    except subprocess.CalledProcessError as e:
        logger.error(f"服务更新失败: {e}")
        print(f"服务更新失败: {e}")
        return False
    except Exception as e:
        logger.error(f"服务更新过程中出错: {e}")
        print(f"服务更新过程中出错: {e}")
        return False


def create_config_example():
    """创建配置示例文件"""
    config_example = {
        "email": {
            "smtp_server": "smtp.qq.com",  # 示例：QQ邮箱SMTP服务器
            "smtp_port": 587,
            "username": "your_email@qq.com",
            "password": "your_password_or_app_token",  # 注意：QQ邮箱需要使用授权码
            "sender": "your_email@qq.com",
            "recipients": ["admin@example.com"]
        },
        "reboot_warning_hours": 24,  # 提前24小时发送警告邮件
        "reboot_warning_minutes": 30,  # 提前30分钟发送最终警告
        "check_interval_seconds": 3600  # 每小时检查一次
    }
    
    import json
    with open("reboot_config_example.json", "w", encoding="utf-8") as f:
        json.dump(config_example, f, indent=4, ensure_ascii=False)
    
    print("\n已创建配置示例文件: reboot_config_example.json")
    print("请根据您的实际情况修改配置文件，然后将其重命名为 reboot_config.json")


def main():
    """主函数"""
    global ctypes
    import ctypes
    
    print("=" * 60)
    print("    自动重启服务 - Windows服务管理工具    ")
    print("=" * 60)
    
    # 检查是否以管理员权限运行
    if not is_admin():
        print("此操作需要管理员权限！")
        print("正在尝试以管理员权限重新运行...")
        run_as_admin()
        sys.exit(1)
    
    # 解析命令行参数
    if len(sys.argv) > 1:
        if sys.argv[1] == "--uninstall":
            uninstall_service()
        elif sys.argv[1] == "--update":
            update_service()
        elif sys.argv[1] == "--create-config":
            create_config_example()
        else:
            print(f"未知参数: {sys.argv[1]}")
            print("\n用法:")
            print("  install_service.py           - 安装服务")
            print("  install_service.py --uninstall    - 卸载服务")
            print("  install_service.py --update       - 更新服务")
            print("  install_service.py --create-config - 创建配置示例")
    else:
        # 默认安装服务
        print("准备安装自动重启服务...")
        
        # 先创建配置示例
        create_config_example()
        
        # 提示用户先配置
        input("\n请先配置好邮件设置，然后按回车键继续安装...")
        
        # 安装服务
        install_service()


if __name__ == "__main__":
    main()