#!/usr/bin/env python3
"""
AgentOven Python SDK — Integration Test for Agent CRUD + Delete Fix.

Tests the full lifecycle: register → list → get → delete → verify gone.
Requires the control plane server running at http://localhost:8080.

Run:
    python3 sdk/python/tests/test_agent_crud.py
"""

import sys
import traceback

from agentoven import Agent, Ingredient, AgentOvenClient

SERVER = "http://localhost:8080"
KITCHEN = "default"
TEST_AGENT_NAME = "sdk-test-delete-agent"
TEST_AGENT_NAME_2 = "sdk-test-phantom-agent"

passed = 0
failed = 0


def ok(label: str):
    global passed
    passed += 1
    print(f"  ✅ PASS: {label}")


def fail(label: str, detail: str = ""):
    global failed
    failed += 1
    msg = f"  ❌ FAIL: {label}"
    if detail:
        msg += f" — {detail}"
    print(msg)


def section(title: str):
    print(f"\n{'─' * 60}")
    print(f"  {title}")
    print(f"{'─' * 60}")


# ── Setup ─────────────────────────────────────────────────────

def cleanup(client: AgentOvenClient):
    """Delete test agents if they exist from a previous run."""
    try:
        client.delete(TEST_AGENT_NAME)
    except Exception:
        pass
    try:
        client.delete(TEST_AGENT_NAME_2)
    except Exception:
        pass


# ── Tests ─────────────────────────────────────────────────────

def test_register_agent(client: AgentOvenClient):
    """Register a new agent."""
    section("1. Register Agent")
    agent = Agent(
        TEST_AGENT_NAME,
        description="Temporary agent for delete test",
        ingredients=[
            Ingredient.model("gpt-4o", provider="openai"),
        ],
    )
    try:
        result = client.register(agent)
        if TEST_AGENT_NAME in result:
            ok(f"Register returned: {result}")
        else:
            fail("Register", f"unexpected result: {result}")
    except Exception as e:
        fail("Register", str(e))


def test_list_agents_contains(client: AgentOvenClient):
    """List agents and verify our test agent is present."""
    section("2. List Agents (should contain test agent)")
    try:
        agents = client.list_agents()
        names = [a.name for a in agents]
        if TEST_AGENT_NAME in names:
            ok(f"Found '{TEST_AGENT_NAME}' in {len(agents)} agents")
        else:
            fail("List", f"'{TEST_AGENT_NAME}' not in {names}")
    except Exception as e:
        fail("List", str(e))


def test_delete_agent_success(client: AgentOvenClient):
    """Delete the test agent — should succeed."""
    section("3. Delete Agent (should succeed)")
    try:
        result = client.delete(TEST_AGENT_NAME)
        ok(f"Delete returned: {result}")
    except Exception as e:
        fail("Delete success", str(e))


def test_agent_gone_after_delete(client: AgentOvenClient):
    """After delete, the agent should no longer appear in the list."""
    section("4. Verify Agent Gone")
    try:
        agents = client.list_agents()
        names = [a.name for a in agents]
        if TEST_AGENT_NAME not in names:
            ok(f"'{TEST_AGENT_NAME}' no longer in agent list")
        else:
            fail("Verify gone", f"'{TEST_AGENT_NAME}' still in list!")
    except Exception as e:
        fail("Verify gone", str(e))


def test_delete_nonexistent_agent(client: AgentOvenClient):
    """Delete a non-existent agent — should raise an error (404)."""
    section("5. Delete Non-Existent Agent (should fail with 404)")
    try:
        result = client.delete(TEST_AGENT_NAME_2)
        fail("Delete non-existent", f"Expected error but got: {result}")
    except RuntimeError as e:
        err_msg = str(e)
        if "404" in err_msg or "not found" in err_msg.lower():
            ok(f"Got expected error: {err_msg}")
        else:
            fail("Delete non-existent", f"Wrong error (expected 404): {err_msg}")
    except Exception as e:
        fail("Delete non-existent", f"Unexpected exception type: {type(e).__name__}: {e}")


def test_delete_by_object(client: AgentOvenClient):
    """Register, then delete by Agent object (not string)."""
    section("6. Delete by Agent Object")
    agent = Agent(
        "sdk-test-obj-delete",
        description="Test object-based delete",
        ingredients=[Ingredient.model("gpt-4o", provider="openai")],
    )
    try:
        client.register(agent)
        result = client.delete(agent)
        ok(f"Delete by object returned: {result}")
    except Exception as e:
        fail("Delete by object", str(e))
    finally:
        # Clean up just in case
        try:
            client.delete("sdk-test-obj-delete")
        except Exception:
            pass


def test_double_delete(client: AgentOvenClient):
    """Register, delete, then delete again — second delete should fail."""
    section("7. Double Delete (second should fail)")
    agent_name = "sdk-test-double-del"
    try:
        agent = Agent(agent_name, description="Double delete test")
        client.register(agent)
        client.delete(agent_name)
        ok("First delete succeeded")
    except Exception as e:
        fail("Double delete setup", str(e))
        return

    try:
        result = client.delete(agent_name)
        fail("Second delete", f"Expected error but got: {result}")
    except RuntimeError as e:
        err_msg = str(e)
        if "404" in err_msg or "not found" in err_msg.lower():
            ok(f"Second delete correctly rejected: {err_msg}")
        else:
            fail("Second delete", f"Wrong error: {err_msg}")
    except Exception as e:
        fail("Second delete", f"Unexpected: {type(e).__name__}: {e}")


# ── Main ──────────────────────────────────────────────────────

def main():
    print("=" * 60)
    print("  AgentOven Python SDK — Agent CRUD + Delete Test")
    print(f"  Server: {SERVER}  Kitchen: {KITCHEN}")
    print("=" * 60)

    client = AgentOvenClient(url=SERVER, kitchen=KITCHEN)
    print(f"\n  Client: {client}")

    # Clean up from previous runs
    cleanup(client)

    # Run tests
    test_register_agent(client)
    test_list_agents_contains(client)
    test_delete_agent_success(client)
    test_agent_gone_after_delete(client)
    test_delete_nonexistent_agent(client)
    test_delete_by_object(client)
    test_double_delete(client)

    # Summary
    total = passed + failed
    print(f"\n{'=' * 60}")
    print(f"  Results: {passed}/{total} passed, {failed} failed")
    print(f"{'=' * 60}")

    if failed > 0:
        sys.exit(1)


if __name__ == "__main__":
    main()
