import os
import sys
from pathlib import Path

from fastapi.testclient import TestClient

# Use project root on sys.path
ROOT_DIR = Path(__file__).resolve().parent
if str(ROOT_DIR) not in sys.path:
    sys.path.insert(0, str(ROOT_DIR))

# Disable auth/rate limit for tests
os.environ["DISABLE_AUTH"] = "true"
os.environ["REDIS_CACHE_TURN_ON"] = "false"
os.environ.setdefault("OPENAI_API_KEY", "test-key")

from memos_core.db import DB_PATH, execute, init_memo_db  # noqa: E402
import memos_core.services as memo_services  # noqa: E402
from server import app  # noqa: E402


# Stub out embedding calls during tests to avoid external OpenAI dependency
async def _noop_embed(self, *_args, **_kwargs):  # pragma: no cover
    return None


memo_services.MemoService._upsert_stub_embedding = _noop_embed  # type: ignore[attr-defined]


def setup_module(module=None):
    # Ensure DB exists and is clean
    Path(DB_PATH).parent.mkdir(parents=True, exist_ok=True)

    async def _reset():
        await init_memo_db()
        await execute("DELETE FROM memo_embeddings")
        await execute("DELETE FROM memos")

    import asyncio

    asyncio.run(_reset())


client = TestClient(app)


def test_memo_crud_flow():
    # Create memo
    resp = client.post(
        "/api/v1/memos",
        json={"content": "hello world", "visibility": "PUBLIC", "tags": ["daily", "test"]},
    )
    assert resp.status_code == 200
    memo = resp.json()
    memo_id = memo["id"]
    assert memo["content"] == "hello world"

    # List memos
    resp = client.get("/api/v1/memos")
    assert resp.status_code == 200
    lst = resp.json()
    assert any(m["id"] == memo_id for m in lst)

    # Get memo
    resp = client.get(f"/api/v1/memos/{memo_id}")
    assert resp.status_code == 200
    data = resp.json()
    assert data["content"] == "hello world"

    # Update memo
    resp = client.patch(f"/api/v1/memos/{memo_id}", json={"content": "updated", "tags": ["daily"]})
    assert resp.status_code == 200
    updated = resp.json()
    assert updated["content"] == "updated"
    assert updated["tags"] == ["daily"]

    # Delete memo
    resp = client.delete(f"/api/v1/memos/{memo_id}")
    assert resp.status_code == 200
    assert resp.json()["status"] == "success"


def test_memo_embedding_flow():
    # Clean tables
    async def _reset():
        await init_memo_db()
        await execute("DELETE FROM memo_embeddings")
        await execute("DELETE FROM memos")

    import asyncio

    asyncio.run(_reset())

    # Create memo
    memo_resp = client.post(
        "/api/v1/memos",
        json={"content": "embedding note", "visibility": "PUBLIC", "tags": ["ai", "daily"]},
    )
    assert memo_resp.status_code == 200
    memo_id = memo_resp.json()["id"]

    # Create embedding
    emb_resp = client.post(
        "/api/v1/memo-embeddings",
        json={
            "memoId": memo_id,
            "content": "embedding note",
            "tags": ["ai", "daily"],
            "dateKey": "2025-01-20",
            "embedding": [1.0, 0.0, 0.0],
            "model": "stub",
        },
    )
    assert emb_resp.status_code == 200

    # Search embedding
    search_resp = client.post(
        "/api/v1/memo-embeddings/search",
        json={"queryEmbedding": [1.0, 0.0, 0.0], "topK": 3},
    )
    assert search_resp.status_code == 200
    results = search_resp.json()
    assert isinstance(results, list)
    assert len(results) >= 1
