#!/usr/bin/env python3
"""GUARDiA Manager 서버 배포 스크립트"""
import paramiko, time, sys, os, io, zipfile

HOST = 'zioinfo.co.kr'; USER = 'root'; PASS = '1q2w3e!Q'
LOCAL_DIST    = 'C:/GUARDiA/manager/dist'
LOCAL_BACKEND = 'C:/GUARDiA/manager/backend'
SEP = chr(92)

client = paramiko.SSHClient()
client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
client.connect(HOST, username=USER, password=PASS, timeout=15)
sftp = client.open_sftp()

def run(label, cmd, timeout=60):
    print(f'\n[{label}]')
    chan = client.get_transport().open_session()
    chan.set_combine_stderr(True)
    chan.exec_command(cmd)
    start = time.time()
    while not chan.exit_status_ready():
        if chan.recv_ready(): sys.stdout.buffer.write(chan.recv(4096)); sys.stdout.flush()
        if time.time() - start > timeout: print('[TIMEOUT]'); break
        time.sleep(0.2)
    while chan.recv_ready(): sys.stdout.buffer.write(chan.recv(4096))
    sys.stdout.flush()
    rc = chan.recv_exit_status()
    print(f'\n→ exit={rc}')
    return rc

# 1. 서버 디렉터리 생성
run('디렉터리 생성',
    'mkdir -p /var/www/manager /opt/manager/backend /opt/manager/logs && echo ok')

# 2. React 빌드 결과 zip → 업로드
print('\n[dist 파일 패키징...]')
zip_buf = io.BytesIO()
count = 0
with zipfile.ZipFile(zip_buf, 'w', zipfile.ZIP_DEFLATED) as zf:
    for root, dirs, files in os.walk(LOCAL_DIST):
        rel = os.path.relpath(root, LOCAL_DIST).replace(SEP, '/')
        for f in files:
            arc = f if rel == '.' else f'{rel}/{f}'
            zf.write(os.path.join(root, f), arc); count += 1
zip_buf.seek(0)
with sftp.open('/tmp/manager-dist.zip', 'wb') as f: f.write(zip_buf.read())
print(f'{count}개 파일 업로드')
run('dist 배포', 'cd /var/www/manager && unzip -q -o /tmp/manager-dist.zip && echo "deployed" && ls | head -5')

# 3. 백엔드 소스 업로드
print('\n[백엔드 소스 업로드...]')
for item in os.listdir(LOCAL_BACKEND):
    lp = os.path.join(LOCAL_BACKEND, item)
    if os.path.isfile(lp) and item.endswith('.py'):
        sftp.put(lp, f'/opt/manager/backend/{item}')
        print(f'  {item}')
# routers / core
for sub in ('routers', 'core'):
    sub_dir = os.path.join(LOCAL_BACKEND, sub)
    if not os.path.isdir(sub_dir): continue
    run(f'{sub} 디렉터리', f'mkdir -p /opt/manager/backend/{sub}')
    for fn in os.listdir(sub_dir):
        if fn.endswith('.py'):
            sftp.put(os.path.join(sub_dir, fn), f'/opt/manager/backend/{sub}/{fn}')
            print(f'  {sub}/{fn}')
# requirements + .env
for fn in ('requirements.txt', '.env'):
    lp = os.path.join(LOCAL_BACKEND, fn)
    if os.path.exists(lp):
        sftp.put(lp, f'/opt/manager/backend/{fn}')
        print(f'  {fn}')

# 4. Python venv + 패키지
run('Python venv',
    'python3 -m venv /opt/manager/venv && '
    '/opt/manager/venv/bin/pip install -r /opt/manager/backend/requirements.txt -q && echo ok',
    120)

# 5. .env 서버 JWT secret 동기화
run('.env JWT secret 동기화',
    "GUARDIA_SECRET=$(grep GUARDIA_JWT_SECRET /opt/guardia/app/.env 2>/dev/null | cut -d= -f2-) && "
    "if [ -n \"$GUARDIA_SECRET\" ]; then "
    "  sed -i \"s|GUARDIA_JWT_SECRET=.*|GUARDIA_JWT_SECRET=$GUARDIA_SECRET|\" /opt/manager/backend/.env && "
    "  echo 'JWT secret synced'; fi")

# 6. systemd 서비스
svc = """[Unit]
Description=GUARDiA Manager API Backend
After=network.target guardia.service

[Service]
User=root
WorkingDirectory=/opt/manager/backend
EnvironmentFile=-/opt/manager/backend/.env
ExecStart=/opt/manager/venv/bin/uvicorn main:app --host 127.0.0.1 --port 8002 --workers 1
Restart=on-failure
RestartSec=5
StandardOutput=append:/opt/manager/logs/backend.log
StandardError=append:/opt/manager/logs/backend.log

[Install]
WantedBy=multi-user.target
"""
with sftp.open('/etc/systemd/system/guardia-manager.service', 'w') as f: f.write(svc)

# 7. Nginx 설정
nginx_conf = r"""server {
    listen 8090;
    server_name _;
    root /var/www/manager;
    index index.html;
    location / {
        try_files $uri $uri/ /index.html;
        add_header Cache-Control no-cache;
    }
    location /api/ {
        proxy_pass         http://127.0.0.1:8002;
        proxy_http_version 1.1;
        proxy_set_header   Host $host;
        proxy_set_header   X-Real-IP $remote_addr;
        proxy_read_timeout 60s;
    }
    location /guardia-api/ {
        proxy_pass         http://127.0.0.1:8001/;
        proxy_set_header   Host $host;
        proxy_set_header   X-Real-IP $remote_addr;
    }
    location ~* \.(js|css|png|ico|svg|woff2)$ {
        expires 7d;
        add_header Cache-Control "public, immutable";
    }
    gzip on;
    gzip_types text/plain text/css application/javascript application/json;
}
"""
with sftp.open('/etc/nginx/sites-available/guardia-manager', 'w') as f: f.write(nginx_conf)

# 8. 서비스 시작
run('UFW 8090 오픈', 'ufw allow 8090/tcp && ufw allow 8002/tcp && echo ok')
run('systemd 등록 + 시작',
    'systemctl daemon-reload && '
    'systemctl enable guardia-manager && '
    'systemctl restart guardia-manager && '
    'sleep 5 && systemctl is-active guardia-manager')

run('Nginx 활성화',
    'ln -sf /etc/nginx/sites-available/guardia-manager /etc/nginx/sites-enabled/ && '
    'nginx -t && systemctl reload nginx && echo NGINX_OK')

# 9. 헬스체크
run('헬스체크', 'curl -s http://localhost:8002/health && echo "" && '
    'curl -s -o /dev/null -w "Manager UI: HTTP %{http_code}" http://localhost:8090/')

sftp.close(); client.close()
print('\n\n=== 배포 완료 ===')
print('GUARDiA Manager: http://zioinfo.co.kr:8090')
