"""
Test Suite for Opora Vie - Admin Backoffice & Enhanced Practitioner Features
Testing: 
- Admin-only routes (/admin/*) 
- Practitioner new fields (years_experience, diplomas, languages, detailed_description)
- Admin authentication (admin@soins-match.fr)
"""

import pytest
import requests
import os
import uuid

BASE_URL = os.environ.get('REACT_APP_BACKEND_URL', 'https://soins-match.preview.emergentagent.com').rstrip('/')

# Test credentials
ADMIN_EMAIL = "admin@soins-match.fr"
ADMIN_PASSWORD = "admin123"
TEST_PRACTITIONER_EMAIL = f"test_practitioner_{uuid.uuid4().hex[:8]}@test.com"
TEST_CLIENT_EMAIL = f"test_client_{uuid.uuid4().hex[:8]}@test.com"
TEST_PASSWORD = "testpass123"


class TestAuthAndAdminAccess:
    """Test authentication and admin access controls"""
    
    @pytest.fixture(scope="class")
    def admin_token(self):
        """Get admin auth token"""
        # First, try to register admin if doesn't exist
        register_response = requests.post(f"{BASE_URL}/api/auth/register", json={
            "email": ADMIN_EMAIL,
            "password": ADMIN_PASSWORD,
            "first_name": "Admin",
            "last_name": "User",
            "role": "client"
        })
        
        # Then login
        login_response = requests.post(f"{BASE_URL}/api/auth/login", json={
            "email": ADMIN_EMAIL,
            "password": ADMIN_PASSWORD
        })
        
        if login_response.status_code == 200:
            return login_response.json()["access_token"]
        pytest.skip("Admin login failed")
    
    @pytest.fixture(scope="class")
    def client_token(self):
        """Get regular client auth token"""
        # Register a test client
        register_response = requests.post(f"{BASE_URL}/api/auth/register", json={
            "email": TEST_CLIENT_EMAIL,
            "password": TEST_PASSWORD,
            "first_name": "Test",
            "last_name": "Client",
            "role": "client"
        })
        
        if register_response.status_code in [200, 400]:
            # Login
            login_response = requests.post(f"{BASE_URL}/api/auth/login", json={
                "email": TEST_CLIENT_EMAIL,
                "password": TEST_PASSWORD
            })
            if login_response.status_code == 200:
                return login_response.json()["access_token"]
        pytest.skip("Client registration/login failed")
    
    @pytest.fixture(scope="class")
    def practitioner_token(self):
        """Get practitioner auth token"""
        # Register a test practitioner
        register_response = requests.post(f"{BASE_URL}/api/auth/register", json={
            "email": TEST_PRACTITIONER_EMAIL,
            "password": TEST_PASSWORD,
            "first_name": "Test",
            "last_name": "Practitioner",
            "role": "practitioner"
        })
        
        if register_response.status_code in [200, 400]:
            # Login
            login_response = requests.post(f"{BASE_URL}/api/auth/login", json={
                "email": TEST_PRACTITIONER_EMAIL,
                "password": TEST_PASSWORD
            })
            if login_response.status_code == 200:
                return login_response.json()["access_token"]
        pytest.skip("Practitioner registration/login failed")
    
    def test_admin_login_returns_is_admin_true(self, admin_token):
        """Test that admin user has is_admin=true in response"""
        response = requests.get(
            f"{BASE_URL}/api/auth/me",
            headers={"Authorization": f"Bearer {admin_token}"}
        )
        assert response.status_code == 200
        data = response.json()
        assert data["is_admin"] == True, "Admin user should have is_admin=True"
        print(f"✓ Admin user has is_admin=True")
    
    def test_regular_client_has_is_admin_false(self, client_token):
        """Test that regular client has is_admin=false"""
        response = requests.get(
            f"{BASE_URL}/api/auth/me",
            headers={"Authorization": f"Bearer {client_token}"}
        )
        assert response.status_code == 200
        data = response.json()
        assert data.get("is_admin", False) == False, "Regular client should not be admin"
        print(f"✓ Regular client has is_admin=False")
    
    def test_admin_practitioners_endpoint_accessible_by_admin(self, admin_token):
        """Test /admin/practitioners endpoint is accessible by admin"""
        response = requests.get(
            f"{BASE_URL}/api/admin/practitioners",
            headers={"Authorization": f"Bearer {admin_token}"}
        )
        assert response.status_code == 200
        assert isinstance(response.json(), list)
        print(f"✓ Admin can access /admin/practitioners")
    
    def test_admin_stats_endpoint_accessible_by_admin(self, admin_token):
        """Test /admin/stats/overview endpoint is accessible by admin"""
        response = requests.get(
            f"{BASE_URL}/api/admin/stats/overview",
            headers={"Authorization": f"Bearer {admin_token}"}
        )
        assert response.status_code == 200
        data = response.json()
        assert "practitioners" in data
        assert "clients" in data
        assert "appointments" in data
        assert "revenue" in data
        print(f"✓ Admin can access /admin/stats/overview - {data}")
    
    def test_admin_practitioners_endpoint_blocked_for_client(self, client_token):
        """Test /admin/practitioners endpoint is blocked for regular client"""
        response = requests.get(
            f"{BASE_URL}/api/admin/practitioners",
            headers={"Authorization": f"Bearer {client_token}"}
        )
        assert response.status_code == 403
        print(f"✓ Client blocked from /admin/practitioners (403)")
    
    def test_admin_stats_endpoint_blocked_for_client(self, client_token):
        """Test /admin/stats/overview endpoint is blocked for regular client"""
        response = requests.get(
            f"{BASE_URL}/api/admin/stats/overview",
            headers={"Authorization": f"Bearer {client_token}"}
        )
        assert response.status_code == 403
        print(f"✓ Client blocked from /admin/stats/overview (403)")


class TestEnhancedPractitionerFields:
    """Test new practitioner fields: years_experience, diplomas, languages, detailed_description"""
    
    @pytest.fixture(scope="class")
    def practitioner_token(self):
        """Get practitioner auth token"""
        test_email = f"test_enhanced_pract_{uuid.uuid4().hex[:8]}@test.com"
        register_response = requests.post(f"{BASE_URL}/api/auth/register", json={
            "email": test_email,
            "password": TEST_PASSWORD,
            "first_name": "Enhanced",
            "last_name": "Practitioner",
            "role": "practitioner"
        })
        
        if register_response.status_code in [200, 400]:
            login_response = requests.post(f"{BASE_URL}/api/auth/login", json={
                "email": test_email,
                "password": TEST_PASSWORD
            })
            if login_response.status_code == 200:
                return login_response.json()["access_token"]
        pytest.skip("Practitioner registration/login failed")
    
    def test_create_practitioner_with_enhanced_fields(self, practitioner_token):
        """Test creating practitioner profile with all new fields"""
        profile_data = {
            "specialty": "naturopathe",
            "bio": "Short bio for testing",
            "detailed_description": "This is a detailed description about my practice, philosophy, and methods. I believe in holistic health approaches.",
            "years_experience": 8,
            "diplomas": ["Diplôme de Naturopathie CENATHO", "Formation en Aromathérapie"],
            "languages": ["fr", "en", "it"],
            "city": "Paris",
            "country": "FR",
            "region": "IDF",
            "consultation_types": ["cabinet", "visio"],
            "price": 75,
            "consultation_duration": 60
        }
        
        response = requests.post(
            f"{BASE_URL}/api/practitioners",
            json=profile_data,
            headers={"Authorization": f"Bearer {practitioner_token}"}
        )
        
        if response.status_code == 400 and "déjà existant" in response.text:
            # Profile already exists, let's update it instead
            response = requests.put(
                f"{BASE_URL}/api/practitioners/me",
                json=profile_data,
                headers={"Authorization": f"Bearer {practitioner_token}"}
            )
        
        assert response.status_code == 200, f"Failed to create/update profile: {response.text}"
        data = response.json()
        
        # Verify new fields
        assert data.get("years_experience") == 8
        assert data.get("diplomas") == ["Diplôme de Naturopathie CENATHO", "Formation en Aromathérapie"]
        assert data.get("languages") == ["fr", "en", "it"]
        assert data.get("detailed_description") == profile_data["detailed_description"]
        print(f"✓ Practitioner created with enhanced fields")
    
    def test_get_practitioner_profile_includes_enhanced_fields(self, practitioner_token):
        """Test getting practitioner profile returns new fields"""
        response = requests.get(
            f"{BASE_URL}/api/practitioners/me/profile",
            headers={"Authorization": f"Bearer {practitioner_token}"}
        )
        
        assert response.status_code == 200
        data = response.json()
        
        # Check that the new fields are present
        assert "years_experience" in data
        assert "diplomas" in data
        assert "languages" in data
        assert "detailed_description" in data
        print(f"✓ Profile GET includes enhanced fields: years_exp={data.get('years_experience')}, languages={data.get('languages')}")
    
    def test_update_practitioner_enhanced_fields(self, practitioner_token):
        """Test updating only the new fields"""
        update_data = {
            "years_experience": 10,
            "diplomas": ["Updated Diploma 1", "Updated Diploma 2", "New Certification"],
            "languages": ["fr", "en", "ru", "ro"],
            "detailed_description": "Updated detailed description with new philosophy."
        }
        
        response = requests.put(
            f"{BASE_URL}/api/practitioners/me",
            json=update_data,
            headers={"Authorization": f"Bearer {practitioner_token}"}
        )
        
        assert response.status_code == 200
        data = response.json()
        
        assert data.get("years_experience") == 10
        assert len(data.get("diplomas", [])) == 3
        assert "ru" in data.get("languages", [])
        assert "ro" in data.get("languages", [])
        print(f"✓ Practitioner enhanced fields updated successfully")


class TestPublicPractitionerProfile:
    """Test public practitioner profile displays enhanced fields"""
    
    def test_public_practitioner_list_includes_enhanced_fields(self):
        """Test that GET /practitioners returns enhanced fields"""
        response = requests.get(f"{BASE_URL}/api/practitioners")
        assert response.status_code == 200
        
        practitioners = response.json()
        if len(practitioners) > 0:
            practitioner = practitioners[0]
            # These fields should be available (even if None)
            expected_fields = ["years_experience", "diplomas", "languages", "detailed_description"]
            for field in expected_fields:
                assert field in practitioner or practitioner.get(field) is None, f"Field {field} missing"
            print(f"✓ Public practitioner list includes enhanced fields")
        else:
            print("ℹ No practitioners found to verify enhanced fields")
    
    def test_public_practitioner_detail_includes_enhanced_fields(self):
        """Test that GET /practitioners/{id} returns enhanced fields"""
        # First get a practitioner ID
        list_response = requests.get(f"{BASE_URL}/api/practitioners")
        assert list_response.status_code == 200
        
        practitioners = list_response.json()
        if len(practitioners) > 0:
            practitioner_id = practitioners[0]["id"]
            
            detail_response = requests.get(f"{BASE_URL}/api/practitioners/{practitioner_id}")
            assert detail_response.status_code == 200
            
            data = detail_response.json()
            expected_fields = ["years_experience", "diplomas", "languages", "detailed_description"]
            for field in expected_fields:
                assert field in data, f"Field {field} missing in detail response"
            print(f"✓ Public practitioner detail includes enhanced fields")
        else:
            print("ℹ No practitioners found to test detail view")


class TestAdminReports:
    """Test admin report generation functionality"""
    
    @pytest.fixture(scope="class")
    def admin_token(self):
        """Get admin auth token"""
        # Try to register admin first (will fail if exists)
        requests.post(f"{BASE_URL}/api/auth/register", json={
            "email": ADMIN_EMAIL,
            "password": ADMIN_PASSWORD,
            "first_name": "Admin",
            "last_name": "User",
            "role": "client"
        })
        
        # Login
        login_response = requests.post(f"{BASE_URL}/api/auth/login", json={
            "email": ADMIN_EMAIL,
            "password": ADMIN_PASSWORD
        })
        
        if login_response.status_code == 200:
            return login_response.json()["access_token"]
        pytest.skip("Admin login failed")
    
    def test_admin_can_get_practitioner_report(self, admin_token):
        """Test admin can generate report for a practitioner"""
        # First get a practitioner ID
        practitioners_response = requests.get(
            f"{BASE_URL}/api/admin/practitioners",
            headers={"Authorization": f"Bearer {admin_token}"}
        )
        
        if practitioners_response.status_code == 200 and len(practitioners_response.json()) > 0:
            practitioner_id = practitioners_response.json()[0]["id"]
            
            report_response = requests.get(
                f"{BASE_URL}/api/admin/practitioner/{practitioner_id}/report?month=1&year=2026",
                headers={"Authorization": f"Bearer {admin_token}"}
            )
            
            assert report_response.status_code == 200
            data = report_response.json()
            
            # Verify report structure
            assert "practitioner" in data
            assert "period" in data
            assert "consultations" in data
            assert "revenue" in data
            assert "appointments" in data
            
            # Verify period
            assert data["period"]["month"] == 1
            assert data["period"]["year"] == 2026
            assert data["period"]["month_name"] == "Janvier"
            
            print(f"✓ Admin can generate practitioner report: {data['practitioner']['name']}, consultations: {data['consultations']['total']}")
        else:
            print("ℹ No practitioners found to generate report")


class TestLanguageSupport:
    """Test that translations are available for all 5 languages"""
    
    def test_specialties_endpoint_works(self):
        """Test that specialties endpoint returns data"""
        response = requests.get(f"{BASE_URL}/api/specialties")
        assert response.status_code == 200
        
        specialties = response.json()
        assert len(specialties) == 5
        
        expected = ["naturopathe", "sophrologue", "psychologue", "osteopathe", "hypnotherapeute"]
        actual_ids = [s["id"] for s in specialties]
        for exp in expected:
            assert exp in actual_ids, f"Missing specialty: {exp}"
        
        print(f"✓ All 5 specialties available: {actual_ids}")


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