#!/usr/bin/env python3
"""
日程管家 · 自动部署到腾讯云服务器
===============================
通过 paramiko SSH 连接，上传文件并执行setup。
"""
import paramiko
import os
import sys
import tarfile
import io
import time
from pathlib import Path

# ─── 配置 ───
SERVER_IP = "110.42.206.64"
SERVER_PORT = 22
SERVER_USER = "root"
SERVER_PASS = "Doudou1981"

LOCAL_DIR = Path(__file__).parent.parent  # schedule/
DEPLOY_DIR = "/opt/schedule"
SERVICE_PORT = "8765"

# ─── 连接 ───
def connect():
    client = paramiko.SSHClient()
    client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
    print(f"🔗 连接 {SERVER_USER}@{SERVER_IP} ...")
    client.connect(SERVER_IP, port=SERVER_PORT, username=SERVER_USER, password=SERVER_PASS, timeout=15)
    print("✅ 已连接")
    return client

# ─── 打包上传 ───
def upload_files(client):
    print("📦 打包本地文件 ...")

    # 创建内存中的 tar.gz
    buf = io.BytesIO()
    with tarfile.open(fileobj=buf, mode="w:gz") as tar:
        for f in LOCAL_DIR.rglob("*"):
            rel = f.relative_to(LOCAL_DIR.parent)
            if "deploy/deploy_to_server.py" in str(rel) or "__pycache__" in str(rel):
                continue
            if f.is_file():
                tar.add(f, arcname=str(rel))
            elif f.is_dir():
                tar.add(f, arcname=str(rel), recursive=False)
    buf.seek(0)

    print(f"📤 上传到服务器 ({len(buf.getvalue())} 字节) ...")

    sftp = client.open_sftp()
    remote_tar = f"{DEPLOY_DIR}/schedule.tar.gz"

    # 创建目录
    try:
        sftp.mkdir(DEPLOY_DIR)
    except:
        pass

    sftp.putfo(buf, remote_tar)
    sftp.close()
    print("✅ 文件上传完成")

# ─── 执行部署命令 ───
def run_setup(client):
    commands = [
        # 清理旧文件
        f"rm -rf {DEPLOY_DIR}/schedule",
        f"cd {DEPLOY_DIR} && tar -xzf schedule.tar.gz",
        f"cd {DEPLOY_DIR} && ls -la",
        # 检查 Python
        "python3 --version",
        # 确保 data 目录存在
        f"mkdir -p {DEPLOY_DIR}/schedule/data",
        # 初始化空数据文件（如果不存在）
        f'[ ! -f {DEPLOY_DIR}/schedule/data/tasks.json ] && echo \'{{"_description":"统一任务数据库","tasks":[],"_last_scan":null}}\' > {DEPLOY_DIR}/schedule/data/tasks.json || echo "tasks.json 已存在"',
        f'[ ! -f {DEPLOY_DIR}/schedule/data/daily_plan.json ] && echo \'{{}}\' > {DEPLOY_DIR}/schedule/data/daily_plan.json || echo "daily_plan.json 已存在"',
        # 复制 projects.json（如果不存在）
        f'[ ! -f {DEPLOY_DIR}/schedule/data/projects.json ] && echo \'{{"_description":"项目空间映射配置","projects":[{{"id":"ai-qifu","name":"AI企服外脑","workspace":"","color":"#1E4DB7","icon":"brain"}},{{"id":"ai-qifu-os","name":"AI企服操作系统","workspace":"","color":"#7F77DD","icon":"cpu"}},{{"id":"hro-system","name":"HRO AI原生系统","workspace":"","color":"#1D9E75","icon":"users"}},{{"id":"personal","name":"个人事务","workspace":"","color":"#E8A838","icon":"calendar"}}]}}\' > {DEPLOY_DIR}/schedule/data/projects.json || echo "projects.json 已存在"',
        # 创建日志目录
        f"mkdir -p {DEPLOY_DIR}/schedule/logs",
        # 创建 systemd service
        f'''cat > /etc/systemd/system/schedule-api.service << 'EOFSERVICE'
[Unit]
Description=日程管家 API 服务
After=network.target

[Service]
Type=simple
User=root
WorkingDirectory={DEPLOY_DIR}/schedule
Environment="SCHEDULE_HOST=0.0.0.0"
Environment="SCHEDULE_PORT={SERVICE_PORT}"
Environment="DASHBOARD_URL=http://{SERVER_IP}:{SERVICE_PORT}/dashboard.html"
ExecStart=/usr/bin/python3 {DEPLOY_DIR}/schedule/server.py
Restart=always
RestartSec=3

[Install]
WantedBy=multi-user.target
EOFSERVICE''',
        # 启停服务
        "systemctl daemon-reload",
        "systemctl stop schedule-api 2>/dev/null || true",
        "systemctl enable schedule-api",
        "systemctl start schedule-api",
        "sleep 2",
        "systemctl status schedule-api --no-pager | head -20",
    ]

    for cmd in commands:
        print(f"\n⚡ 执行: {cmd[:80]}...")
        stdin, stdout, stderr = client.exec_command(cmd, timeout=30)
        exit_code = stdout.channel.recv_exit_status()
        output = stdout.read().decode("utf-8", errors="replace")
        err = stderr.read().decode("utf-8", errors="replace")
        if output.strip():
            print(output.strip())
        if err.strip() and exit_code != 0:
            print(f"⚠️  {err.strip()}")

# ─── 验证部署 ───
def verify(client):
    print("\n🔍 验证部署 ...")
    stdin, stdout, stderr = client.exec_command(
        f"curl -s -o /dev/null -w '%{{http_code}}' http://localhost:{SERVICE_PORT}/api/tasks",
        timeout=10
    )
    exit_code = stdout.channel.recv_exit_status()
    result = stdout.read().decode("utf-8").strip()
    if result == "200":
        print(f"✅ API 响应正常 (HTTP {result})")
    else:
        print(f"⚠️  API 响应: {result}")

    print(f"\n🎉 部署完成！")
    print(f"📋 日程看板: http://{SERVER_IP}:{SERVICE_PORT}/dashboard.html")
    print(f"")
    print(f"⚠️  请确保腾讯云防火墙已放行端口 {SERVICE_PORT}")
    print(f"   控制台 → 云服务器 → 防火墙 → 添加规则")
    print(f"   协议: TCP | 端口: {SERVICE_PORT} | 来源: 0.0.0.0/0")

# ─── 主流程 ───
def main():
    client = None
    try:
        client = connect()
        upload_files(client)
        run_setup(client)
        verify(client)
    except Exception as e:
        print(f"\n❌ 部署失败: {e}")
        sys.exit(1)
    finally:
        if client:
            client.close()

if __name__ == "__main__":
    main()
