"""
Unit tests for response helper functions
Tests success_response, error_response, paginated_response
"""
from django.test import TestCase, RequestFactory
from rest_framework import status
from igny8_core.api.response import success_response, error_response, paginated_response, get_request_id


class ResponseHelpersTestCase(TestCase):
    """Test cases for response helper functions"""
    
    def setUp(self):
        """Set up test fixtures"""
        self.factory = RequestFactory()
    
    def test_success_response_with_data(self):
        """Test success_response with data"""
        data = {"id": 1, "name": "Test"}
        response = success_response(data=data, message="Success")
        
        self.assertEqual(response.status_code, status.HTTP_200_OK)
        self.assertTrue(response.data['success'])
        self.assertEqual(response.data['data'], data)
        self.assertEqual(response.data['message'], "Success")
    
    def test_success_response_without_data(self):
        """Test success_response without data"""
        response = success_response(message="Success")
        
        self.assertEqual(response.status_code, status.HTTP_200_OK)
        self.assertTrue(response.data['success'])
        self.assertNotIn('data', response.data)
        self.assertEqual(response.data['message'], "Success")
    
    def test_success_response_with_custom_status(self):
        """Test success_response with custom status code"""
        data = {"id": 1}
        response = success_response(data=data, status_code=status.HTTP_201_CREATED)
        
        self.assertEqual(response.status_code, status.HTTP_201_CREATED)
        self.assertTrue(response.data['success'])
        self.assertEqual(response.data['data'], data)
    
    def test_success_response_with_request_id(self):
        """Test success_response includes request_id when request provided"""
        request = self.factory.get('/test/')
        request.request_id = 'test-request-id-123'
        
        response = success_response(data={"id": 1}, request=request)
        
        self.assertTrue(response.data['success'])
        self.assertEqual(response.data['request_id'], 'test-request-id-123')
    
    def test_error_response_with_error_message(self):
        """Test error_response with error message"""
        response = error_response(error="Validation failed")
        
        self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST)
        self.assertFalse(response.data['success'])
        self.assertEqual(response.data['error'], "Validation failed")
    
    def test_error_response_with_errors_dict(self):
        """Test error_response with field-specific errors"""
        errors = {"email": ["Invalid email format"], "password": ["Too short"]}
        response = error_response(error="Validation failed", errors=errors)
        
        self.assertFalse(response.data['success'])
        self.assertEqual(response.data['error'], "Validation failed")
        self.assertEqual(response.data['errors'], errors)
    
    def test_error_response_status_code_mapping(self):
        """Test error_response maps status codes to default error messages"""
        # Test 401
        response = error_response(status_code=status.HTTP_401_UNAUTHORIZED)
        self.assertEqual(response.data['error'], 'Authentication required')
        
        # Test 403
        response = error_response(status_code=status.HTTP_403_FORBIDDEN)
        self.assertEqual(response.data['error'], 'Permission denied')
        
        # Test 404
        response = error_response(status_code=status.HTTP_404_NOT_FOUND)
        self.assertEqual(response.data['error'], 'Resource not found')
        
        # Test 409
        response = error_response(status_code=status.HTTP_409_CONFLICT)
        self.assertEqual(response.data['error'], 'Conflict')
        
        # Test 422
        response = error_response(status_code=status.HTTP_422_UNPROCESSABLE_ENTITY)
        self.assertEqual(response.data['error'], 'Validation failed')
        
        # Test 429
        response = error_response(status_code=status.HTTP_429_TOO_MANY_REQUESTS)
        self.assertEqual(response.data['error'], 'Rate limit exceeded')
        
        # Test 500
        response = error_response(status_code=status.HTTP_500_INTERNAL_SERVER_ERROR)
        self.assertEqual(response.data['error'], 'Internal server error')
    
    def test_error_response_with_request_id(self):
        """Test error_response includes request_id when request provided"""
        request = self.factory.get('/test/')
        request.request_id = 'test-request-id-456'
        
        response = error_response(error="Error occurred", request=request)
        
        self.assertFalse(response.data['success'])
        self.assertEqual(response.data['request_id'], 'test-request-id-456')
    
    def test_error_response_with_debug_info(self):
        """Test error_response includes debug info when provided"""
        debug_info = {"exception_type": "ValueError", "message": "Test error"}
        response = error_response(error="Error", debug_info=debug_info)
        
        self.assertFalse(response.data['success'])
        self.assertEqual(response.data['debug'], debug_info)
    
    def test_paginated_response_with_data(self):
        """Test paginated_response with paginated data"""
        paginated_data = {
            'count': 100,
            'next': 'http://test.com/api/v1/test/?page=2',
            'previous': None,
            'results': [{"id": 1}, {"id": 2}]
        }
        response = paginated_response(paginated_data, message="Success")
        
        self.assertEqual(response.status_code, status.HTTP_200_OK)
        self.assertTrue(response.data['success'])
        self.assertEqual(response.data['count'], 100)
        self.assertEqual(response.data['next'], paginated_data['next'])
        self.assertEqual(response.data['previous'], None)
        self.assertEqual(response.data['results'], paginated_data['results'])
        self.assertEqual(response.data['message'], "Success")
    
    def test_paginated_response_without_message(self):
        """Test paginated_response without message"""
        paginated_data = {
            'count': 50,
            'next': None,
            'previous': None,
            'results': []
        }
        response = paginated_response(paginated_data)
        
        self.assertTrue(response.data['success'])
        self.assertEqual(response.data['count'], 50)
        self.assertNotIn('message', response.data)
    
    def test_paginated_response_with_request_id(self):
        """Test paginated_response includes request_id when request provided"""
        request = self.factory.get('/test/')
        request.request_id = 'test-request-id-789'
        
        paginated_data = {
            'count': 10,
            'next': None,
            'previous': None,
            'results': []
        }
        response = paginated_response(paginated_data, request=request)
        
        self.assertTrue(response.data['success'])
        self.assertEqual(response.data['request_id'], 'test-request-id-789')
    
    def test_paginated_response_fallback(self):
        """Test paginated_response handles non-dict input"""
        response = paginated_response(None)
        
        self.assertTrue(response.data['success'])
        self.assertEqual(response.data['count'], 0)
        self.assertIsNone(response.data['next'])
        self.assertIsNone(response.data['previous'])
        self.assertEqual(response.data['results'], [])
    
    def test_get_request_id_from_request_object(self):
        """Test get_request_id retrieves from request.request_id"""
        request = self.factory.get('/test/')
        request.request_id = 'request-id-from-object'
        
        request_id = get_request_id(request)
        self.assertEqual(request_id, 'request-id-from-object')
    
    def test_get_request_id_from_headers(self):
        """Test get_request_id retrieves from headers"""
        request = self.factory.get('/test/', HTTP_X_REQUEST_ID='request-id-from-header')
        
        request_id = get_request_id(request)
        self.assertEqual(request_id, 'request-id-from-header')
    
    def test_get_request_id_generates_new(self):
        """Test get_request_id generates new UUID if not found"""
        request = self.factory.get('/test/')
        
        request_id = get_request_id(request)
        self.assertIsNotNone(request_id)
        self.assertIsInstance(request_id, str)
        # UUID format check
        import uuid
        try:
            uuid.UUID(request_id)
        except ValueError:
            self.fail("Generated request_id is not a valid UUID")

