#!/opt/homebrew/bin/python3.11
"""
最终关机工具 - Final Shutdown Tool
解决所有关机问题：认证、超时、进程树、sudo权限
"""

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


def run_command_with_auth(cmd, timeout=30, use_sudo=False, password=None):
    """运行命令，支持认证和sudo"""
    try:
        if use_sudo and password:
            # 使用 expect 处理 sudo 密码输入
            sudo_cmd = f'echo "{password}" | sudo -S {cmd}'
            result = subprocess.run(
                sudo_cmd, shell=True, capture_output=True, text=True, timeout=timeout
            )
        elif use_sudo:
            # 尝试直接 sudo（可能需要终端交互）
            result = subprocess.run(
                f"sudo {cmd}",
                shell=True,
                capture_output=True,
                text=True,
                timeout=timeout,
            )
        else:
            result = subprocess.run(
                cmd, shell=True, capture_output=True, text=True, timeout=timeout
            )

        return result.returncode == 0, result.stdout.strip(), result.stderr.strip()
    except subprocess.TimeoutExpired:
        return False, f"超时 ({timeout}s)", ""
    except Exception as e:
        return False, "", str(e)


def find_processes_by_keywords(keywords):
    """更可靠的进程查找"""
    processes = []
    for proc in psutil.process_iter(["pid", "name", "cmdline", "username"]):
        try:
            cmdline = " ".join(proc.info["cmdline"]) if proc.info["cmdline"] else ""
            name = proc.info["name"] or ""
            username = proc.info["username"] or ""

            # 跳过系统进程和 root 进程（除非明确需要）
            if username == "root" and "caddy" not in cmdline.lower():
                continue

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


def stop_process_tree_completely(pid, timeout=15):
    """完全停止进程树"""
    try:
        parent = psutil.Process(pid)

        # 获取所有子进程（递归）
        children = parent.children(recursive=True)
        all_processes = [parent] + children

        print(f"  停止进程树: PID {pid} (共 {len(all_processes)} 个进程)")

        # 1. 发送 SIGTERM 给所有进程
        for proc in all_processes:
            try:
                proc.terminate()
            except:
                pass

        # 2. 等待
        time.sleep(3)

        # 3. 检查哪些进程还在运行
        still_running = []
        for proc in all_processes:
            try:
                if proc.is_running():
                    still_running.append(proc)
            except:
                pass

        # 4. 如果还有进程在运行，发送 SIGKILL
        if still_running:
            print(f"    {len(still_running)} 个进程仍在运行，发送 SIGKILL...")
            for proc in still_running:
                try:
                    proc.kill()
                except:
                    pass

            # 最后等待
            time.sleep(2)

        # 5. 最终检查
        final_running = []
        for proc in all_processes:
            try:
                if proc.is_running():
                    final_running.append(proc)
            except:
                pass

        return len(final_running) == 0

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


def stop_service_comprehensive(
    service_name, keywords, stop_commands=None, sudo_commands=None, password="accusys"
):
    """综合停止服务"""
    print(f"\n停止 {service_name}...")

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

    # 2. 执行停止命令（如果有）
    if stop_commands:
        for cmd in stop_commands:
            print(f"  执行命令: {cmd}")

            # 检查是否需要认证
            needs_auth = "redis-cli" in cmd or "mysqladmin" in cmd
            use_sudo = "pg_ctl" in cmd or "mongod" in cmd

            success, stdout, stderr = run_command_with_auth(
                cmd,
                timeout=20,
                use_sudo=use_sudo,
                password=password if use_sudo else None,
            )

            if not success:
                print(f"    命令失败")
                if stderr:
                    print(f"    错误: {stderr[:100]}")

    # 3. 执行 sudo 命令（如果需要）
    if sudo_commands:
        for cmd in sudo_commands:
            print(f"  执行 sudo 命令: {cmd}")
            success, stdout, stderr = run_command_with_auth(
                cmd, timeout=15, use_sudo=True, password=password
            )
            if not success:
                print(f"    sudo 命令失败: {stderr[:100] if stderr else '未知错误'}")

    # 4. 等待命令生效
    time.sleep(5)

    # 5. 停止所有找到的进程树
    processes = find_processes_by_keywords(keywords)
    if processes:
        print(f"  仍有 {len(processes)} 个进程在运行，停止进程树...")
        for proc in processes:
            stop_process_tree_completely(proc.pid, timeout=10)

    # 6. 最终检查
    time.sleep(3)
    remaining = find_processes_by_keywords(keywords)
    if remaining:
        print(f"  ❌ {service_name} 仍在运行 ({len(remaining)} 个进程)")

        # 显示剩余进程信息
        for proc in remaining[:5]:  # 只显示前5个
            try:
                cmdline = (
                    " ".join(proc.info["cmdline"])
                    if proc.info["cmdline"]
                    else proc.info["name"]
                )
                print(f"    PID {proc.pid}: {cmdline[:80]}...")
            except:
                print(f"    PID {proc.pid}: (无法获取信息)")

        if len(remaining) > 5:
            print(f"    ... 还有 {len(remaining) - 5} 个进程")

        return False
    else:
        print(f"  ✅ {service_name} 已停止")
        return True


def main():
    print("=" * 70)
    print("最终关机工具 - 解决所有关机问题")
    print(f"时间: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}")
    print("=" * 70)

    # 密码（从环境变量或默认值）
    password = os.getenv("SUDO_PASSWORD", "accusys")

    # 服务定义（基于测试结果优化）
    services = [
        {
            "name": "Redis",
            "keywords": ["redis-server"],
            "stop_commands": ["redis-cli -a accusys shutdown"],
            "sudo_commands": None,
        },
        {
            "name": "PostgreSQL",
            "keywords": ["postgres"],
            "stop_commands": [
                "pg_ctl -D /Users/accusys/momentry/var/postgresql stop -m fast -t 60"
            ],
            "sudo_commands": None,
        },
        {
            "name": "AI 处理器",
            "keywords": [
                "asr_processor",
                "ocr_processor",
                "yolo_processor",
                "face_processor",
                "pose_processor",
                "cut_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": "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 -paccusys shutdown"],
            "sudo_commands": None,
        },
        {
            "name": "Qdrant",
            "keywords": ["qdrant"],
            "stop_commands": None,
            "sudo_commands": None,
        },
    ]

    results = []

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

    # 生成报告
    print("\n" + "=" * 70)
    print("关机完成报告")
    print("=" * 70)

    all_stopped = True
    stopped_count = 0

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

    print(f"\n停止进度: {stopped_count}/{len(services)} 个服务已停止")

    # 收集所有关键词用于检查剩余进程
    all_keywords = []
    for service in services:
        all_keywords.extend(service["keywords"])

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

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

    # 最终建议
    print("\n" + "=" * 70)
    if all_stopped:
        print("🎉 所有服务已成功停止！")
        print("系统可以安全关机。")
        print("\n建议关机命令:")
        print("  sudo shutdown -h now  # 立即关机")
        print("  sudo reboot           # 重启")
    else:
        print("⚠️  部分服务仍在运行。")
        print("\n下一步建议:")
        print("1. 手动检查并停止剩余进程")
        print("2. 使用以下命令强制关机:")
        print("   sudo shutdown -h now")
        print("3. 系统会在关机时自动处理剩余进程")
        print("\n注意: 强制关机可能会导致数据丢失，建议先保存重要工作。")

    # 保存详细报告
    report_file = f"/tmp/final_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("=" * 50 + "\n")
        f.write(f"结果: {'完全成功' if all_stopped else '部分成功'}\n")
        f.write(f"停止进度: {stopped_count}/{len(services)} 个服务\n\n")

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

        if not all_stopped:
            f.write("\n仍在运行的进程:\n")
            remaining = find_processes_by_keywords(all_keywords)
            for proc in remaining:
                try:
                    cmdline = (
                        " ".join(proc.info["cmdline"])
                        if proc.info["cmdline"]
                        else proc.info["name"]
                    )
                    f.write(f"  PID {proc.pid}: {cmdline}\n")
                except:
                    f.write(f"  PID {proc.pid}: (无法获取信息)\n")

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

    return all_stopped


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

        traceback.print_exc()
        sys.exit(1)
