#!/usr/bin/env python3
"""E2E: 节点 CRUD + 搜索 + 位置"""
from helper import *

header("Nodes")

pid = create_project(unique_name("E2E-节点"))
nid1 = create_node(pid, "目标主机", "host", "## 192.168.1.1")["id"]

# ── Create ──
ok("create node")

assert_ok(get(f"/api/v1/projects/{pid}/nodes/{nid1}"))
ok("get node by id")

# ── List ──
nodes = assert_ok(get(f"/api/v1/projects/{pid}/nodes"))
assert len(nodes) == 1
ok("list nodes (1 node)")

# ── Create with after + edge ──
nid2 = create_node(pid, "发现 Nacos", "service", "## 端口 8848",
                   after=nid1, edge_label="端口扫描")["id"]
ok("create with after + edge")

# Edge should exist
edges = assert_ok(get(f"/api/v1/projects/{pid}/edges"))
assert len(edges) == 1 and edges[0]["label"] == "端口扫描"
ok("auto-edge created")

# ── Update ──
assert_ok(put(f"/api/v1/projects/{pid}/nodes/{nid1}",
              {"label": "目标主机(已更新)", "node_type": "host"}))
n = assert_ok(get(f"/api/v1/projects/{pid}/nodes/{nid1}"))
assert n["label"] == "目标主机(已更新)"
ok("update node label")

# Update with set_verdict
assert_ok(put(f"/api/v1/projects/{pid}/nodes/{nid1}",
              {"set_verdict": "success"}))
n = assert_ok(get(f"/api/v1/projects/{pid}/nodes/{nid1}"))
assert n["properties"]["verdict"] == "success"
ok("update node verdict")

# Update with set_evidence
assert_ok(put(f"/api/v1/projects/{pid}/nodes/{nid1}",
              {"set_evidence": "confirmed"}))
n = assert_ok(get(f"/api/v1/projects/{pid}/nodes/{nid1}"))
assert n["properties"]["evidence"] == "confirmed"
ok("update node evidence")

# Filter by node_type/verdict/evidence
filtered = assert_ok(get(f"/api/v1/projects/{pid}/nodes?node_type=host&verdict=success&evidence=confirmed"))
assert len(filtered) == 1 and filtered[0]["id"] == nid1
ok("list nodes filters by type/verdict/evidence")

# ── Search ──
results = assert_ok(get(f"/api/v1/projects/{pid}/nodes/search?q=Nacos"))
assert len(results) == 1
ok("search finds Nacos")

results = assert_ok(get(f"/api/v1/projects/{pid}/nodes/search?q=nonexistent12345"))
assert len(results) == 0
ok("search empty result")

# ── Delete ──
delete_node_force(pid, nid2)
assert len(assert_ok(get(f"/api/v1/projects/{pid}/nodes"))) == 1
ok("force delete connected node")

# Cannot delete connected node without force
create_node(pid, "再发现 Redis", "service", "## 6379", after=nid1, edge_label="继续扫描")
assert_err(delete(f"/api/v1/projects/{pid}/nodes/{nid1}"), 409)
delete_node_force(pid, nid1)
assert len(assert_ok(get(f"/api/v1/projects/{pid}/nodes"))) == 1
assert len(assert_ok(get(f"/api/v1/projects/{pid}/edges"))) == 0
ok("force delete connected node cascades edges")

# ── 404 cases ──
assert_err(get(f"/api/v1/projects/{pid}/nodes/{nid2}"), 404)
ok("404 on deleted node")

# Cleanup
delete_project(pid)

summary()
