"""E2E API Test Script - Test all CuCu Note endpoints after auth fix"""
import asyncio
import sys
import json
import urllib.request
import urllib.error

BASE = "http://localhost:5000"

def request(method, path, body=None, token=None):
    url = BASE + path
    data = json.dumps(body).encode() if body else None
    headers = {"Content-Type": "application/json"}
    if token:
        headers["Authorization"] = f"Bearer {token}"
    req = urllib.request.Request(url, data=data, headers=headers, method=method)
    try:
        with urllib.request.urlopen(req, timeout=10) as resp:
            raw = resp.read()
            return resp.status, json.loads(raw) if raw.strip() else {}
    except urllib.error.HTTPError as e:
        raw = e.read()
        try:
            return e.code, json.loads(raw) if raw.strip() else {"http_error": e.code}
        except Exception:
            return e.code, {"raw": raw.decode(errors='replace')[:200]}
    except Exception as ex:
        return 0, {"error": str(ex)}

def ok(code):
    return "PASS" if code in (200, 201) else "FAIL"

results = []

print("=" * 60)
print("CuCu Note API E2E Test Suite")
print("=" * 60)

# =============================================
# 1. AUTH - Sign In
# =============================================
print("\n[1] AUTH - Sign In")
code, data = request("POST", "/api/v1/auth/signin", {"email": "test@example.com", "password": "Password123!"})
token = data.get("accessToken", "")
print(f"  POST /auth/signin -> {code} {ok(code)} | token={token[:30] if token else 'NONE'}...")
results.append(("Auth: Sign In", ok(code)))

# =============================================
# 2. AUTH - Get Me (Profile)
# =============================================
print("\n[2] AUTH - Get Me")
code, data = request("GET", "/api/v1/auth/me", token=token)
user_id = data.get("id", "")
print(f"  GET /auth/me -> {code} {ok(code)} | user_id={user_id} email={data.get('email')}")
results.append(("Auth: Get Me / Profile", ok(code)))

# =============================================
# 3. MEMOS - Create
# =============================================
print("\n[3] MEMOS - Create new memo")
code, data = request("POST", "/api/v1/memos", {"content": "Hello from E2E test! #test", "visibility": "PRIVATE"}, token=token)
memo_uid = data.get("uid") or data.get("id", "")
memo_id = data.get("id", "")
print(f"  POST /memos -> {code} {ok(code)} | memo_id={memo_id} uid={memo_uid}")
results.append(("Memos: Create Memo", ok(code)))

# =============================================
# 4. MEMOS - List
# =============================================
print("\n[4] MEMOS - List memos")
code, data = request("GET", "/api/v1/memos", token=token)
memo_count = len(data) if isinstance(data, list) else data.get("total", "?")
print(f"  GET /memos -> {code} {ok(code)} | count={memo_count}")
results.append(("Memos: List Memos", ok(code)))

# =============================================
# 5. MEMOS - Edit
# =============================================
print("\n[5] MEMOS - Edit memo")
if memo_id:
    code, data = request("PATCH", f"/api/v1/memos/{memo_id}", {"content": "Updated by E2E test! #test #edited"}, token=token)
    print(f"  PATCH /memos/{memo_id} -> {code} {ok(code)}")
    results.append(("Memos: Edit Memo", ok(code)))
else:
    print("  SKIP (no memo_id)")
    results.append(("Memos: Edit Memo", "SKIP"))

# =============================================
# 6. MEMOS - Change Visibility
# =============================================
print("\n[6] MEMOS - Change Visibility to PUBLIC")
if memo_id:
    code, data = request("PATCH", f"/api/v1/memos/{memo_id}", {"visibility": "PUBLIC"}, token=token)
    print(f"  PATCH /memos/{memo_id} visibility=PUBLIC -> {code} {ok(code)}")
    results.append(("Memos: Change Visibility", ok(code)))
else:
    results.append(("Memos: Change Visibility", "SKIP"))

# =============================================
# 7. MEMOS - Pin
# =============================================
print("\n[7] MEMOS - Pin memo")
if memo_id:
    code, data = request("PATCH", f"/api/v1/memos/{memo_id}/pin", None, token=token)
    if code == 0:
        code, data = request("POST", f"/api/v1/memos/{memo_id}/pin", {"pinned": True}, token=token)
    print(f"  PIN /memos/{memo_id}/pin -> {code} {ok(code)}")
    results.append(("Memos: Pin Memo", ok(code)))
else:
    results.append(("Memos: Pin Memo", "SKIP"))

# =============================================
# 8. REACTIONS - Add emoji reaction
# =============================================
print("\n[8] REACTIONS - Add emoji reaction")
if memo_id:
    code, data = request("POST", f"/api/v1/memos/{memo_id}/reactions", {"reaction_type": "THUMBS_UP"}, token=token)
    print(f"  POST /memos/{memo_id}/reactions -> {code} {ok(code)} | {data}")
    results.append(("Reactions: Add Emoji", ok(code)))
else:
    results.append(("Reactions: Add Emoji", "SKIP"))

# =============================================
# 9. COMMENTS - Post a comment
# =============================================
print("\n[9] COMMENTS - Post a comment on memo")
if memo_uid:
    code, data = request("POST", "/api/v1/memos", {"content": "This is a test comment!", "parent": str(memo_id)}, token=token)
    print(f"  POST /memos (comment) -> {code} {ok(code)} | {data.get('id')}")
    results.append(("Comments: Post Comment", ok(code)))
else:
    results.append(("Comments: Post Comment", "SKIP"))

# =============================================
# 10. TEAMS - List teams
# =============================================
print("\n[10] TEAMS - List teams")
code, data = request("GET", "/api/v1/teams", token=token)
print(f"  GET /teams -> {code} {ok(code)} | {data}")
results.append(("Teams: List Teams", ok(code)))

# =============================================
# 11. TEAMS - Create team
# =============================================
print("\n[11] TEAMS - Create a team")
code, data = request("POST", "/api/v1/teams", {"name": "E2E Test Team", "description": "Auto-created by E2E test"}, token=token)
team_id = data.get("id")
print(f"  POST /teams -> {code} {ok(code)} | team_id={team_id}")
results.append(("Teams: Create Team", ok(code)))

# =============================================
# 12. INBOX - List notifications
# =============================================
print("\n[12] INBOX - List notifications")
if user_id:
    code, data = request("GET", f"/api/v1/users/{user_id}/inbox/unread_count", token=token)
    print(f"  GET /inbox -> {code} {ok(code)} | {data}")
    results.append(("Inbox: List Notifications", ok(code)))
else:
    results.append(("Inbox: List Notifications", "SKIP"))

# =============================================
# 13. INSTANCE - Get instance info
# =============================================
print("\n[13] INSTANCE - Get instance info")
code, data = request("GET", "/api/v1/instance")
print(f"  GET /instance -> {code} {ok(code)} | {data}")
results.append(("Instance: Get Info", ok(code)))

# =============================================
# SUMMARY
# =============================================
print("\n" + "=" * 60)
print("TEST RESULTS SUMMARY")
print("=" * 60)
passed = sum(1 for _, r in results if r == "PASS")
failed = sum(1 for _, r in results if r == "FAIL")
skipped = sum(1 for _, r in results if r == "SKIP")
for name, result in results:
    icon = "[+]" if result == "PASS" else "[-]" if result == "FAIL" else "[~]"
    print(f"  {icon} {name}: {result}")
print(f"\nTotal: {passed} PASS / {failed} FAIL / {skipped} SKIP")
