"""Test skeleton codegen for NIKAME.

Generates a tests/ directory with conftest.py, fixtures, and
an example health check test.
"""

from __future__ import annotations


def generate_test_files(
    project_name: str,
    has_postgres: bool,
    has_redis: bool,
    has_auth: bool,
) -> list[tuple[str, str]]:
    """Generate test scaffolding files.

    Args:
        project_name: Name of the project.
        has_postgres: Whether Postgres is active.
        has_redis: Whether Redis/Dragonfly is active.
        has_auth: Whether auth features are enabled.

    Returns:
        List of (relative_path, content) tuples.
    """
    files: list[tuple[str, str]] = []

    files.append(("tests/__init__.py", ""))
    files.append(("tests/conftest.py", _conftest(has_postgres, has_redis)))
    files.append(("tests/test_health.py", _test_health()))

    if has_auth:
        files.append(("tests/test_auth.py", _test_auth()))

    files.append(("pytest.ini", _pytest_ini()))

    return files


def _conftest(has_postgres: bool, has_redis: bool) -> str:
    imports = [
        "import os",
        "import pytest",
        "from httpx import AsyncClient, ASGITransport",
    ]

    fixtures = []

    # Base app fixture
    fixtures.append('''
@pytest.fixture(scope="session")
def anyio_backend():
    return "asyncio"


@pytest.fixture
async def client():
    """Async test client for the FastAPI application."""
    from app.main import app

    transport = ASGITransport(app=app)
    async with AsyncClient(transport=transport, base_url="http://test") as ac:
        yield ac
''')

    if has_postgres:
        imports.append("from sqlalchemy.ext.asyncio import create_async_engine, AsyncSession")
        imports.append("from sqlalchemy.orm import sessionmaker")
        fixtures.append('''
@pytest.fixture
async def db_session():
    """Create a test database session.

    Override the app's database dependency with a test database.
    Set TEST_DATABASE_URL in your environment or .env.test file.
    """
    test_db_url = os.environ.get(
        "TEST_DATABASE_URL",
        "postgresql+asyncpg://postgres:postgres@localhost:5432/test_db"
    )
    engine = create_async_engine(test_db_url, echo=False)
    async_session = sessionmaker(engine, class_=AsyncSession, expire_on_commit=False)

    async with async_session() as session:
        yield session

    await engine.dispose()
''')

    if has_redis:
        imports.append("import redis.asyncio as aioredis")
        fixtures.append('''
@pytest.fixture
async def redis_client():
    """Create a test Redis client."""
    test_redis_url = os.environ.get("TEST_REDIS_URL", "redis://localhost:6379/1")
    client = aioredis.from_url(test_redis_url)
    yield client
    await client.aclose()
''')

    return "\n".join(imports) + "\n" + "\n".join(fixtures)


def _test_health() -> str:
    return '''"""Health endpoint tests — Auto-generated by NIKAME."""

import pytest


@pytest.mark.anyio
async def test_health_endpoint(client):
    """Verify the health endpoint returns 200 OK."""
    response = await client.get("/health")
    assert response.status_code == 200
    data = response.json()
    assert data["status"] == "ok" or "status" in data


@pytest.mark.anyio
async def test_root_endpoint(client):
    """Verify the root endpoint is reachable."""
    response = await client.get("/")
    assert response.status_code in (200, 404, 307)
'''


def _test_auth() -> str:
    return '''"""Auth endpoint tests — Auto-generated by NIKAME."""

import pytest


@pytest.mark.anyio
async def test_register_user(client):
    """Test user registration."""
    response = await client.post("/api/auth/register", json={
        "email": "test@example.com",
        "password": "SecurePassword123!"
    })
    # Should succeed or return validation error
    assert response.status_code in (200, 201, 422)


@pytest.mark.anyio
async def test_login_invalid_credentials(client):
    """Test login with invalid credentials returns 401."""
    response = await client.post("/api/auth/login", json={
        "email": "nonexistent@example.com",
        "password": "wrong"
    })
    assert response.status_code in (401, 404, 422)
'''


def _pytest_ini() -> str:
    return """[pytest]
asyncio_mode = auto
testpaths = tests
addopts = -v --tb=short -x
markers =
    slow: marks tests as slow (deselect with '-m "not slow"')
    integration: marks tests requiring running infrastructure
"""
