"""
Integration tests for database and cache connectivity.

These tests verify that the CI pipeline can connect to:
- PostgreSQL database
- Valkey/Redis cache

Run with: pytest tests/test_integration/test_db_connection.py -v
"""

import os
import pytest


@pytest.mark.integration
def test_database_connection():
    """Test that we can connect to PostgreSQL."""
    import psycopg2

    db_url = os.environ.get("DATABASE_URL")
    assert db_url is not None, "DATABASE_URL not set"

    # Parse connection parameters from URL
    # Format: postgresql://user:password@host:port/dbname
    conn = psycopg2.connect(db_url)
    try:
        cur = conn.cursor()
        cur.execute("SELECT 1")
        result = cur.fetchone()
        assert result[0] == 1, "Database query returned unexpected result"

        # Test database version
        cur.execute("SELECT version()")
        version = cur.fetchone()[0]
        assert "PostgreSQL" in version, f"Unexpected database: {version}"
        print(f"Connected to: {version.split(',')[0]}")

    finally:
        conn.close()


@pytest.mark.integration
def test_database_can_create_table():
    """Test that we can create and drop tables."""
    import psycopg2

    db_url = os.environ.get("DATABASE_URL")
    assert db_url is not None, "DATABASE_URL not set"

    conn = psycopg2.connect(db_url)
    conn.autocommit = True
    try:
        cur = conn.cursor()

        # Create test table
        cur.execute("""
            CREATE TABLE IF NOT EXISTS _ci_test_table (
                id SERIAL PRIMARY KEY,
                name VARCHAR(100),
                created_at TIMESTAMP DEFAULT NOW()
            )
        """)

        # Insert test data
        cur.execute(
            "INSERT INTO _ci_test_table (name) VALUES (%s) RETURNING id",
            ("integration_test",)
        )
        inserted_id = cur.fetchone()[0]
        assert inserted_id is not None, "Insert failed"

        # Read back
        cur.execute("SELECT name FROM _ci_test_table WHERE id = %s", (inserted_id,))
        name = cur.fetchone()[0]
        assert name == "integration_test", f"Read back failed: {name}"

        # Cleanup
        cur.execute("DROP TABLE IF EXISTS _ci_test_table")

    finally:
        conn.close()


@pytest.mark.integration
def test_valkey_connection():
    """Test that we can connect to Valkey/Redis."""
    import redis

    valkey_url = os.environ.get("VALKEY_URL") or os.environ.get("REDIS_URL")
    assert valkey_url is not None, "VALKEY_URL or REDIS_URL not set"

    r = redis.from_url(valkey_url)
    try:
        # Test ping
        assert r.ping() is True, "Valkey ping failed"

        # Test set/get
        test_key = "_ci_test_key"
        test_value = "integration_test_value"

        r.set(test_key, test_value)
        result = r.get(test_key)
        assert result == test_value.encode(), f"Get returned: {result}"

        # Cleanup
        r.delete(test_key)
        assert r.get(test_key) is None, "Delete failed"

        # Get server info
        info = r.info("server")
        server_version = info.get("redis_version", "unknown")
        print(f"Connected to Valkey/Redis version: {server_version}")

    finally:
        r.close()


@pytest.mark.integration
def test_valkey_can_store_json():
    """Test that Valkey can store and retrieve JSON data."""
    import redis
    import json

    valkey_url = os.environ.get("VALKEY_URL") or os.environ.get("REDIS_URL")
    assert valkey_url is not None, "VALKEY_URL or REDIS_URL not set"

    r = redis.from_url(valkey_url)
    try:
        test_key = "_ci_test_json"
        test_data = {
            "user_id": "test-123",
            "session": {"active": True, "created": "2025-01-01"},
            "scores": [85, 90, 78]
        }

        # Store as JSON
        r.set(test_key, json.dumps(test_data))

        # Retrieve and parse
        result = r.get(test_key)
        parsed = json.loads(result)

        assert parsed["user_id"] == "test-123"
        assert parsed["session"]["active"] is True
        assert parsed["scores"] == [85, 90, 78]

        # Cleanup
        r.delete(test_key)

    finally:
        r.close()


@pytest.mark.integration
def test_valkey_expiration():
    """Test that Valkey TTL/expiration works."""
    import redis
    import time

    valkey_url = os.environ.get("VALKEY_URL") or os.environ.get("REDIS_URL")
    assert valkey_url is not None, "VALKEY_URL or REDIS_URL not set"

    r = redis.from_url(valkey_url)
    try:
        test_key = "_ci_test_expiry"

        # Set with 2 second TTL
        r.setex(test_key, 2, "temporary_value")

        # Should exist immediately
        assert r.get(test_key) is not None, "Key should exist"

        # Check TTL
        ttl = r.ttl(test_key)
        assert 0 < ttl <= 2, f"TTL should be 1-2, got {ttl}"

        # Wait for expiration
        time.sleep(3)

        # Should be gone
        assert r.get(test_key) is None, "Key should have expired"

    finally:
        # Cleanup (in case test failed before expiration)
        r.delete(test_key)
        r.close()
