#!/opt/homebrew/bin/python3.11
"""
终极关机工具 - Ultimate Shutdown Tool
使用更彻底的方法停止所有服务，解决进程检测和权限问题
Ultimate tool for stopping all services, solving process detection and permission issues
"""

import os
import sys
import time
import signal
import subprocess
import psutil
from datetime import datetime


def run_command(cmd, timeout=30):
    """运行命令并返回输出"""
    try:
        result = subprocess.run(
            cmd, shell=True, capture_output=True, text=True, timeout=timeout
        )
        return result.returncode == 0, result.stdout.strip()
    except subprocess.TimeoutExpired:
        return False, f"超时 ({timeout}s)"
    except Exception as e:
        return False, str(e)


def find_processes(keywords):
    """查找包含关键字的进程"""
    processes = []
    for proc in psutil.process_iter(["pid", "name", "cmdline"]):
        try:
            cmdline = " ".join(proc.info["cmdline"]) if proc.info["cmdline"] else ""
            name = proc.info["name"] or ""

            for keyword in keywords:
                if keyword in cmdline or keyword in name:
                    processes.append(proc)
                    break
        except (psutil.NoSuchProcess, psutil.AccessDenied):
            continue
    return processes


def stop_process_tree(pid, timeout=10):
    """停止进程树（父进程和所有子进程）"""
    try:
        parent = psutil.Process(pid)
        children = parent.children(recursive=True)

        # 先停止子进程
        for child in children:
            try:
                child.terminate()
            except:
                pass

        # 停止父进程
        parent.terminate()

        # 等待进程结束
        try:
            parent.wait(timeout=timeout)
        except psutil.TimeoutExpired:
            alive = [parent] + children
        else:
            alive = []

        # 检查子进程
        for child in children:
            try:
                if child.is_running():
                    alive.append(child)
            except:
                pass

        # 如果还有存活的，强制停止
        for p in alive:
            try:
                p.kill()
            except:
                pass

        return len(alive) == 0
    except psutil.NoSuchProcess:
        return True
    except Exception as e:
        print(f"停止进程 {pid} 失败: {e}")
        return False


def stop_service(
    service_name, process_keywords, stop_commands=None, sudo_commands=None
):
    """停止服务"""
    print(f"\n停止 {service_name}...")

    # 1. 查找进程
    processes = find_processes(process_keywords)
    print(f"  找到 {len(processes)} 个进程")

    # 2. 执行停止命令（如果有）
    if stop_commands:
        for cmd in stop_commands:
            print(f"  执行命令: {cmd}")
            success, output = run_command(cmd, timeout=15)
            if not success:
                print(f"  命令失败: {output}")

    # 3. 执行 sudo 命令（如果需要）
    if sudo_commands:
        for cmd in sudo_commands:
            print(f"  执行 sudo 命令: {cmd}")
            sudo_cmd = f"echo 'accusys' | sudo -S {cmd}"
            success, output = run_command(sudo_cmd, timeout=15)
            if not success:
                print(f"  sudo 命令失败: {output}")

    # 4. 等待
    time.sleep(5)

    # 5. 检查并停止进程树
    processes = find_processes(process_keywords)
    if processes:
        print(f"  仍有 {len(processes)} 个进程在运行，停止进程树...")
        for proc in processes:
            stop_process_tree(proc.pid, timeout=5)

    # 6. 最终检查
    time.sleep(3)
    remaining = find_processes(process_keywords)
    if remaining:
        print(f"  ❌ {service_name} 仍在运行 ({len(remaining)} 个进程)")
        return False
    else:
        print(f"  ✅ {service_name} 已停止")
        return True


def main():
    print("=" * 60)
    print("终极关机工具")
    print(f"时间: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}")
    print("=" * 60)

    # 服务定义
    services = [
        {
            "name": "AI 处理器",
            "keywords": [
                "asr_processor",
                "ocr_processor",
                "yolo_processor",
                "face_processor",
                "pose_processor",
                "cut_processor",
                "asrx_processor",
                "caption_processor",
                "story_processor",
            ],
            "stop_commands": None,
            "sudo_commands": None,
        },
        {
            "name": "Momentry 服务",
            "keywords": ["momentry server", "momentry worker", "momentry_playground"],
            "stop_commands": None,
            "sudo_commands": None,
        },
        {
            "name": "MCP 服务器",
            "keywords": [
                "mcp-server-redis",
                "mcp-server-postgres",
                "mcp-server-filesystem",
                "mcp-server-qdrant",
                "mongodb-mcp-server",
                "gitea-mcp-server",
            ],
            "stop_commands": None,
            "sudo_commands": None,
        },
        {
            "name": "应用服务",
            "keywords": ["php-fpm", "n8n", "ollama", "gitea web", "sftpgo serve"],
            "stop_commands": None,
            "sudo_commands": None,
        },
        {
            "name": "Caddy",
            "keywords": ["caddy"],
            "stop_commands": None,
            "sudo_commands": ["pkill -TERM caddy", "pkill -KILL caddy"],
        },
        {
            "name": "Redis",
            "keywords": ["redis-server"],
            "stop_commands": ["redis-cli shutdown"],
            "sudo_commands": None,
        },
        {
            "name": "PostgreSQL",
            "keywords": ["postgres"],
            "stop_commands": [
                "pg_ctl -D /Users/accusys/momentry/var/postgresql stop -m fast"
            ],
            "sudo_commands": None,
        },
        {
            "name": "MongoDB",
            "keywords": ["mongod"],
            "stop_commands": None,
            "sudo_commands": [
                "mongod --dbpath /opt/homebrew/var/mongodb --shutdown",
                "pkill -TERM mongod",
                "pkill -KILL mongod",
            ],
        },
        {
            "name": "MariaDB",
            "keywords": ["mariadbd"],
            "stop_commands": ["mysqladmin -u root shutdown"],
            "sudo_commands": None,
        },
        {
            "name": "Qdrant",
            "keywords": ["qdrant"],
            "stop_commands": None,
            "sudo_commands": None,
        },
    ]

    results = []

    # 停止所有服务
    for service in services:
        success = stop_service(
            service["name"],
            service["keywords"],
            service.get("stop_commands"),
            service.get("sudo_commands"),
        )
        results.append((service["name"], success))

    # 最终检查
    print("\n" + "=" * 60)
    print("最终状态检查")
    print("=" * 60)

    all_stopped = True
    for service_name, success in results:
        if success:
            print(f"✅ {service_name}: 已停止")
        else:
            print(f"❌ {service_name}: 仍在运行")
            all_stopped = False

    # 列出所有仍在运行的进程
    if not all_stopped:
        print("\n仍在运行的进程:")
        print("-" * 40)

        all_keywords = []
        for service in services:
            all_keywords.extend(service["keywords"])

        remaining = find_processes(all_keywords)
        for proc in remaining:
            try:
                cmdline = (
                    " ".join(proc.info["cmdline"])
                    if proc.info["cmdline"]
                    else proc.info["name"]
                )
                print(f"  PID {proc.pid}: {cmdline[:100]}...")
            except:
                print(f"  PID {proc.pid}: (无法获取信息)")

    print("\n" + "=" * 60)
    if all_stopped:
        print("✅ 所有服务已停止！")
        print("系统可以安全关机。")
    else:
        print("⚠️  部分服务仍在运行。")
        print("建议:")
        print("1. 手动检查并停止剩余进程")
        print("2. 使用 'sudo shutdown -h now' 强制关机")
        print("3. 系统会在关机时处理剩余进程")

    # 生成报告
    report_file = f"/tmp/ultimate_shutdown_report_{int(time.time())}.txt"
    with open(report_file, "w") as f:
        f.write("终极关机工具报告\n")
        f.write(f"时间: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}\n")
        f.write("=" * 40 + "\n")
        f.write(f"结果: {'成功' if all_stopped else '部分成功'}\n\n")

        f.write("服务状态:\n")
        for service_name, success in results:
            f.write(f"  {service_name}: {'✅ 已停止' if success else '❌ 仍在运行'}\n")

    print(f"\n详细报告保存到: {report_file}")
    print("=" * 60)


if __name__ == "__main__":
    try:
        main()
    except KeyboardInterrupt:
        print("\n\n操作被用户中断")
        sys.exit(130)
    except Exception as e:
        print(f"\n错误: {e}")
        sys.exit(1)
