"""
Comprehensive API test suite with proper authentication handling.
"""

import json
import time
from loguru import logger


class TestComprehensiveAPIs:
    """Comprehensive API test suite using Flask test client."""

    def test_auth_apis(self, authenticated_client):
        """Test authentication APIs."""
        logger.info("Testing Authentication APIs")

        # Check auth status
        response = authenticated_client.get("/auth/check")
        assert response.status_code == 200
        data = json.loads(response.data)
        assert data["authenticated"] is True

        # Test integrity check
        response = authenticated_client.get("/auth/integrity-check")
        assert response.status_code == 200
        data = json.loads(response.data)
        assert "integrity" in data

        logger.info("✅ Auth APIs tested")

    def test_settings_apis(self, authenticated_client):
        """Test settings APIs."""
        logger.info("Testing Settings APIs")

        # Get all settings
        response = authenticated_client.get("/settings/api")
        assert response.status_code == 200
        data = json.loads(response.data)
        assert data["status"] == "success"
        assert "settings" in data

        # Get categories
        response = authenticated_client.get("/settings/api/categories")
        assert response.status_code == 200
        data = json.loads(response.data)
        assert "categories" in data

        # Get types
        response = authenticated_client.get("/settings/api/types")
        assert response.status_code == 200
        data = json.loads(response.data)
        assert "types" in data

        # Get available models
        print("\n[DEBUG] Testing /settings/api/available-models")
        response = authenticated_client.get("/settings/api/available-models")
        print(f"[DEBUG] Response status: {response.status_code}")
        assert response.status_code == 200
        data = json.loads(response.data)
        print(f"[DEBUG] Response keys: {list(data.keys())}")
        # The endpoint returns provider_options and providers, not models
        assert "provider_options" in data
        assert "providers" in data

        # Get available search engines
        response = authenticated_client.get(
            "/settings/api/available-search-engines"
        )
        assert response.status_code == 200
        data = json.loads(response.data)
        assert "engines" in data or "engine_options" in data

        # Test setting CRUD
        test_key = "test.setting"
        test_value = {"value": "test_value_123"}

        # Create/Update setting
        response = authenticated_client.put(
            f"/settings/api/{test_key}",
            json=test_value,
            content_type="application/json",
        )
        assert response.status_code in [200, 201]

        # Get the setting
        response = authenticated_client.get(f"/settings/api/{test_key}")
        # Setting might have been created or might not exist
        assert response.status_code in [200, 404]

        # Delete the setting
        response = authenticated_client.delete(f"/settings/api/{test_key}")
        assert response.status_code in [200, 204, 404]

        logger.info("✅ Settings APIs tested")

    def test_research_apis(self, authenticated_client):
        """Test research APIs."""
        logger.info("Testing Research APIs")

        # Get research history (endpoint is /api/history not /research/api/history)
        response = authenticated_client.get("/api/history")
        assert response.status_code == 200
        data = json.loads(response.data)
        assert "history" in data or "items" in data

        # Start a test research
        research_data = {
            "query": "Test research from comprehensive API test",
            "mode": "quick",
            "model_provider": "OLLAMA",
            "model": "llama2",
            "search_engine": "searxng",
            "max_results": 5,
            "iterations": 1,
            "questions_per_iteration": 2,
        }

        response = authenticated_client.post(
            "/api/start_research",
            json=research_data,
            content_type="application/json",
        )

        if response.status_code == 200:
            data = json.loads(response.data)
            assert "research_id" in data
            research_id = data["research_id"]

            # Give it a moment to start
            time.sleep(0.5)

            # Check status
            response = authenticated_client.get(
                f"/api/research/{research_id}/status"
            )
            assert response.status_code == 200

            # Terminate research
            response = authenticated_client.post(
                f"/api/terminate/{research_id}"
            )
            assert response.status_code in [200, 404]

        logger.info("✅ Research APIs tested")

    def test_metrics_apis(self, authenticated_client):
        """Test metrics APIs."""
        logger.info("Testing Metrics APIs")

        # Get metrics summary
        response = authenticated_client.get("/metrics/api/metrics")
        assert response.status_code == 200
        data = json.loads(response.data)
        # The endpoint returns 'metrics' not 'summary'
        assert "metrics" in data

        # Get enhanced metrics
        response = authenticated_client.get("/metrics/api/metrics/enhanced")
        assert response.status_code == 200

        # Get pricing info
        response = authenticated_client.get("/metrics/api/pricing")
        assert response.status_code == 200
        data = json.loads(response.data)
        # The endpoint returns 'pricing' not 'models'
        assert "pricing" in data

        # Get cost analytics
        response = authenticated_client.get("/metrics/api/cost-analytics")
        assert response.status_code == 200

        # Test cost calculation
        cost_data = {
            "model_name": "gpt-3.5-turbo",
            "prompt_tokens": 1000,
            "completion_tokens": 500,
        }
        response = authenticated_client.post(
            "/metrics/api/cost-calculation",
            json=cost_data,
            content_type="application/json",
        )
        assert response.status_code == 200

        logger.info("✅ Metrics APIs tested")

    def test_benchmark_apis(self, authenticated_client):
        """Test benchmark APIs."""
        logger.info("Testing Benchmark APIs")

        # Get benchmark history
        response = authenticated_client.get("/benchmark/api/history")
        assert response.status_code == 200
        data = json.loads(response.data)
        # The endpoint returns 'runs' not 'history'
        assert "runs" in data

        # Get saved configs
        response = authenticated_client.get("/benchmark/api/configs")
        assert response.status_code == 200
        data = json.loads(response.data)
        assert "configs" in data

        # Check running benchmark
        response = authenticated_client.get("/benchmark/api/running")
        assert response.status_code == 200
        data = json.loads(response.data)
        # The endpoint might return either is_running or success key
        assert "is_running" in data or "success" in data

        # Validate config
        test_config = {
            "name": "Test Config",
            "queries": ["test query"],
            "models": ["gpt-3.5-turbo"],
            "search_engines": ["searxng"],
        }
        response = authenticated_client.post(
            "/benchmark/api/validate-config",
            json=test_config,
            content_type="application/json",
        )
        assert response.status_code == 200

        logger.info("✅ Benchmark APIs tested")

    def test_history_apis(self, authenticated_client):
        """Test history APIs."""
        logger.info("Testing History APIs")

        response = authenticated_client.get("/history/api")
        assert response.status_code == 200
        data = json.loads(response.data)
        # The endpoint returns 'items' not 'history'
        assert "items" in data
        assert isinstance(data["items"], list)

        logger.info("✅ History APIs tested")

    def test_config_apis(self, authenticated_client):
        """Test configuration APIs."""
        logger.info("Testing Config APIs")

        # Get current config (correct path is /research/api/settings/current-config)
        response = authenticated_client.get(
            "/research/api/settings/current-config"
        )
        assert response.status_code == 200
        data = json.loads(response.data)
        # The response has a 'config' key containing the actual config
        assert "config" in data or ("llm" in data and "search" in data)
        if "config" in data:
            config = data["config"]
            assert "provider" in config or "llm" in config

        # Get public config (correct path is /research/api/config)
        response = authenticated_client.get("/research/api/config")
        assert response.status_code == 200
        data = json.loads(response.data)
        assert "version" in data
        # The endpoint returns basic config, not available_models
        assert "llm_provider" in data or "search_tool" in data

        logger.info("✅ Config APIs tested")

    def test_health_check_apis(self, authenticated_client):
        """Test health check APIs."""
        logger.info("Testing Health Check APIs")

        # Check Ollama status (correct path is /research/api/check/ollama_status)
        response = authenticated_client.get("/research/api/check/ollama_status")
        assert response.status_code == 200
        data = json.loads(response.data)
        # The endpoint returns 'running' not 'available'
        assert "running" in data or "available" in data

        # Check Ollama model (might return 400 if no model specified)
        response = authenticated_client.get("/research/api/check/ollama_model")
        assert response.status_code in [200, 400]

        logger.info("✅ Health Check APIs tested")

    def test_api_v1_endpoints(self, authenticated_client):
        """Test API v1 endpoints."""
        logger.info("Testing API v1 endpoints")

        # Health check
        response = authenticated_client.get("/api/v1/health")
        assert response.status_code == 200
        data = json.loads(response.data)
        assert data["status"] == "ok"

        # API documentation
        response = authenticated_client.get("/api/v1/")
        assert response.status_code == 200
        data = json.loads(response.data)
        assert data["api_version"] == "v1"
        assert "endpoints" in data

        logger.info("✅ API v1 endpoints tested")

    def test_rate_limiting(self, authenticated_client):
        """Test rate limiting functionality."""
        logger.info("Testing Rate Limiting")

        # Get rate limiting status
        response = authenticated_client.get(
            "/settings/api/rate-limiting/status"
        )
        assert response.status_code == 200

        # Get current rate limits
        response = authenticated_client.get(
            "/metrics/api/rate-limiting/current"
        )
        assert response.status_code == 200

        # Test cleanup
        response = authenticated_client.post(
            "/settings/api/rate-limiting/cleanup"
        )
        assert response.status_code == 200

        logger.info("✅ Rate limiting tested")

    def test_data_location_api(self, authenticated_client):
        """Test data location API."""
        logger.info("Testing Data Location API")

        response = authenticated_client.get("/settings/api/data-location")
        assert response.status_code == 200
        data = json.loads(response.data)
        # The endpoint returns 'data_directory' not 'data_dir'
        assert "data_directory" in data
        assert "is_custom" in data

        logger.info("✅ Data location API tested")
