
import urllib.request
import json
import time

with open("G:/erp/.test_token") as f:
    token = f.read().strip()

base = "http://localhost:3000"

def api(method, path, data=None, tok=None):
    url = base + path
    headers = {"Content-Type": "application/json"}
    if tok:
        headers["Authorization"] = f"Bearer {tok}"
    body = json.dumps(data).encode("utf-8") if data else None
    req = urllib.request.Request(url, data=body, headers=headers, method=method)
    start = int(time.time()*1000)
    try:
        with urllib.request.urlopen(req) as resp:
            elapsed = int(time.time()*1000) - start
            return resp.status, json.loads(resp.read().decode("utf-8")), elapsed
    except urllib.error.HTTPError as e:
        elapsed = int(time.time()*1000) - start
        try:
            rbody = json.loads(e.read().decode("utf-8"))
        except:
            rbody = {"raw": str(e)}
        return e.code, rbody, elapsed

results = []

def log(test_id, name, code, ms, details):
    status = "PASS" if (200 <= code < 300) or (code == 400) or (code == 404) or (code == 409) else "FAIL"
    print(f"  [{status}] {name}: HTTP {code}, {ms}ms - {details[:100]}")
    results.append((test_id, name, status, code, ms, details))

print("=" * 60)
print("Part 2: User Management Endpoints")
print("=" * 60)

# 2.1 GET /users
code, body, ms = api("GET", "/api/v1/users", tok=token)
data = body.get("data", {})
items = data.get("items", [])
log("2.1", "GET /users - list", code, ms, f"total={data.get("total")}, items={len(items)}, success={body.get("success")}")

# 2.2 GET /users with pagination
code, body, ms = api("GET", "/api/v1/users?page=1&page_size=1", tok=token)
data = body.get("data", {})
log("2.2", "GET /users?page=1&page_size=1", code, ms, f"total={data.get("total")}, page={data.get("page")}, page_size={data.get("page_size")}, items={len(data.get("items",[]))}")

# 2.3 POST /users - create
code, body, ms = api("POST", "/api/v1/users", {
    "username": "test_user_api",
    "password": "Test@2026!",
    "display_name": "API Test User",
    "email": "test@api.com",
    "phone": "13800138000"
}, tok=token)
ud = body.get("data", {})
test_user_id = ud.get("id", "") if ud else ""
log("2.3", "POST /users - create", code, ms, f"id={test_user_id}, username={ud.get("username")}, status={ud.get("status")}, pw_in_resp={"password" in ud}" if ud else f"FAIL: {body}")

if test_user_id:
    with open("G:/erp/.test_user_id", "w") as f:
        f.write(test_user_id)

# 2.4 duplicate username
code, body, ms = api("POST", "/api/v1/users", {
    "username": "test_user_api",
    "password": "Test@2026!",
    "display_name": "Duplicate User"
}, tok=token)
log("2.4", "POST /users - duplicate username", code, ms, f"Expected 400/409, got {code}: {json.dumps(body, ensure_ascii=False)[:100]}")

# 2.5 missing fields
code, body, ms = api("POST", "/api/v1/users", {
    "display_name": "No username"
}, tok=token)
log("2.5", "POST /users - missing fields", code, ms, f"code={code}")

# 2.6 short password
code, body, ms = api("POST", "/api/v1/users", {
    "username": "short_pwd_user",
    "password": "12",
    "display_name": "Short Pwd"
}, tok=token)
log("2.6", "POST /users - short password", code, ms, f"code={code}, body={json.dumps(body, ensure_ascii=False)[:100]}")

if test_user_id:
    # 2.7 GET single user
    code, body, ms = api("GET", f"/api/v1/users/{test_user_id}", tok=token)
    ud = body.get("data", {})
    log("2.7", "GET /users/{id}", code, ms, f"found={ud.get("id")==test_user_id}, pw_in_resp={"password" in ud}, status={ud.get("status")}" if ud else f"body={body}")

    # 2.8 GET invalid UUID
    code, body, ms = api("GET", "/api/v1/users/00000000-0000-0000-0000-000000000000", tok=token)
    log("2.8", "GET /users/invalid-uuid", code, ms, f"code={code}")

    # 2.9 PUT - normal update
    code, body, ms = api("PUT", f"/api/v1/users/{test_user_id}", {
        "display_name": "Updated User",
        "email": "updated@api.com",
        "version": 1
    }, tok=token)
    ud = body.get("data", {})
    log("2.9", "PUT /users/{id} - update", code, ms, f"display_name={ud.get("display_name")}, email={ud.get("email")}, version={ud.get("version")}" if ud else f"body={body}")

    # 2.10 PUT - optimistic lock conflict
    code, body, ms = api("PUT", f"/api/v1/users/{test_user_id}", {
        "display_name": "Conflict",
        "version": 999
    }, tok=token)
    log("2.10", "PUT /users/{id} - version conflict", code, ms, f"code={code}, body={json.dumps(body, ensure_ascii=False)[:100]}")

    # 2.11 assign roles
    code_r, body_r, _ = api("GET", "/api/v1/roles", tok=token)
    roles = body_r.get("data", {}).get("items", [])
    if roles:
        admin_role_id = roles[0]["id"]
        code, body, ms = api("POST", f"/api/v1/users/{test_user_id}/roles", {"role_ids": [admin_role_id]}, tok=token)
        log("2.11", "POST /users/{id}/roles", code, ms, f"code={code}")
    else:
        log("2.11", "POST /users/{id}/roles", 0, 0, "SKIP: no roles found")

print("
" + "=" * 60)
print("Part 2 Summary")
print("=" * 60)
passed = sum(1 for r in results if r[2]=="PASS")
failed = sum(1 for r in results if r[2]=="FAIL")
print(f"Passed: {passed}, Failed: {failed}, Total: {len(results)}")
