"""
Basic tests for MEDUSA REST API

Tests API endpoints, license validation, and authentication.
"""

import pytest
import json
from pathlib import Path
from datetime import datetime, timedelta
from unittest.mock import Mock, patch

# Try to import API components (fastapi is optional - paid tier only)
try:
    from fastapi.testclient import TestClient
    from medusa.api.main import app
    from medusa.api.models import ScanRequest, ScanStatus
    from medusa.core.licensing import LicenseManager, LicenseInfo, LicenseTier
    API_AVAILABLE = True
except ImportError:
    API_AVAILABLE = False
    pytestmark = pytest.mark.skip(reason="API dependencies not installed. Install with: pip install -e '.[api]'")


class TestAPIHealth:
    """Test health and license endpoints (no auth required)"""

    def test_health_endpoint(self):
        """Test health check endpoint"""
        client = TestClient(app)
        response = client.get("/api/v1/health")

        assert response.status_code == 200
        data = response.json()
        assert data["status"] == "healthy"
        assert "version" in data
        assert "license_tier" in data
        assert "timestamp" in data

    def test_license_endpoint(self):
        """Test license information endpoint"""
        client = TestClient(app)
        response = client.get("/api/v1/license")

        assert response.status_code == 200
        data = response.json()
        assert "tier" in data
        assert "is_valid" in data
        assert "api_access" in data
        assert "features" in data

    def test_root_endpoint(self):
        """Test API root endpoint"""
        client = TestClient(app)
        response = client.get("/")

        assert response.status_code == 200
        data = response.json()
        assert data["name"] == "MEDUSA Security Scanner API"
        assert "version" in data


class TestAPIAuthentication:
    """Test API authentication and license validation"""

    def test_scan_without_license(self):
        """Test that scan endpoint requires license"""
        client = TestClient(app)

        # Mock free tier license
        with patch('medusa.api.auth.get_license_manager') as mock_manager:
            mock_license = Mock()
            mock_license.is_valid = True
            mock_license.api_access = False
            mock_license.tier = LicenseTier.FREE

            mock_mgr = Mock()
            mock_mgr.get_license.return_value = mock_license
            mock_mgr.has_feature.return_value = False
            mock_manager.return_value = mock_mgr

            response = client.post(
                "/api/v1/scan",
                json={
                    "target": "/tmp/test",
                    "fail_on": "high"
                }
            )

            assert response.status_code == 402
            assert "Professional or Enterprise" in response.json()["error"]

    def test_scan_with_professional_license(self):
        """Test scan endpoint with Professional license"""
        client = TestClient(app)

        # Mock Professional license
        with patch('medusa.api.auth.get_license_manager') as mock_manager:
            mock_license = LicenseInfo(
                tier=LicenseTier.PROFESSIONAL,
                email="test@example.com",
                expires_at=datetime.now() + timedelta(days=365),
                api_access=True,
            )

            mock_mgr = Mock()
            mock_mgr.get_license.return_value = mock_license
            mock_mgr.has_feature.return_value = True
            mock_manager.return_value = mock_mgr

            # Create temp directory for testing
            import tempfile
            with tempfile.TemporaryDirectory() as tmpdir:
                response = client.post(
                    "/api/v1/scan",
                    json={
                        "target": tmpdir,
                        "fail_on": "high"
                    }
                )

                assert response.status_code == 202
                data = response.json()
                assert "scan_id" in data
                assert data["status"] == "pending"


class TestScanEndpoints:
    """Test scan creation and status endpoints"""

    @patch('medusa.api.main.verify_api_access')
    def test_create_scan_invalid_path(self, mock_verify):
        """Test scan creation with invalid target path"""
        # Mock Professional license
        mock_verify.return_value = LicenseInfo(
            tier=LicenseTier.PROFESSIONAL,
            api_access=True,
        )

        client = TestClient(app)
        response = client.post(
            "/api/v1/scan",
            json={
                "target": "/nonexistent/path",
                "fail_on": "high"
            }
        )

        assert response.status_code == 400
        assert "does not exist" in response.json()["error"]

    @patch('medusa.api.main.verify_api_access')
    def test_get_scan_not_found(self, mock_verify):
        """Test getting scan status for non-existent scan"""
        # Mock Professional license
        mock_verify.return_value = LicenseInfo(
            tier=LicenseTier.PROFESSIONAL,
            api_access=True,
        )

        client = TestClient(app)
        response = client.get("/api/v1/scan/nonexistent_scan_id")

        assert response.status_code == 404
        assert "not found" in response.json()["error"]


class TestAPIModels:
    """Test Pydantic models"""

    def test_scan_request_model(self):
        """Test ScanRequest model validation"""
        from medusa.api.models import ScanRequest

        # Valid request
        request = ScanRequest(
            target="/tmp/test",
            fail_on="high",
            output_format="json"
        )
        assert request.target == "/tmp/test"
        assert request.fail_on == "high"

        # Test default values
        assert request.scanners is None
        assert request.exclude_paths is None

    def test_scan_response_model(self):
        """Test ScanResponse model"""
        from medusa.api.models import ScanResponse, ScanStatus

        response = ScanResponse(
            scan_id="test_123",
            status=ScanStatus.PENDING,
            message="Test message",
            target="/tmp/test"
        )
        assert response.scan_id == "test_123"
        assert response.status == ScanStatus.PENDING


if __name__ == "__main__":
    pytest.main([__file__, "-v"])
