"""E2E conftest：清理 API fixture + session 兜底 + manifest"""

import os
import uuid
import atexit
import pytest
import requests as http_requests

API_BASE = os.environ.get("API_BASE", "http://localhost:8083")
POLL_INTERVAL = 5
MAX_WAIT_DISPATCH = 120
MAX_WAIT_AGENT = 300
E2E_PREFIX = "e2e-v27-"


def _check_environment():
    """前置检查：daemon 是否运行"""
    try:
        resp = http_requests.get(f"{API_BASE}/api/projects", timeout=5)
        assert resp.status_code == 200, f"daemon 未响应: {resp.status_code}"
    except Exception as e:
        pytest.skip(f"daemon 未运行: {e}")


def _pid(prefix: str = E2E_PREFIX) -> str:
    """生成唯一测试项目ID"""
    return f"{prefix}{uuid.uuid4().hex[:8]}"


def _tid() -> str:
    """生成唯一任务ID"""
    return f"e2e-task-{uuid.uuid4().hex[:8]}"


def _cleanup_project(pid: str):
    """清理单个项目"""
    try:
        http_requests.delete(
            f"{API_BASE}/api/projects/{pid}?physical=true", timeout=10
        )
    except Exception:
        pass


def _get_db_path(pid: str):
    """获取项目 blackboard.db 路径"""
    from src.utils import get_data_root
    return get_data_root() / pid / "blackboard.db"


def _create_project(tracked_list, name_prefix="E2E", agents=None):
    """创建测试项目并记录到 manifest"""
    pid = _pid()
    config = {}
    if agents:
        config["agents"] = agents
    resp = http_requests.post(
        f"{API_BASE}/api/projects",
        json={"id": pid, "name": f"{name_prefix}-{pid}", "config": config},
        timeout=10,
    )
    assert resp.status_code == 200, f"创建项目失败: {resp.text}"
    tracked_list.append(pid)
    return pid


def _create_task(pid, **kwargs):
    """创建测试任务"""
    tid = kwargs.get("id") or _tid()
    body = {"id": tid, "status": "pending", "priority": 5, **kwargs}
    resp = http_requests.post(
        f"{API_BASE}/api/projects/{pid}/tasks", json=body, timeout=10
    )
    assert resp.status_code == 200, f"创建任务失败: {resp.text}"
    return tid


def _poll_task(pid, tid, timeout=MAX_WAIT_AGENT, terminal_states=("done", "failed", "cancelled")):
    """轮询任务状态直到终态"""
    import time
    start = time.time()
    while time.time() - start < timeout:
        resp = http_requests.get(
            f"{API_BASE}/api/projects/{pid}/tasks/{tid}", timeout=10
        )
        if resp.status_code == 200:
            data = resp.json()
            status = data.get("status", "")
            if status in terminal_states:
                return data
        time.sleep(POLL_INTERVAL)
    return {"status": "timeout", "tid": tid}


# ── Session 级 fixture ──

@pytest.fixture(scope="session")
def e2e_session_prefix():
    """Session 级唯一前缀"""
    return f"e2e-v27-{uuid.uuid4().hex[:6]}-"


_session_manifest = []


@pytest.fixture(scope="session", autouse=True)
def e2e_session_cleanup():
    """Session 结束时兜底清理所有 e2e- 前缀项目"""
    yield
    for pid in list(_session_manifest):
        _cleanup_project(pid)
    _session_manifest.clear()
