"""
API Integration Tests
Tests all API endpoints without triggering AI generation.
"""
import pytest
import httpx
from datetime import datetime


class TestAPI:
    """API endpoint tests."""
    
    base_url = "http://localhost:8000"
    token = None
    user_id = None
    project_id = None
    api_key_id = None
    
    @pytest.fixture(scope="class", autouse=True)
    async def setup_class(self):
        """Set up test class."""
        # Login as admin to get token
        async with httpx.AsyncClient() as client:
            response = await client.post(
                f"{self.base_url}/auth/login",
                params={"username": "admin", "password": "admin123"}
            )
            if response.status_code == 200:
                TestAPI.token = response.json()["access_token"]
    
    @pytest.mark.asyncio
    async def test_health_check(self):
        """Test health endpoint."""
        async with httpx.AsyncClient() as client:
            response = await client.get(f"{self.base_url}/health")
            
        assert response.status_code == 200
        data = response.json()
        assert data["status"] == "healthy"
        assert data["service"] == "gateway"
    
    @pytest.mark.asyncio
    async def test_register_user(self):
        """Test user registration."""
        async with httpx.AsyncClient() as client:
            response = await client.post(
                f"{self.base_url}/auth/register",
                json={
                    "username": f"testuser_{datetime.utcnow().timestamp()}",
                    "email": f"test_{datetime.utcnow().timestamp()}@example.com",
                    "password": "password123"
                }
            )
            
        assert response.status_code == 201
        data = response.json()
        assert "id" in data
        assert "email" in data
        TestAPI.user_id = data["id"]
    
    @pytest.mark.asyncio
    async def test_login(self):
        """Test user login."""
        async with httpx.AsyncClient() as client:
            response = await client.post(
                f"{self.base_url}/auth/login",
                params={"username": "admin", "password": "admin123"}
            )
            
        assert response.status_code == 200
        data = response.json()
        assert "access_token" in data
        assert data["token_type"] == "bearer"
    
    @pytest.mark.asyncio
    async def test_get_current_user(self):
        """Test getting current user info."""
        headers = {"Authorization": f"Bearer {self.token}"}
        
        async with httpx.AsyncClient() as client:
            response = await client.get(
                f"{self.base_url}/auth/me",
                headers=headers
            )
            
        assert response.status_code == 200
        data = response.json()
        assert "username" in data
        assert "email" in data
    
    @pytest.mark.asyncio
    async def test_create_project(self):
        """Test project creation (without triggering AI)."""
        headers = {"Authorization": f"Bearer {self.token}"}
        
        async with httpx.AsyncClient() as client:
            response = await client.post(
                f"{self.base_url}/projects",
                headers=headers,
                json={
                    "name": "Test Project",
                    "prompt": "Test prompt",
                    "audio_settings": None,  # Don't trigger audio generation
                    "video_settings": None   # Don't trigger video generation
                }
            )
            
        assert response.status_code == 201
        data = response.json()
        assert "id" in data
        assert data["name"] == "Test Project"
        assert data["status"] == "pending"
        TestAPI.project_id = data["id"]
    
    @pytest.mark.asyncio
    async def test_list_projects(self):
        """Test listing projects."""
        headers = {"Authorization": f"Bearer {self.token}"}
        
        async with httpx.AsyncClient() as client:
            response = await client.get(
                f"{self.base_url}/projects",
                headers=headers,
                params={"skip": 0, "limit": 10}
            )
            
        assert response.status_code == 200
        data = response.json()
        assert isinstance(data, list)
    
    @pytest.mark.asyncio
    async def test_get_project(self):
        """Test getting single project."""
        headers = {"Authorization": f"Bearer {self.token}"}
        
        async with httpx.AsyncClient() as client:
            response = await client.get(
                f"{self.base_url}/projects/{self.project_id}",
                headers=headers
            )
            
        assert response.status_code == 200
        data = response.json()
        assert data["id"] == self.project_id
    
    @pytest.mark.asyncio
    async def test_update_project(self):
        """Test updating project."""
        headers = {"Authorization": f"Bearer {self.token}"}
        
        async with httpx.AsyncClient() as client:
            response = await client.patch(
                f"{self.base_url}/projects/{self.project_id}",
                headers=headers,
                json={"name": "Updated Project Name"}
            )
            
        assert response.status_code == 200
        data = response.json()
        assert data["name"] == "Updated Project Name"
    
    @pytest.mark.asyncio
    async def test_create_api_key(self):
        """Test API key creation."""
        headers = {"Authorization": f"Bearer {self.token}"}
        
        async with httpx.AsyncClient() as client:
            response = await client.post(
                f"{self.base_url}/api-keys",
                headers=headers,
                params={"name": "Test API Key"}
            )
            
        assert response.status_code == 201
        data = response.json()
        assert "id" in data
        assert "key" in data  # Only returned on creation
        TestAPI.api_key_id = data["id"]
    
    @pytest.mark.asyncio
    async def test_list_api_keys(self):
        """Test listing API keys."""
        headers = {"Authorization": f"Bearer {self.token}"}
        
        async with httpx.AsyncClient() as client:
            response = await client.get(
                f"{self.base_url}/api-keys",
                headers=headers
            )
            
        assert response.status_code == 200
        data = response.json()
        assert isinstance(data, list)
    
    @pytest.mark.asyncio
    async def test_admin_list_users(self):
        """Test admin endpoint for listing users."""
        headers = {"Authorization": f"Bearer {self.token}"}
        
        async with httpx.AsyncClient() as client:
            response = await client.get(
                f"{self.base_url}/admin/users",
                headers=headers
            )
            
        assert response.status_code == 200
        data = response.json()
        assert isinstance(data, list)
    
    @pytest.mark.asyncio
    async def test_admin_stats(self):
        """Test admin stats endpoint."""
        headers = {"Authorization": f"Bearer {self.token}"}
        
        async with httpx.AsyncClient() as client:
            response = await client.get(
                f"{self.base_url}/admin/stats",
                headers=headers
            )
            
        assert response.status_code == 200
        data = response.json()
        assert "total_users" in data
        assert "total_projects" in data
    
    @pytest.mark.asyncio
    async def test_delete_api_key(self):
        """Test API key deletion."""
        headers = {"Authorization": f"Bearer {self.token}"}
        
        async with httpx.AsyncClient() as client:
            response = await client.delete(
                f"{self.base_url}/api-keys/{self.api_key_id}",
                headers=headers
            )
            
        assert response.status_code == 200
    
    @pytest.mark.asyncio
    async def test_delete_project(self):
        """Test project deletion."""
        headers = {"Authorization": f"Bearer {self.token}"}
        
        async with httpx.AsyncClient() as client:
            response = await client.delete(
                f"{self.base_url}/projects/{self.project_id}",
                headers=headers
            )
            
        assert response.status_code == 200
