# -*- coding: utf-8 -*-
'''
STEP121-7 PATCH 1
server_manager.py 현재 배치 표시 개선 패치

사용:
    cd /d D:\\honghee\\server_manager
    python patch_STEP121_7_current_job_status.py

적용 후:
    python -m py_compile server_manager.py
    python server_manager.py
'''

from pathlib import Path
from datetime import datetime
import sys

BASE = Path(__file__).resolve().parent
TARGET = BASE / "server_manager.py"

if not TARGET.exists():
    print("[ERROR] server_manager.py not found:", TARGET)
    sys.exit(1)

src = TARGET.read_text(encoding="utf-8", errors="replace")
backup = BASE / f"server_manager_backup_STEP121_7_1_{datetime.now().strftime('%Y%m%d_%H%M%S')}.py"
backup.write_text(src, encoding="utf-8")
print("[BACKUP]", backup)

helper_marker = "\ndef current_job_status():\n"

helper_code = '''

def find_python_process_by_keyword(keyword):
    keyword = str(keyword or "").lower().replace("/", "\\\\")
    if not keyword:
        return None

    ps_cmd = (
        'powershell -NoProfile -Command '
        '"Get-CimInstance Win32_Process | '
        'Where-Object {$_.Name -eq \'python.exe\'} | '
        'Select-Object ProcessId,CommandLine | ConvertTo-Json -Compress"'
    )

    out, err, code = run_cmd_capture(ps_cmd)
    if not out:
        return None

    try:
        data = json.loads(out)
        if isinstance(data, dict):
            data = [data]

        for item in data or []:
            cmd = str(item.get("CommandLine") or "")
            cmd_norm = cmd.lower().replace("/", "\\\\")
            if keyword in cmd_norm:
                return {
                    "pid": int(item.get("ProcessId") or 0),
                    "command_line": cmd,
                }
    except Exception:
        return None

    return None


def get_latest_running_pipeline():
    rows, err = db_query_all("""
        SELECT
            id,
            run_type,
            status,
            started_at,
            TIMESTAMPDIFF(MINUTE, started_at, NOW()) AS running_minutes,
            message
        FROM blog_pipeline_runs
        WHERE status = 'running'
        ORDER BY id DESC
        LIMIT 1
    """)

    if err or not rows:
        return None

    return rows[0]
'''

if helper_marker not in src:
    print("[ERROR] current_job_status marker not found")
    sys.exit(2)

if "def find_python_process_by_keyword(" not in src:
    src = src.replace(helper_marker, helper_code + helper_marker, 1)
    print("[PATCH] helper functions inserted")
else:
    print("[SKIP] helper functions already exist")

old_current_job_status = '''def current_job_status():
    if job_process and job_process.poll() is None:
        return {"running": True, "pid": job_process.pid}
    return {"running": False, "pid": None}
'''

new_current_job_status = '''def current_job_status():
    """
    현재 배치 상태.
    우선순위:
    1) server_manager가 직접 실행한 job_process
    2) DB blog_pipeline_runs.status='running'
    3) 실행 중인 python.exe command line 보조 탐색
    """
    if job_process and job_process.poll() is None:
        return {
            "running": True,
            "pid": job_process.pid,
            "source": "manager",
            "label": "Manager 실행중",
            "detail": f"pid {job_process.pid}",
        }

    running = get_latest_running_pipeline()
    if running:
        run_type = str(running.get("run_type") or "")
        pid = None
        cmd = ""

        keyword_map = {
            "publish_worker": "workers\\\\publish_worker.py",
            "private_queue_worker": "workers\\\\private_queue_worker.py",
            "schedule_daily_articles": "jobs\\\\schedule_daily_articles.py",
            "fetch_article_detail": "naver_response_article_fetcher",
            "generate_blog_drafts": "jobs\\\\generate_blog_drafts.py",
            "daily_pipeline_runner": "jobs\\\\daily_pipeline_runner.py",
        }

        keyword = keyword_map.get(run_type, run_type)
        found = find_python_process_by_keyword(keyword)
        if found:
            pid = found.get("pid")
            cmd = found.get("command_line") or ""

        return {
            "running": True,
            "pid": pid,
            "source": "db",
            "run_id": running.get("id"),
            "run_type": run_type,
            "label": f"DB 실행중: {run_type or '-'}",
            "detail": f"run_id {running.get('id')} / {int(running.get('running_minutes') or 0)}분",
            "command_line": cmd,
        }

    return {
        "running": False,
        "pid": None,
        "source": "",
        "label": "대기",
        "detail": "",
    }
'''

if old_current_job_status not in src:
    print("[ERROR] current_job_status block not matched. No changes written.")
    sys.exit(3)

src = src.replace(old_current_job_status, new_current_job_status, 1)
print("[PATCH] current_job_status replaced")

old_top_job = '''    job_badge = "🟢 실행 중" if job["running"] else "⚪ 대기"
    job_pid = job["pid"] or "-"
'''
new_top_job = '''    job_badge = "🟢 실행 중" if job.get("running") else "⚪ 대기"
    job_pid = job.get("pid") or "-"
    job_detail = job.get("label") or job.get("detail") or ""
    if job.get("detail"):
        job_detail = f"{job_detail}<br>{html_escape(job.get('detail'))}"
'''

if old_top_job not in src:
    print("[ERROR] job_badge block not matched. No changes written.")
    sys.exit(4)

src = src.replace(old_top_job, new_top_job, 1)
print("[PATCH] dashboard job badge variables replaced")

old_card = '''    <div class="summary-card">
        <div class="label">현재 배치</div>
        <div class="summary-title">{job_badge}</div>
        <div class="muted">pid {job_pid}</div>
    </div>
'''
new_card = '''    <div class="summary-card">
        <div class="label">현재 배치</div>
        <div class="summary-title">{job_badge}</div>
        <div class="muted">pid {job_pid}<br>{job_detail}</div>
    </div>
'''

if old_card not in src:
    print("[ERROR] current batch card block not matched. No changes written.")
    sys.exit(5)

src = src.replace(old_card, new_card, 1)
print("[PATCH] dashboard current batch card replaced")

TARGET.write_text(src, encoding="utf-8")
print("[DONE] STEP121-7 PATCH 1 applied")
print("[NEXT] python -m py_compile server_manager.py")
