#!/usr/bin/env python3
"""
Backend API Testing for Abbas FIT - NEW Admin Features
Testing the newly added admin features as per review request:
1. App Settings (Admin Only)
2. Legal Pages CRUD (Admin Only) 
3. API Keys Management (Admin Only)
4. User Block/Unblock
5. Bulk User Actions
"""

import requests
import json
import sys
from datetime import datetime

# Configuration
BASE_URL = "https://fitcoach-108.preview.emergentagent.com/api"
ADMIN_EMAIL = "admin@abbasfit.com"
ADMIN_PASSWORD = "admin"

class NewAdminFeaturesTester:
    def __init__(self):
        self.token = None
        self.test_results = []
        self.failed_tests = []
        
    def log_test(self, test_name, success, details=""):
        """Log test result"""
        status = "✅ PASS" if success else "❌ FAIL"
        result = f"{status}: {test_name}"
        if details:
            result += f" - {details}"
        print(result)
        
        self.test_results.append({
            "test": test_name,
            "success": success,
            "details": details,
            "timestamp": datetime.now().isoformat()
        })
        
        if not success:
            self.failed_tests.append(test_name)
    
    def make_request(self, method, endpoint, data=None, headers=None, expect_status=200):
        """Make HTTP request with error handling"""
        url = f"{BASE_URL}{endpoint}"
        
        default_headers = {"Content-Type": "application/json"}
        if self.token:
            default_headers["Authorization"] = f"Bearer {self.token}"
        
        if headers:
            default_headers.update(headers)
            
        try:
            if method.upper() == "GET":
                response = requests.get(url, headers=default_headers, timeout=30)
            elif method.upper() == "POST":
                response = requests.post(url, json=data, headers=default_headers, timeout=30)
            elif method.upper() == "PUT":
                response = requests.put(url, json=data, headers=default_headers, timeout=30)
            elif method.upper() == "DELETE":
                response = requests.delete(url, headers=default_headers, timeout=30)
            else:
                raise ValueError(f"Unsupported method: {method}")
                
            return response
            
        except requests.exceptions.RequestException as e:
            print(f"Request failed: {e}")
            return None
    
    def test_admin_login(self):
        """Test admin login and get JWT token"""
        print("\n=== Testing Admin Login ===")
        
        login_data = {
            "email": ADMIN_EMAIL,
            "password": ADMIN_PASSWORD
        }
        
        response = self.make_request("POST", "/auth/login", login_data)
        
        if response and response.status_code == 200:
            data = response.json()
            if "access_token" in data and data.get("user", {}).get("role") == "admin":
                self.token = data["access_token"]
                self.log_test("Admin Login", True, f"Token received, role: {data['user']['role']}")
                return True
            else:
                self.log_test("Admin Login", False, "Invalid response structure or role")
                return False
        else:
            status = response.status_code if response else "No response"
            self.log_test("Admin Login", False, f"Login failed with status: {status}")
            return False
    
    def test_app_settings(self):
        """Test App Settings endpoints"""
        print("\n=== Testing App Settings ===")
        
        # Test public settings endpoint (no auth needed)
        temp_token = self.token
        self.token = None  # Remove token for public endpoint
        
        response = self.make_request("GET", "/settings")
        if response and response.status_code == 200:
            self.log_test("GET /api/settings (public)", True, "Public settings retrieved")
        else:
            status = response.status_code if response else "No response"
            self.log_test("GET /api/settings (public)", False, f"Status: {status}")
        
        # Restore token for admin endpoints
        self.token = temp_token
        
        # Test admin settings endpoint
        response = self.make_request("GET", "/admin/settings")
        if response and response.status_code == 200:
            settings_data = response.json()
            self.log_test("GET /api/admin/settings", True, f"Admin settings retrieved with {len(settings_data)} fields")
        else:
            status = response.status_code if response else "No response"
            self.log_test("GET /api/admin/settings", False, f"Status: {status}")
            return
        
        # Test updating app settings
        update_data = {
            "app_name": "Abbas FIT Updated",
            "contact_email": "test@abbasfit.com",
            "hero_title": "Transform Your Body - Updated"
        }
        
        response = self.make_request("PUT", "/admin/settings", update_data)
        if response and response.status_code == 200:
            updated_data = response.json()
            if updated_data.get("app_name") == update_data["app_name"]:
                self.log_test("PUT /api/admin/settings", True, "Settings updated successfully")
            else:
                self.log_test("PUT /api/admin/settings", False, "Settings not updated properly")
        else:
            status = response.status_code if response else "No response"
            self.log_test("PUT /api/admin/settings", False, f"Status: {status}")
    
    def test_legal_pages(self):
        """Test Legal Pages CRUD operations"""
        print("\n=== Testing Legal Pages CRUD ===")
        
        # Test getting all legal pages
        response = self.make_request("GET", "/admin/legal")
        if response and response.status_code == 200:
            legal_pages = response.json()
            self.log_test("GET /api/admin/legal", True, f"Retrieved {len(legal_pages)} legal pages")
        else:
            status = response.status_code if response else "No response"
            self.log_test("GET /api/admin/legal", False, f"Status: {status}")
        
        # Test creating a new legal page
        create_data = {
            "page_type": "terms",
            "title": "Terms of Service - Test",
            "content": "<h1>Test Terms</h1><p>This is a test terms page created by automated testing.</p>"
        }
        
        response = self.make_request("POST", "/admin/legal", create_data)
        created_page_id = None
        
        if response and response.status_code == 200:
            created_page = response.json()
            created_page_id = created_page.get("id")
            if created_page_id and created_page.get("title") == create_data["title"]:
                self.log_test("POST /api/admin/legal", True, f"Legal page created with ID: {created_page_id}")
            else:
                self.log_test("POST /api/admin/legal", False, "Page created but missing ID or title mismatch")
        else:
            status = response.status_code if response else "No response"
            self.log_test("POST /api/admin/legal", False, f"Status: {status}")
            return
        
        # Test updating the legal page
        if created_page_id:
            update_data = {
                "title": "Terms of Service - Updated",
                "content": "<h1>Updated Terms</h1><p>This content has been updated.</p>"
            }
            
            response = self.make_request("PUT", f"/admin/legal/{created_page_id}", update_data)
            if response and response.status_code == 200:
                updated_page = response.json()
                if updated_page.get("title") == update_data["title"]:
                    self.log_test("PUT /api/admin/legal/{id}", True, "Legal page updated successfully")
                else:
                    self.log_test("PUT /api/admin/legal/{id}", False, "Update response incorrect")
            else:
                status = response.status_code if response else "No response"
                self.log_test("PUT /api/admin/legal/{id}", False, f"Status: {status}")
        
        # Test public endpoint for terms page
        temp_token = self.token
        self.token = None  # Remove token for public endpoint
        
        response = self.make_request("GET", "/legal/terms")
        if response and response.status_code == 200:
            terms_data = response.json()
            self.log_test("GET /api/legal/terms (public)", True, "Public terms page retrieved")
        else:
            status = response.status_code if response else "No response"
            self.log_test("GET /api/legal/terms (public)", False, f"Status: {status}")
        
        # Restore token
        self.token = temp_token
        
        # Test deleting the legal page
        if created_page_id:
            response = self.make_request("DELETE", f"/admin/legal/{created_page_id}")
            if response and response.status_code == 200:
                self.log_test("DELETE /api/admin/legal/{id}", True, "Legal page deleted successfully")
            else:
                status = response.status_code if response else "No response"
                self.log_test("DELETE /api/admin/legal/{id}", False, f"Status: {status}")
    
    def test_api_keys_management(self):
        """Test API Keys Management"""
        print("\n=== Testing API Keys Management ===")
        
        # Test getting all API keys (should return masked keys)
        response = self.make_request("GET", "/admin/api-keys")
        if response and response.status_code == 200:
            api_keys = response.json()
            self.log_test("GET /api/admin/api-keys", True, f"Retrieved {len(api_keys)} API keys (masked)")
        else:
            status = response.status_code if response else "No response"
            self.log_test("GET /api/admin/api-keys", False, f"Status: {status}")
        
        # Test creating a new API key
        create_data = {
            "name": "Test Gemini Key",
            "key_type": "gemini",
            "api_key": "test-gemini-key-12345-abcdef",
            "description": "Test API key for automated testing"
        }
        
        response = self.make_request("POST", "/admin/api-keys", create_data)
        created_key_id = None
        
        if response and response.status_code == 200:
            created_key = response.json()
            created_key_id = created_key.get("id")
            if created_key_id and created_key.get("name") == create_data["name"]:
                self.log_test("POST /api/admin/api-keys", True, f"API key created with ID: {created_key_id}")
            else:
                self.log_test("POST /api/admin/api-keys", False, "Key created but missing ID or name mismatch")
        else:
            status = response.status_code if response else "No response"
            self.log_test("POST /api/admin/api-keys", False, f"Status: {status}")
            return
        
        # Test updating the API key
        if created_key_id:
            update_data = {
                "name": "Updated Test Gemini Key",
                "description": "Updated description for testing"
            }
            
            response = self.make_request("PUT", f"/admin/api-keys/{created_key_id}", update_data)
            if response and response.status_code == 200:
                updated_key = response.json()
                if updated_key.get("name") == update_data["name"]:
                    self.log_test("PUT /api/admin/api-keys/{id}", True, "API key updated successfully")
                else:
                    self.log_test("PUT /api/admin/api-keys/{id}", False, "Update response incorrect")
            else:
                status = response.status_code if response else "No response"
                self.log_test("PUT /api/admin/api-keys/{id}", False, f"Status: {status}")
        
        # Test revealing actual API key
        if created_key_id:
            response = self.make_request("GET", f"/admin/api-keys/{created_key_id}/reveal")
            if response and response.status_code == 200:
                revealed_key = response.json()
                if "api_key" in revealed_key:
                    self.log_test("GET /api/admin/api-keys/{id}/reveal", True, "API key revealed successfully")
                else:
                    self.log_test("GET /api/admin/api-keys/{id}/reveal", False, "Reveal response missing api_key")
            else:
                status = response.status_code if response else "No response"
                self.log_test("GET /api/admin/api-keys/{id}/reveal", False, f"Status: {status}")
        
        # Test deleting the API key
        if created_key_id:
            response = self.make_request("DELETE", f"/admin/api-keys/{created_key_id}")
            if response and response.status_code == 200:
                self.log_test("DELETE /api/admin/api-keys/{id}", True, "API key deleted successfully")
            else:
                status = response.status_code if response else "No response"
                self.log_test("DELETE /api/admin/api-keys/{id}", False, f"Status: {status}")
    
    def test_user_block_unblock(self):
        """Test User Block/Unblock functionality"""
        print("\n=== Testing User Block/Unblock ===")
        
        # First, get a list of users to test with
        response = self.make_request("GET", "/admin/users")
        if not response or response.status_code != 200:
            self.log_test("User Block/Unblock Setup", False, "Could not retrieve users list")
            return
        
        users = response.json()
        test_user = None
        
        # Find a regular user (not admin) to test with
        for user in users:
            if user.get("role") == "user" and not user.get("is_blocked"):
                test_user = user
                break
        
        if not test_user:
            self.log_test("User Block/Unblock Setup", False, "No suitable test user found")
            return
        
        user_id = test_user["id"]
        user_email = test_user["email"]
        
        # Test blocking the user
        response = self.make_request("PUT", f"/admin/users/{user_id}/block")
        if response and response.status_code == 200:
            self.log_test("PUT /api/admin/users/{user_id}/block", True, f"User {user_email} blocked successfully")
            
            # Test that blocked user cannot login (we'll test with wrong password but should get 403 if blocked)
            login_data = {
                "email": user_email,
                "password": "wrongpassword"  # We don't know the actual password
            }
            
            # Save current token
            admin_token = self.token
            self.token = None
            
            login_response = self.make_request("POST", "/auth/login", login_data)
            if login_response and login_response.status_code == 403:
                self.log_test("Blocked User Login Test", True, "Blocked user correctly denied login (403)")
            elif login_response and login_response.status_code == 401:
                # This is also acceptable - user might be blocked or password wrong
                self.log_test("Blocked User Login Test", True, "User login failed (401 - block check working)")
            else:
                status = login_response.status_code if login_response else "No response"
                self.log_test("Blocked User Login Test", False, f"Unexpected status: {status}")
            
            # Restore admin token
            self.token = admin_token
            
        else:
            status = response.status_code if response else "No response"
            self.log_test("PUT /api/admin/users/{user_id}/block", False, f"Status: {status}")
            return
        
        # Test unblocking the user
        response = self.make_request("PUT", f"/admin/users/{user_id}/unblock")
        if response and response.status_code == 200:
            self.log_test("PUT /api/admin/users/{user_id}/unblock", True, f"User {user_email} unblocked successfully")
        else:
            status = response.status_code if response else "No response"
            self.log_test("PUT /api/admin/users/{user_id}/unblock", False, f"Status: {status}")
    
    def test_bulk_user_actions(self):
        """Test Bulk User Actions"""
        print("\n=== Testing Bulk User Actions ===")
        
        # Get users for bulk testing
        response = self.make_request("GET", "/admin/users")
        if not response or response.status_code != 200:
            self.log_test("Bulk Actions Setup", False, "Could not retrieve users list")
            return
        
        users = response.json()
        test_user_ids = []
        
        # Get up to 2 regular users for testing
        for user in users:
            if user.get("role") == "user" and len(test_user_ids) < 2:
                test_user_ids.append(user["id"])
        
        if len(test_user_ids) < 1:
            self.log_test("Bulk Actions Setup", False, "Not enough test users found")
            return
        
        # Test bulk block action
        bulk_block_data = {
            "user_ids": test_user_ids,
            "action": "block"
        }
        
        response = self.make_request("POST", "/admin/users/bulk-action", bulk_block_data)
        if response and response.status_code == 200:
            result = response.json()
            self.log_test("POST /api/admin/users/bulk-action (block)", True, f"Bulk block completed for {len(test_user_ids)} users")
        else:
            status = response.status_code if response else "No response"
            self.log_test("POST /api/admin/users/bulk-action (block)", False, f"Status: {status}")
        
        # Test bulk unblock action
        bulk_unblock_data = {
            "user_ids": test_user_ids,
            "action": "unblock"
        }
        
        response = self.make_request("POST", "/admin/users/bulk-action", bulk_unblock_data)
        if response and response.status_code == 200:
            result = response.json()
            self.log_test("POST /api/admin/users/bulk-action (unblock)", True, f"Bulk unblock completed for {len(test_user_ids)} users")
        else:
            status = response.status_code if response else "No response"
            self.log_test("POST /api/admin/users/bulk-action (unblock)", False, f"Status: {status}")
    
    def test_error_handling(self):
        """Test error handling scenarios"""
        print("\n=== Testing Error Handling ===")
        
        # Test accessing admin endpoint without token
        old_token = self.token
        self.token = None
        
        response = self.make_request("GET", "/admin/settings")
        if response and response.status_code == 401:
            self.log_test("Unauthorized Access Test", True, "Correctly returned 401 without token")
        else:
            status = response.status_code if response else "No response"
            self.log_test("Unauthorized Access Test", False, f"Expected 401, got: {status}")
        
        # Restore token
        self.token = old_token
        
        # Test accessing non-existent legal page
        response = self.make_request("GET", "/admin/legal/non-existent-id")
        if response and response.status_code == 404:
            self.log_test("Non-existent Resource Test", True, "Correctly returned 404 for non-existent legal page")
        else:
            status = response.status_code if response else "No response"
            self.log_test("Non-existent Resource Test", False, f"Expected 404, got: {status}")
    
    def run_all_tests(self):
        """Run all test suites"""
        print("🚀 Starting Abbas FIT Backend API Testing - NEW Admin Features")
        print(f"Testing against: {BASE_URL}")
        print(f"Admin credentials: {ADMIN_EMAIL}")
        
        # Login first
        if not self.test_admin_login():
            print("❌ Admin login failed - cannot proceed with other tests")
            return False
        
        # Run all test suites for NEW admin features
        self.test_app_settings()
        self.test_legal_pages()
        self.test_api_keys_management()
        self.test_user_block_unblock()
        self.test_bulk_user_actions()
        self.test_error_handling()
        
        # Print summary
        print("\n" + "="*60)
        print("🏁 TEST SUMMARY")
        print("="*60)
        
        total_tests = len(self.test_results)
        passed_tests = len([t for t in self.test_results if t["success"]])
        failed_tests = len(self.failed_tests)
        
        print(f"Total Tests: {total_tests}")
        print(f"Passed: {passed_tests}")
        print(f"Failed: {failed_tests}")
        print(f"Success Rate: {(passed_tests/total_tests)*100:.1f}%")
        
        if self.failed_tests:
            print(f"\n❌ Failed Tests:")
            for test in self.failed_tests:
                print(f"  - {test}")
        else:
            print("\n🎉 All tests passed!")
        
        return failed_tests == 0

if __name__ == "__main__":
    runner = NewAdminFeaturesTester()
    success = runner.run_all_tests()
    sys.exit(0 if success else 1)