# -*- coding: utf-8 -*-
"""bg proc host 模式手工验证(ASCII-only 输出,GBK console 安全)。

场景:
1. shell background 启动一个 ~6s 的命令 -> 立即返回
2. 期间 status = running
3. 结束后 status = finished, exit_code=0, 日志内容对
4. inline python background + kill
5. count_running / list_procs / sweep 冒烟
"""
import shutil
import sys
import tempfile
import time
from pathlib import Path

sys.path.insert(0, str(Path(__file__).resolve().parents[1]))

from core import procs  # noqa: E402

anchor = Path(tempfile.mkdtemp(prefix="zcbot_bgproc_test_"))
task_id = "11111111-1111-1111-1111-111111111111"
fails = []


def check(name, cond):
    print(("[ok] " if cond else "[FAIL] ") + name)
    if not cond:
        fails.append(name)


# 1. python inline bg: 3s 后打印再退出
code = "import time\nprint('phase1', flush=True)\ntime.sleep(3)\nprint('phase2 done', flush=True)\n"
t0 = time.time()
pid1, d1 = procs.launch_host(
    anchor, task_id, kind="python", command_display="python <inline>",
    cwd=anchor, timeout_s=120, env=None, inline_code=code,
    argv=None, shell_cmd=None,
)
launch_elapsed = time.time() - t0
check("launch returns fast (<2s), got %.2fs" % launch_elapsed, launch_elapsed < 2)

time.sleep(1.5)
meta1 = procs.read_meta(d1)
st, ec = procs.status_of(meta1, d1)
check("running mid-flight (got %s)" % st, st == "running")
check("count_running == 1 (got %d)" % procs.count_running(anchor), procs.count_running(anchor) == 1)

for _ in range(20):
    time.sleep(0.5)
    st, ec = procs.status_of(procs.read_meta(d1), d1)
    if st == "finished":
        break
check("finished with exit 0 (got %s/%s)" % (st, ec), st == "finished" and ec == 0)
log = procs.tail_log(d1)
check("log has phase2 output", "phase2 done" in log)

# 2. timeout kill: sleep 60 but timeout_s=61 clamp floor -> use argv sleep via python
code2 = "import time\ntime.sleep(600)\n"
pid2, d2 = procs.launch_host(
    anchor, task_id, kind="python", command_display="python <sleeper>",
    cwd=anchor, timeout_s=120, env=None, inline_code=code2,
    argv=None, shell_cmd=None,
)
time.sleep(1.5)
meta2 = procs.read_meta(d2)
st2, _ = procs.status_of(meta2, d2)
check("sleeper running", st2 == "running")
msg = procs.kill_proc(meta2, d2)
time.sleep(1.0)
st2b, ec2 = procs.status_of(procs.read_meta(d2), d2)
check("killed -> finished 137 (got %s/%s, msg=%s)" % (st2b, ec2, msg),
      st2b == "finished" and ec2 == 137)

# 3. list + format
items = procs.list_procs(anchor, task_id)
check("list_procs sees 2 (got %d)" % len(items), len(items) == 2)
for m in items:
    print("    " + procs.format_proc_line(m))

# 4. sweep: nothing removed (fresh), then with ttl=0 removes finished dirs
stats = procs.sweep(anchor.parent / "_nonexistent_users")
stats2 = procs.sweep(anchor.parent, ttl_s=10 ** 9)  # anchor.parent as users base: anchor is one 'user'
# note: sweep expects user_root_base -> iterates children; anchor.parent contains anchor
check("sweep noop keeps dirs", (anchor / procs.PROCS_SUBDIR / task_id).is_dir())
stats3 = procs.sweep(anchor.parent, ttl_s=0)
remaining = list((anchor / procs.PROCS_SUBDIR / task_id).glob("*")) if (anchor / procs.PROCS_SUBDIR / task_id).is_dir() else []
check("sweep ttl=0 removed finished dirs (left %d)" % len(remaining), len(remaining) == 0)

shutil.rmtree(anchor, ignore_errors=True)
print()
if fails:
    print("RESULT: %d FAILURE(S): %s" % (len(fails), "; ".join(fails)))
    sys.exit(1)
print("RESULT: ALL PASS")
