#!/usr/bin/env python3
"""
Полный тест безопасности и функциональности Emergency Service
- Проверка блокировки временных токенов
- Проверка работы JWT аутентификации
- Полное тестирование всех Emergency API endpoints
- Создание и проверка записей экстренных вызовов
"""

import asyncio
import json
import httpx
import websockets
from typing import Optional

class SecurityTest:
    def __init__(self):
        self.base_url = "http://localhost:8000"    # API Gateway
        self.emergency_url = "http://localhost:8002"  # Emergency Service напрямую
        self.ws_url = "ws://localhost:8002"        # Emergency Service
        
    async def test_temp_token_rejection(self) -> bool:
        """Тестируем, что временные токены отклоняются"""
        print("🔒 ТЕСТ БЕЗОПАСНОСТИ: Блокировка временных токенов")
        print("="*60)
        
        temp_tokens = [
            "temp_token_for_shadow85@list.ru",
            "test_token_123",
            "temp_token_12345",
            "test_token_admin"
        ]
        
        all_rejected = True
        
        for token in temp_tokens:
            try:
                ws_url = f"{self.ws_url}/api/v1/emergency/ws/current_user_id?token={token}"
                print(f"🔍 Тестируем токен: {token[:30]}...")
                
                # Пытаемся подключиться (должно быть отклонено)
                async with websockets.connect(ws_url) as websocket:
                    print(f"❌ ПРОБЛЕМА БЕЗОПАСНОСТИ: Токен {token[:30]}... был принят!")
                    all_rejected = False
                    
            except websockets.exceptions.ConnectionClosed as e:
                if e.code in [1008, 403]:  # Policy violation или Forbidden
                    print(f"✅ Токен {token[:30]}... корректно отклонен (код: {e.code})")
                else:
                    print(f"⚠️  Токен {token[:30]}... отклонен с неожиданным кодом: {e.code}")
                    
            except Exception as e:
                print(f"✅ Токен {token[:30]}... корректно отклонен: {type(e).__name__}")
        
        return all_rejected
    
    async def test_jwt_token_acceptance(self) -> bool:
        """Тестируем, что настоящие JWT токены принимаются"""
        print("\n🔓 ТЕСТ: Прием настоящих JWT токенов")
        print("="*50)
        
        try:
            # Получаем настоящий JWT токен
            async with httpx.AsyncClient() as client:
                login_data = {
                    "email": "shadow85@list.ru",
                    "password": "R0sebud1985"
                }
                
                print("🔐 Получаем JWT токен...")
                response = await client.post(
                    f"{self.base_url}/api/v1/auth/login",
                    json=login_data,
                    headers={"Content-Type": "application/json"}
                )
                
                if response.status_code != 200:
                    print(f"❌ Не удалось получить JWT токен: {response.status_code}")
                    return False
                
                auth_data = response.json()
                jwt_token = auth_data.get("access_token")
                
                if not jwt_token:
                    print("❌ JWT токен не найден в ответе")
                    return False
                
                print(f"✅ JWT токен получен: {jwt_token[:50]}...")
                
                # Тестируем WebSocket с JWT токеном
                ws_url = f"{self.ws_url}/api/v1/emergency/ws/current_user_id?token={jwt_token}"
                print("🔌 Тестируем WebSocket с JWT токеном...")
                
                async with websockets.connect(ws_url) as websocket:
                    print("✅ JWT токен принят, WebSocket подключен!")
                    
                    # Отправляем ping
                    await websocket.send(json.dumps({"type": "ping"}))
                    
                    try:
                        response = await asyncio.wait_for(websocket.recv(), timeout=3.0)
                        print(f"📥 Ответ сервера: {response}")
                    except asyncio.TimeoutError:
                        print("⏰ Таймаут, но подключение работает")
                    
                    return True
                    
        except Exception as e:
            print(f"❌ Ошибка тестирования JWT токена: {e}")
            return False

    async def test_emergency_endpoints(self) -> bool:
        """Полное тестирование всех endpoint'ов экстренных вызовов"""
        print("\n🚨 ТЕСТ: Полная проверка Emergency API")
        print("="*60)
        
        try:
            # Получаем JWT токен
            async with httpx.AsyncClient() as client:
                login_data = {
                    "email": "shadow85@list.ru",
                    "password": "R0sebud1985"
                }
                
                print("🔐 Авторизация для тестирования API...")
                response = await client.post(
                    f"{self.base_url}/api/v1/auth/login",
                    json=login_data,
                    headers={"Content-Type": "application/json"}
                )
                
                if response.status_code != 200:
                    print(f"❌ Ошибка авторизации: {response.status_code}")
                    return False
                
                auth_data = response.json()
                jwt_token = auth_data.get("access_token")
                headers = {
                    "Authorization": f"Bearer {jwt_token}",
                    "Content-Type": "application/json"
                }
                
                test_results = {}
                
                # 1. Создание экстренного вызова (правильный endpoint)
                print("\n📞 1. Тест создания экстренного вызова...")
                alert_data = {
                    "alert_type": "medical",
                    "latitude": 55.7558,
                    "longitude": 37.6176,
                    "address": "Красная площадь, Москва",
                    "description": "Тестовый экстренный вызов для проверки API"
                }
                
                response = await client.post(
                    f"{self.emergency_url}/api/v1/alert",  # Используем правильный endpoint
                    json=alert_data,
                    headers=headers
                )
                
                if response.status_code in [200, 201]:
                    created_alert = response.json()
                    alert_id = created_alert.get("id")
                    print(f"✅ Экстренный вызов создан: ID={alert_id}")
                    test_results["create_alert"] = True
                else:
                    print(f"❌ Ошибка создания вызова: {response.status_code} - {response.text}")
                    test_results["create_alert"] = False
                    alert_id = None
                
                # 2. Получение моих вызовов
                print("\n📋 2. Тест получения моих вызовов...")
                response = await client.get(
                    f"{self.emergency_url}/api/v1/alerts/my",
                    headers=headers
                )
                
                if response.status_code == 200:
                    alerts = response.json()
                    print(f"✅ Получен список моих вызовов: {len(alerts)} записей")
                    test_results["get_my_alerts"] = True
                else:
                    print(f"❌ Ошибка получения моих вызовов: {response.status_code}")
                    test_results["get_my_alerts"] = False
                
                # 3. Получение активных вызовов
                print("\n� 3. Тест получения активных вызовов...")
                response = await client.get(
                    f"{self.emergency_url}/api/v1/alerts/active",
                    headers=headers
                )
                
                if response.status_code == 200:
                    active_alerts = response.json()
                    print(f"✅ Получен список активных вызовов: {len(active_alerts)} записей")
                    test_results["get_active_alerts"] = True
                else:
                    print(f"❌ Ошибка получения активных вызовов: {response.status_code}")
                    test_results["get_active_alerts"] = False
                
                # 4. Создание отчета об экстренной ситуации
                print("\n📝 4. Тест создания отчета...")
                report_data = {
                    "incident_type": "suspicious_activity",
                    "latitude": 55.7500,
                    "longitude": 37.6200,
                    "address": "Тверская улица, Москва",
                    "description": "Тестовый отчет о подозрительной активности",
                    "severity": "medium"
                }
                
                response = await client.post(
                    f"{self.emergency_url}/api/v1/report",
                    json=report_data,
                    headers=headers
                )
                
                if response.status_code in [200, 201]:
                    created_report = response.json()
                    report_id = created_report.get("id")
                    print(f"✅ Отчет создан: ID={report_id}")
                    test_results["create_report"] = True
                else:
                    print(f"❌ Ошибка создания отчета: {response.status_code} - {response.text}")
                    test_results["create_report"] = False
                    report_id = None
                
                # 5. Получение списка отчетов
                print("\n📊 5. Тест получения списка отчетов...")
                response = await client.get(
                    f"{self.emergency_url}/api/v1/reports",
                    headers=headers
                )
                
                if response.status_code == 200:
                    reports = response.json()
                    print(f"✅ Получен список отчетов: {len(reports)} записей")
                    test_results["get_reports"] = True
                else:
                    print(f"❌ Ошибка получения отчетов: {response.status_code}")
                    test_results["get_reports"] = False
                
                # 6. Поиск ближайших вызовов
                print("\n🗺️  6. Тест поиска ближайших вызовов...")
                response = await client.get(
                    f"{self.emergency_url}/api/v1/alerts/nearby?latitude=55.7558&longitude=37.6176&radius=5",
                    headers=headers
                )
                
                if response.status_code == 200:
                    nearby_alerts = response.json()
                    print(f"✅ Найдены ближайшие вызовы: {len(nearby_alerts)} в радиусе 5км")
                    test_results["nearby_alerts"] = True
                else:
                    print(f"❌ Ошибка поиска ближайших: {response.status_code}")
                    test_results["nearby_alerts"] = False
                
                # 7. Создание проверки безопасности
                print("\n🛡️  7. Тест создания проверки безопасности...")
                safety_data = {
                    "latitude": 55.7600,
                    "longitude": 37.6100,
                    "status": "safe",
                    "message": "Тестовая проверка безопасности - всё в порядке"
                }
                
                response = await client.post(
                    f"{self.emergency_url}/api/v1/safety-check",
                    json=safety_data,
                    headers=headers
                )
                
                if response.status_code in [200, 201]:
                    safety_check = response.json()
                    print(f"✅ Проверка безопасности создана: статус={safety_check.get('status')}")
                    test_results["create_safety_check"] = True
                else:
                    print(f"❌ Ошибка создания проверки: {response.status_code} - {response.text}")
                    test_results["create_safety_check"] = False
                
                # 8. Получение списка проверок безопасности
                print("\n�️  8. Тест получения проверок безопасности...")
                response = await client.get(
                    f"{self.emergency_url}/api/v1/safety-checks",
                    headers=headers
                )
                
                if response.status_code == 200:
                    safety_checks = response.json()
                    print(f"✅ Получен список проверок: {len(safety_checks)} записей")
                    test_results["get_safety_checks"] = True
                else:
                    print(f"❌ Ошибка получения проверок: {response.status_code}")
                    test_results["get_safety_checks"] = False
                
                # 9. Получение статистики
                print("\n📈 9. Тест получения статистики...")
                response = await client.get(
                    f"{self.emergency_url}/api/v1/stats",
                    headers=headers
                )
                
                if response.status_code == 200:
                    stats = response.json()
                    print(f"✅ Статистика получена: {stats}")
                    test_results["get_statistics"] = True
                else:
                    print(f"❌ Ошибка получения статистики: {response.status_code}")
                    test_results["get_statistics"] = False
                
                # 10. Ответ на экстренный вызов (если создан)
                if alert_id:
                    print(f"\n🆘 10. Тест ответа на вызов ID={alert_id}...")
                    response_data = {
                        "response_type": "help_on_way",
                        "message": "Помощь в пути, держитесь!"
                    }
                    
                    response = await client.post(
                        f"{self.emergency_url}/api/v1/alert/{alert_id}/respond",
                        json=response_data,
                        headers=headers
                    )
                    
                    if response.status_code in [200, 201]:
                        alert_response = response.json()
                        print(f"✅ Ответ на вызов создан: {alert_response.get('response_type')}")
                        test_results["respond_to_alert"] = True
                    else:
                        print(f"❌ Ошибка ответа на вызов: {response.status_code}")
                        test_results["respond_to_alert"] = False
                
                # Результат тестирования API
                total_tests = len(test_results)
                passed_tests = sum(test_results.values())
                
                print(f"\n📊 РЕЗУЛЬТАТ ТЕСТИРОВАНИЯ API:")
                print(f"✅ Пройдено: {passed_tests}/{total_tests} тестов")
                
                for test_name, result in test_results.items():
                    status = "✅" if result else "❌"
                    print(f"  {status} {test_name}")
                
                return passed_tests == total_tests
                
        except Exception as e:
            print(f"❌ Ошибка тестирования Emergency API: {e}")
            return False
    
    async def run_security_test(self):
        """Запуск полного теста безопасности"""
        print("🛡️  ЗАПУСК ПОЛНОГО ТЕСТА БЕЗОПАСНОСТИ И ФУНКЦИОНАЛЬНОСТИ")
        print("="*80)
        
        # Тест 1: Блокировка временных токенов
        temp_tokens_blocked = await self.test_temp_token_rejection()
        
        # Тест 2: Прием JWT токенов  
        jwt_tokens_accepted = await self.test_jwt_token_acceptance()
        
        # Тест 3: Полная проверка Emergency API
        emergency_api_working = await self.test_emergency_endpoints()
        
        # Результат
        print("\n" + "="*80)
        print("📊 ПОЛНЫЙ РЕЗУЛЬТАТ ТЕСТИРОВАНИЯ")
        print("="*80)
        
        all_tests_passed = temp_tokens_blocked and jwt_tokens_accepted and emergency_api_working
        
        if all_tests_passed:
            print("✅ ВСЕ ТЕСТЫ ПРОЙДЕНЫ УСПЕШНО!")
            print("✅ Безопасность: Временные токены корректно блокируются")
            print("✅ Аутентификация: JWT токены корректно принимаются")
            print("✅ Функциональность: Все Emergency API работают")
            print("🔒 Система полностью готова к продакшену")
        else:
            print("❌ ОБНАРУЖЕНЫ ПРОБЛЕМЫ!")
            if not temp_tokens_blocked:
                print("❌ Проблема безопасности: Временные токены не блокируются")
            if not jwt_tokens_accepted:
                print("❌ Проблема аутентификации: JWT токены не принимаются")
            if not emergency_api_working:
                print("❌ Проблема функциональности: Emergency API работают неполностью")
            print("⚠️  Система НЕ готова к продакшену")
        
        print(f"\n📈 Статистика тестирования:")
        print(f"  🔒 Безопасность: {'✅ ПРОЙДЕНО' if temp_tokens_blocked else '❌ ПРОВАЛЕНО'}")
        print(f"  🔐 Аутентификация: {'✅ ПРОЙДЕНО' if jwt_tokens_accepted else '❌ ПРОВАЛЕНО'}")
        print(f"  🚨 Emergency API: {'✅ ПРОЙДЕНО' if emergency_api_working else '❌ ПРОВАЛЕНО'}")
        
        return all_tests_passed

async def main():
    """Главная функция"""
    tester = SecurityTest()
    await tester.run_security_test()

if __name__ == "__main__":
    asyncio.run(main())