"""Integration tests for owlvin-tools — every tool, happy + edge + error."""
import os
import sys
import tempfile
import time

# Ensure we test the installed package, not the local server.py
from owlvin_tools.server import search, _classify, _extract_sql, _extract_path

PASS = 0
FAIL = 0

def check(name, result, expect_in=None, expect_not=None):
    global PASS, FAIL
    ok = True
    reason = ""
    if expect_in:
        for term in expect_in:
            if term.lower() not in result.lower():
                ok = False
                reason = f"missing '{term}'"
                break
    if expect_not:
        for term in expect_not:
            if term.lower() in result.lower():
                ok = False
                reason = f"contains '{term}'"
                break
    if ok:
        PASS += 1
        print(f"  PASS  {name}")
    else:
        FAIL += 1
        print(f"  FAIL  {name} — {reason}")
        print(f"        {result[:150]}")


def test(name, query, **kwargs):
    try:
        result = search(query)
        check(name, result, **kwargs)
    except Exception as e:
        global FAIL
        FAIL += 1
        print(f"  CRASH {name} — {e}")


# ─── Input guards ───
print("\n=== Input Guards ===")
test("None input", None, expect_in=["no query"])
test("Empty string", "", expect_in=["no query"])
test("Whitespace", "   ", expect_in=["no query"])
test("Integer input", 42, expect_in=["no query"])

# ─── Web search ───
print("\n=== Web Search ===")
test("Basic search", "what is Python programming language",
     expect_not=["no results", "error:"])
test("Search no results gracefully", "xyzzyplughqwertyuiop12345",
     expect_not=["traceback", "error:"])

# ─── Health ───
print("\n=== Health Checks ===")
test("Health: drumsplit", "is drumsplit healthy",
     expect_in=["drumsplit"], expect_not=["quote", "approve_url"])
test("Health: all", "health status check",
     expect_in=["drumsplit"])
test("Health: custom URL", "health https://example.com",
     expect_not=["traceback"])

# ─── Processes ───
print("\n=== Process Management ===")
test("Process list", "what processes are running", expect_in=["PID"])
test("Ports", "what ports are listening", expect_in=["LISTEN"])
test("Find process", "find process python", expect_in=["python"])
test("Kill guard", "kill launchd", expect_in=["refused"])

# ─── Secrets ───
print("\n=== Secrets ===")
os.environ["TEST_API_KEY"] = "sk-test-1234567890abcdef"
test("Secret: check exists", "check TEST_API_KEY",
     expect_in=["TEST_API_KEY", "exists"])
test("Secret: show masked", "show TEST_API_KEY",
     expect_not=["sk-test-1234567890abcdef"])
test("Secret: missing key", "check NONEXISTENT_SECRET_KEY",
     expect_in=["not found"])
del os.environ["TEST_API_KEY"]

# ─── Cost ───
print("\n=== Cost ===")
test("Cost: no API key", "how much have I spent",
     expect_in=["no api key"])

# ─── Lint ───
print("\n=== Code Linting ===")
# Create a file with a known lint issue
lint_file = tempfile.mktemp(suffix=".py")
with open(lint_file, "w") as f:
    f.write("import os\nimport sys\nx = 1\n")
test("Lint: find issues", f"lint {lint_file}", expect_in=["ruff"])
test("Lint: missing file", "lint /nonexistent/file.py", expect_in=["not found"])
os.unlink(lint_file)

# ─── Data ───
print("\n=== Data Queries ===")
csv_file = tempfile.mktemp(suffix=".csv")
with open(csv_file, "w") as f:
    f.write("name,age\nalice,30\nbob,25\ncharlie,35\n")
try:
    import duckdb
    HAS_DUCKDB = True
except ImportError:
    HAS_DUCKDB = False
if HAS_DUCKDB:
    test("SQL: basic query", f'SELECT name FROM data WHERE age > 28 {csv_file}',
         expect_in=["alice", "charlie"])
    test("SQL: count", f'SELECT count(*) as n FROM data {csv_file}',
         expect_in=["3"])
    test("SQL: missing file", "SELECT * FROM data /nonexistent/file.csv",
         expect_in=["not found"])
else:
    test("SQL: no duckdb", f'SELECT count(*) FROM data {csv_file}',
         expect_in=["not available"])
os.unlink(csv_file)

# ─── Document conversion ───
print("\n=== Document Conversion ===")
test("Convert: missing docling", "convert /tmp/test.pdf",
     expect_not=["traceback"])
test("Convert: missing file", "convert /nonexistent/doc.pdf",
     expect_in=["not found"])

# ─── Podcast ───
print("\n=== Podcast ===")
try:
    import feedparser
    test("Podcast: no URL", "latest podcast episode",
         expect_in=["provide", "url"])
except ImportError:
    test("Podcast: no feedparser", "latest podcast episode",
         expect_in=["not available"])

# ─── Memory ───
print("\n=== Memory ===")
# Memory should degrade on systems without recall scripts
has_recall = os.path.exists(os.path.expanduser("~/AI_HUB/_MEMORY/recall.py"))
if has_recall:
    test("Memory: recall", "recall drumsplit", expect_not=["traceback"])
else:
    test("Memory: not configured", "recall something",
         expect_in=["not configured"])

# ─── Service discovery ───
print("\n=== Service Discovery ===")
test("Discovery: list services", "what services are available",
     expect_in=["drumsplit"])
test("Discovery: audio listing", "what audio services do you have",
     expect_in=["drumsplit"], expect_not=["approve_url"])

# ─── URL fetch ───
print("\n=== URL Fetch ===")
test("Fetch: example.com", "https://example.com",
     expect_in=["example"], expect_not=["traceback"])

# ─── Adversarial ───
print("\n=== Adversarial ===")
test("Massive input", "a" * 5000, expect_not=["traceback"])
test("Path traversal", "convert ../../../../etc/passwd",
     expect_not=["root:x:"])
test("Unicode", "search 你好世界 مرحبا 🎵", expect_not=["traceback"])

# ─── Unit checks ───
print("\n=== Unit Checks ===")
# _classify
assert _classify("is drumsplit healthy") == "health", f"classify health failed: {_classify('is drumsplit healthy')}"
PASS += 1; print("  PASS  classify: health intent")

assert _classify("what ports are open") == "process", f"classify process failed"
PASS += 1; print("  PASS  classify: process intent")

# _extract_sql
sql = _extract_sql("SELECT name FROM data WHERE age > 30 /tmp/test.csv")
assert sql and "WHERE" in sql, f"extract_sql lost WHERE: {sql}"
PASS += 1; print("  PASS  extract_sql: preserves WHERE")

# _extract_path
path = _extract_path("lint /tmp/my_code.py", ("py",))
assert path == "/tmp/my_code.py", f"extract_path failed: {path}"
PASS += 1; print("  PASS  extract_path: finds .py")

# ─── Summary ───
print(f"\n{'='*50}")
print(f"TOTAL: {PASS + FAIL} | PASS: {PASS} | FAIL: {FAIL}")
print(f"{'='*50}")
sys.exit(1 if FAIL > 0 else 0)
