"""
Comprehensive Unit Tests for Export Functionality and Data Integrity

This module contains unit tests for export functionality, data integrity validation,
and report generation across all formats.
"""

from django.test import TestCase, TransactionTestCase
from django.utils import timezone
from django.contrib.auth import get_user_model
from django.core.files.storage import default_storage
from unittest.mock import patch, MagicMock, mock_open
from decimal import Decimal
from datetime import date, timedelta
import json
import csv
import io
import tempfile
import os

from users.models import Branch
from reports.enhanced_pdf_service import EnhancedPDFService
from reports.export_functions import ExportService
from reports.advanced_filtering_service import AdvancedFilteringService
from reports.batch_processing_service import BatchProcessingService
from reports.chart_generation_service import ChartGenerationService

User = get_user_model()


class PDFGenerationTest(TestCase):
    """Test cases for PDF generation functionality"""
    
    def setUp(self):
        """Set up test data"""
        self.branch = Branch.objects.create(
            name="Test Branch",
            code="TB001",
            is_active=True
        )
        
        self.user = User.objects.create_user(
            username="testuser",
            email="test@test.com",
            password="testpass123",
            role="loan_officer",
            branch=self.branch,
            phone_number="+254700000001"
        )
        
        self.pdf_service = EnhancedPDFService()
    
    def test_basic_pdf_generation(self):
        """Test basic PDF generation"""
        # Mock report data
        report_data = {
            'title': 'Test Report',
            'generated_by': self.user.get_full_name(),
            'generated_at': timezone.now(),
            'content': [
                {'type': 'text', 'content': 'This is a test report'},
                {'type': 'table', 'headers': ['Name', 'Amount'], 'rows': [['John', '1000'], ['Jane', '2000']]}
            ]
        }
        
        # Mock PDF generation
        with patch('reports.enhanced_pdf_service.canvas') as mock_canvas:
            mock_canvas.Canvas.return_value = MagicMock()
            
            result = self.pdf_service.generate_report(report_data, 'test_report.pdf')
            
            # Verify PDF generation
            self.assertIn('success', result)
            self.assertTrue(result['success'])
            self.assertIn('file_path', result)
            self.assertIn('file_size', result)
    
    def test_pdf_with_charts(self):
        """Test PDF generation with charts"""
        # Mock chart data
        chart_data = {
            'type': 'bar',
            'title': 'Monthly Performance',
            'data': {
                'labels': ['Jan', 'Feb', 'Mar'],
                'values': [100, 150, 120]
            }
        }
        
        report_data = {
            'title': 'Performance Report',
            'charts': [chart_data],
            'content': []
        }
        
        # Mock chart generation
        with patch.object(self.pdf_service, '_generate_chart') as mock_chart:
            mock_chart.return_value = '/tmp/chart.png'
            
            with patch('reports.enhanced_pdf_service.canvas') as mock_canvas:
                mock_canvas.Canvas.return_value = MagicMock()
                
                result = self.pdf_service.generate_report(report_data, 'chart_report.pdf')
                
                # Verify chart was generated
                mock_chart.assert_called_once()
                self.assertTrue(result['success'])
    
    def test_pdf_with_branding(self):
        """Test PDF generation with company branding"""
        report_data = {
            'title': 'Branded Report',
            'branding': {
                'logo_path': '/path/to/logo.png',
                'company_name': 'Test Company',
                'address': '123 Test Street',
                'phone': '+254700000000'
            },
            'content': []
        }
        
        with patch('reports.enhanced_pdf_service.canvas') as mock_canvas:
            mock_pdf = MagicMock()
            mock_canvas.Canvas.return_value = mock_pdf
            
            result = self.pdf_service.generate_report(report_data, 'branded_report.pdf')
            
            # Verify branding elements were added
            self.assertTrue(result['success'])
            # Verify canvas methods were called for branding
            mock_pdf.drawString.assert_called()
    
    def test_pdf_error_handling(self):
        """Test PDF generation error handling"""
        report_data = {
            'title': 'Error Test Report',
            'content': []
        }
        
        # Mock PDF generation error
        with patch('reports.enhanced_pdf_service.canvas') as mock_canvas:
            mock_canvas.Canvas.side_effect = Exception("PDF generation error")
            
            result = self.pdf_service.generate_report(report_data, 'error_report.pdf')
            
            # Verify error handling
            self.assertFalse(result['success'])
            self.assertIn('error', result)
    
    def test_pdf_template_system(self):
        """Test PDF template system"""
        template_data = {
            'template': 'portfolio_summary',
            'data': {
                'manager_name': self.user.get_full_name(),
                'total_clients': 50,
                'active_loans': 45,
                'collection_rate': 85.5
            }
        }
        
        with patch.object(self.pdf_service, '_load_template') as mock_template:
            mock_template.return_value = {
                'layout': 'standard',
                'sections': ['header', 'summary', 'details', 'footer']
            }
            
            with patch('reports.enhanced_pdf_service.canvas') as mock_canvas:
                mock_canvas.Canvas.return_value = MagicMock()
                
                result = self.pdf_service.generate_from_template(template_data)
                
                # Verify template was loaded and used
                mock_template.assert_called_once_with('portfolio_summary')
                self.assertTrue(result['success'])


class ExcelExportTest(TestCase):
    """Test cases for Excel export functionality"""
    
    def setUp(self):
        """Set up test data"""
        self.export_service = ExportService()
        
        # Mock data for export
        self.test_data = [
            {
                'client_name': 'John Doe',
                'loan_amount': Decimal('10000.00'),
                'interest_rate': Decimal('12.5'),
                'status': 'Active',
                'disbursement_date': timezone.now().date(),
                'due_date': timezone.now().date() + timedelta(days=30)
            },
            {
                'client_name': 'Jane Smith',
                'loan_amount': Decimal('15000.00'),
                'interest_rate': Decimal('10.0'),
                'status': 'Completed',
                'disbursement_date': timezone.now().date() - timedelta(days=60),
                'due_date': timezone.now().date() - timedelta(days=30)
            }
        ]
    
    def test_basic_excel_export(self):
        """Test basic Excel export functionality"""
        with patch('reports.export_functions.openpyxl') as mock_openpyxl:
            mock_workbook = MagicMock()
            mock_worksheet = MagicMock()
            mock_openpyxl.Workbook.return_value = mock_workbook
            mock_workbook.active = mock_worksheet
            
            result = self.export_service.export_to_excel(
                data=self.test_data,
                filename='test_export.xlsx'
            )
            
            # Verify Excel export
            self.assertTrue(result['success'])
            self.assertEqual(result['rows_exported'], 2)
            self.assertIn('file_path', result)
    
    def test_excel_with_formatting(self):
        """Test Excel export with formatting rules"""
        formatting_rules = {
            'loan_amount': 'currency',
            'interest_rate': 'percentage',
            'disbursement_date': 'date',
            'due_date': 'date'
        }
        
        with patch('reports.export_functions.openpyxl') as mock_openpyxl:
            mock_workbook = MagicMock()
            mock_worksheet = MagicMock()
            mock_openpyxl.Workbook.return_value = mock_workbook
            mock_workbook.active = mock_worksheet
            
            result = self.export_service.export_to_excel(
                data=self.test_data,
                filename='formatted_export.xlsx',
                formatting_rules=formatting_rules
            )
            
            # Verify formatting was applied
            self.assertTrue(result['success'])
            # Verify formatting methods were called
            mock_worksheet.cell.assert_called()
    
    def test_excel_multiple_worksheets(self):
        """Test Excel export with multiple worksheets"""
        worksheet_data = {
            'Loans': self.test_data,
            'Summary': [
                {'metric': 'Total Loans', 'value': 2},
                {'metric': 'Total Amount', 'value': Decimal('25000.00')}
            ]
        }
        
        with patch('reports.export_functions.openpyxl') as mock_openpyxl:
            mock_workbook = MagicMock()
            mock_openpyxl.Workbook.return_value = mock_workbook
            
            result = self.export_service.export_multiple_sheets(
                worksheet_data=worksheet_data,
                filename='multi_sheet_export.xlsx'
            )
            
            # Verify multiple worksheets were created
            self.assertTrue(result['success'])
            self.assertEqual(result['worksheets_created'], 2)
    
    def test_excel_with_charts(self):
        """Test Excel export with embedded charts"""
        chart_config = {
            'type': 'column',
            'title': 'Loan Amounts by Client',
            'data_range': 'A1:B3',
            'position': 'D1'
        }
        
        with patch('reports.export_functions.openpyxl') as mock_openpyxl:
            mock_workbook = MagicMock()
            mock_worksheet = MagicMock()
            mock_chart = MagicMock()
            
            mock_openpyxl.Workbook.return_value = mock_workbook
            mock_workbook.active = mock_worksheet
            mock_openpyxl.chart.ColumnChart.return_value = mock_chart
            
            result = self.export_service.export_with_charts(
                data=self.test_data,
                filename='chart_export.xlsx',
                charts=[chart_config]
            )
            
            # Verify chart was added
            self.assertTrue(result['success'])
            mock_worksheet.add_chart.assert_called_once()
    
    def test_excel_data_validation(self):
        """Test Excel export with data validation"""
        validation_rules = {
            'status': {
                'type': 'list',
                'formula1': '"Active,Pending,Completed"'
            },
            'interest_rate': {
                'type': 'decimal',
                'operator': 'between',
                'formula1': 0,
                'formula2': 100
            }
        }
        
        with patch('reports.export_functions.openpyxl') as mock_openpyxl:
            mock_workbook = MagicMock()
            mock_worksheet = MagicMock()
            mock_validation = MagicMock()
            
            mock_openpyxl.Workbook.return_value = mock_workbook
            mock_workbook.active = mock_worksheet
            mock_openpyxl.worksheet.datavalidation.DataValidation.return_value = mock_validation
            
            result = self.export_service.export_with_validation(
                data=self.test_data,
                filename='validated_export.xlsx',
                validation_rules=validation_rules
            )
            
            # Verify data validation was added
            self.assertTrue(result['success'])
            mock_worksheet.add_data_validation.assert_called()


class CSVExportTest(TestCase):
    """Test cases for CSV export functionality"""
    
    def setUp(self):
        """Set up test data"""
        self.export_service = ExportService()
        
        self.test_data = [
            {'name': 'John Doe', 'amount': 1000, 'status': 'Active'},
            {'name': 'Jane Smith', 'amount': 2000, 'status': 'Pending'}
        ]
    
    def test_basic_csv_export(self):
        """Test basic CSV export functionality"""
        with patch('builtins.open', mock_open()) as mock_file:
            result = self.export_service.export_to_csv(
                data=self.test_data,
                filename='test_export.csv'
            )
            
            # Verify CSV export
            self.assertTrue(result['success'])
            self.assertEqual(result['rows_exported'], 2)
            mock_file.assert_called_once()
    
    def test_csv_with_custom_delimiter(self):
        """Test CSV export with custom delimiter"""
        with patch('builtins.open', mock_open()) as mock_file:
            result = self.export_service.export_to_csv(
                data=self.test_data,
                filename='test_export.csv',
                delimiter=';'
            )
            
            # Verify custom delimiter was used
            self.assertTrue(result['success'])
    
    def test_csv_encoding_handling(self):
        """Test CSV export with different encodings"""
        # Test data with special characters
        special_data = [
            {'name': 'José García', 'amount': 1000, 'notes': 'Café'},
            {'name': 'François Müller', 'amount': 2000, 'notes': 'Naïve'}
        ]
        
        with patch('builtins.open', mock_open()) as mock_file:
            result = self.export_service.export_to_csv(
                data=special_data,
                filename='special_chars.csv',
                encoding='utf-8'
            )
            
            # Verify encoding was handled
            self.assertTrue(result['success'])
            mock_file.assert_called_with('special_chars.csv', 'w', encoding='utf-8', newline='')
    
    def test_csv_large_dataset(self):
        """Test CSV export with large dataset"""
        # Generate large dataset
        large_data = [
            {'id': i, 'name': f'Client {i}', 'amount': i * 100}
            for i in range(10000)
        ]
        
        with patch('builtins.open', mock_open()) as mock_file:
            with patch('csv.DictWriter') as mock_writer:
                mock_writer_instance = MagicMock()
                mock_writer.return_value = mock_writer_instance
                
                result = self.export_service.export_to_csv(
                    data=large_data,
                    filename='large_export.csv'
                )
                
                # Verify large dataset was handled
                self.assertTrue(result['success'])
                self.assertEqual(result['rows_exported'], 10000)


class BatchProcessingTest(TestCase):
    """Test cases for batch processing functionality"""
    
    def setUp(self):
        """Set up test data"""
        self.batch_service = BatchProcessingService()
        
        self.branch = Branch.objects.create(
            name="Test Branch",
            code="TB001",
            is_active=True
        )
        
        self.user = User.objects.create_user(
            username="testuser",
            email="test@test.com",
            password="testpass123",
            role="loan_officer",
            branch=self.branch,
            phone_number="+254700000001"
        )
    
    def test_batch_export_processing(self):
        """Test batch export processing"""
        export_requests = [
            {
                'type': 'pdf',
                'template': 'portfolio_report',
                'data': {'manager_id': self.user.id},
                'filename': 'portfolio_report.pdf'
            },
            {
                'type': 'excel',
                'template': 'client_list',
                'data': {'branch_id': self.branch.id},
                'filename': 'client_list.xlsx'
            },
            {
                'type': 'csv',
                'template': 'loan_summary',
                'data': {'date_range': '2024-01-01,2024-01-31'},
                'filename': 'loan_summary.csv'
            }
        ]
        
        # Mock individual export processing
        with patch.object(self.batch_service, '_process_single_export') as mock_process:
            mock_process.return_value = {
                'success': True,
                'file_path': '/tmp/test_file',
                'file_size': 1024
            }
            
            result = self.batch_service.process_batch_exports(export_requests)
            
            # Verify batch processing
            self.assertTrue(result['success'])
            self.assertEqual(result['total_requests'], 3)
            self.assertEqual(result['completed'], 3)
            self.assertEqual(result['failed'], 0)
            self.assertEqual(mock_process.call_count, 3)
    
    def test_batch_processing_with_failures(self):
        """Test batch processing with some failures"""
        export_requests = [
            {'type': 'pdf', 'template': 'valid_template', 'data': {}},
            {'type': 'excel', 'template': 'invalid_template', 'data': {}},
            {'type': 'csv', 'template': 'valid_template', 'data': {}}
        ]
        
        # Mock mixed success/failure results
        def mock_process_side_effect(request):
            if request['template'] == 'invalid_template':
                return {'success': False, 'error': 'Template not found'}
            return {'success': True, 'file_path': '/tmp/test_file'}
        
        with patch.object(self.batch_service, '_process_single_export') as mock_process:
            mock_process.side_effect = mock_process_side_effect
            
            result = self.batch_service.process_batch_exports(export_requests)
            
            # Verify partial success
            self.assertTrue(result['success'])  # Overall success if any completed
            self.assertEqual(result['completed'], 2)
            self.assertEqual(result['failed'], 1)
            self.assertIn('failed_requests', result)
    
    def test_progress_tracking(self):
        """Test progress tracking during batch processing"""
        export_requests = [{'type': 'pdf', 'data': {}} for _ in range(5)]
        
        progress_updates = []
        
        def mock_progress_callback(current, total, status):
            progress_updates.append({'current': current, 'total': total, 'status': status})
        
        with patch.object(self.batch_service, '_process_single_export') as mock_process:
            mock_process.return_value = {'success': True, 'file_path': '/tmp/test'}
            
            result = self.batch_service.process_batch_exports(
                export_requests,
                progress_callback=mock_progress_callback
            )
            
            # Verify progress tracking
            self.assertTrue(result['success'])
            self.assertEqual(len(progress_updates), 5)
            self.assertEqual(progress_updates[-1]['current'], 5)
            self.assertEqual(progress_updates[-1]['total'], 5)
    
    def test_report_scheduling(self):
        """Test report scheduling functionality"""
        schedule_config = {
            'name': 'Weekly Portfolio Report',
            'report_type': 'portfolio_summary',
            'frequency': 'weekly',
            'day_of_week': 1,  # Monday
            'time': '09:00',
            'recipients': ['manager@test.com', 'admin@test.com'],
            'parameters': {
                'branch_id': self.branch.id,
                'include_charts': True,
                'format': 'pdf'
            }
        }
        
        # Mock scheduling system
        with patch.object(self.batch_service, '_create_scheduled_task') as mock_schedule:
            mock_schedule.return_value = {
                'success': True,
                'schedule_id': 'schedule_123',
                'next_run': timezone.now() + timedelta(days=7)
            }
            
            result = self.batch_service.schedule_report(schedule_config)
            
            # Verify scheduling
            self.assertTrue(result['success'])
            self.assertIn('schedule_id', result)
            self.assertIn('next_run', result)
    
    def test_email_delivery(self):
        """Test email delivery of generated reports"""
        report_files = [
            {'path': '/tmp/report1.pdf', 'name': 'Portfolio Report.pdf'},
            {'path': '/tmp/report2.xlsx', 'name': 'Client List.xlsx'}
        ]
        
        email_config = {
            'recipients': ['test@example.com'],
            'subject': 'Scheduled Reports',
            'body': 'Please find attached reports.',
            'sender': 'system@test.com'
        }
        
        # Mock email sending
        with patch.object(self.batch_service, '_send_email_with_attachments') as mock_email:
            mock_email.return_value = {
                'success': True,
                'message_id': 'msg_123',
                'recipients_sent': 1
            }
            
            result = self.batch_service.send_reports_by_email(report_files, email_config)
            
            # Verify email delivery
            self.assertTrue(result['success'])
            self.assertEqual(result['recipients_sent'], 1)
            mock_email.assert_called_once()


class ChartGenerationTest(TestCase):
    """Test cases for chart generation functionality"""
    
    def setUp(self):
        """Set up test data"""
        self.chart_service = ChartGenerationService()
    
    def test_bar_chart_generation(self):
        """Test bar chart generation"""
        chart_data = {
            'type': 'bar',
            'title': 'Monthly Loan Disbursements',
            'x_label': 'Month',
            'y_label': 'Amount (KES)',
            'data': {
                'labels': ['Jan', 'Feb', 'Mar', 'Apr'],
                'values': [100000, 150000, 120000, 180000]
            }
        }
        
        with patch('reports.chart_generation_service.matplotlib.pyplot') as mock_plt:
            mock_fig = MagicMock()
            mock_plt.figure.return_value = mock_fig
            
            result = self.chart_service.generate_chart(chart_data, '/tmp/chart.png')
            
            # Verify chart generation
            self.assertTrue(result['success'])
            self.assertIn('file_path', result)
            mock_plt.bar.assert_called_once()
            mock_plt.title.assert_called_once_with('Monthly Loan Disbursements')
    
    def test_line_chart_generation(self):
        """Test line chart generation"""
        chart_data = {
            'type': 'line',
            'title': 'Portfolio Growth Trend',
            'data': {
                'labels': ['Q1', 'Q2', 'Q3', 'Q4'],
                'datasets': [
                    {
                        'label': 'Clients',
                        'values': [100, 120, 140, 160],
                        'color': '#007bff'
                    },
                    {
                        'label': 'Loans',
                        'values': [80, 95, 110, 130],
                        'color': '#28a745'
                    }
                ]
            }
        }
        
        with patch('reports.chart_generation_service.matplotlib.pyplot') as mock_plt:
            result = self.chart_service.generate_chart(chart_data, '/tmp/line_chart.png')
            
            # Verify line chart generation
            self.assertTrue(result['success'])
            # Verify multiple lines were plotted
            self.assertEqual(mock_plt.plot.call_count, 2)
    
    def test_pie_chart_generation(self):
        """Test pie chart generation"""
        chart_data = {
            'type': 'pie',
            'title': 'Loan Status Distribution',
            'data': {
                'labels': ['Active', 'Completed', 'Defaulted'],
                'values': [60, 35, 5],
                'colors': ['#28a745', '#007bff', '#dc3545']
            }
        }
        
        with patch('reports.chart_generation_service.matplotlib.pyplot') as mock_plt:
            result = self.chart_service.generate_chart(chart_data, '/tmp/pie_chart.png')
            
            # Verify pie chart generation
            self.assertTrue(result['success'])
            mock_plt.pie.assert_called_once()
    
    def test_chart_customization(self):
        """Test chart customization options"""
        chart_data = {
            'type': 'bar',
            'title': 'Custom Chart',
            'data': {'labels': ['A', 'B'], 'values': [10, 20]},
            'customization': {
                'figure_size': (12, 8),
                'title_font_size': 16,
                'grid': True,
                'legend': True,
                'colors': ['#ff6b6b', '#4ecdc4']
            }
        }
        
        with patch('reports.chart_generation_service.matplotlib.pyplot') as mock_plt:
            mock_fig = MagicMock()
            mock_plt.figure.return_value = mock_fig
            
            result = self.chart_service.generate_chart(chart_data, '/tmp/custom_chart.png')
            
            # Verify customization was applied
            self.assertTrue(result['success'])
            mock_plt.figure.assert_called_with(figsize=(12, 8))
            mock_plt.grid.assert_called_with(True)
    
    def test_chart_error_handling(self):
        """Test chart generation error handling"""
        invalid_chart_data = {
            'type': 'invalid_type',
            'data': {}
        }
        
        result = self.chart_service.generate_chart(invalid_chart_data, '/tmp/error_chart.png')
        
        # Verify error handling
        self.assertFalse(result['success'])
        self.assertIn('error', result)


class DataIntegrityValidationTest(TestCase):
    """Test cases for data integrity validation"""
    
    def setUp(self):
        """Set up test data"""
        self.export_service = ExportService()
    
    def test_data_type_validation(self):
        """Test data type validation during export"""
        test_data = [
            {
                'id': 1,
                'name': 'John Doe',
                'amount': Decimal('1000.50'),
                'date': timezone.now().date(),
                'is_active': True
            },
            {
                'id': 'invalid_id',  # Invalid type
                'name': None,        # Invalid type
                'amount': 'not_a_number',  # Invalid type
                'date': 'invalid_date',    # Invalid type
                'is_active': 'yes'         # Invalid type
            }
        ]
        
        # Validate data types
        validation_result = self.export_service.validate_data_types(test_data)
        
        # Verify validation results
        self.assertFalse(validation_result['is_valid'])
        self.assertTrue(len(validation_result['errors']) > 0)
        self.assertIn('type_errors', validation_result)
    
    def test_data_completeness_validation(self):
        """Test data completeness validation"""
        incomplete_data = [
            {'id': 1, 'name': 'John Doe', 'amount': 1000},
            {'id': 2, 'name': '', 'amount': None},  # Missing required fields
            {'id': None, 'name': 'Jane Smith'}      # Missing required fields
        ]
        
        required_fields = ['id', 'name', 'amount']
        
        validation_result = self.export_service.validate_completeness(
            incomplete_data, required_fields
        )
        
        # Verify completeness validation
        self.assertFalse(validation_result['is_complete'])
        self.assertEqual(validation_result['incomplete_records'], 2)
        self.assertIn('missing_fields', validation_result)
    
    def test_data_consistency_validation(self):
        """Test data consistency validation"""
        inconsistent_data = [
            {'total': 100, 'part1': 60, 'part2': 40},  # Consistent
            {'total': 100, 'part1': 70, 'part2': 40},  # Inconsistent (110 != 100)
            {'total': 200, 'part1': 120, 'part2': 80}  # Consistent
        ]
        
        consistency_rules = [
            {
                'rule': 'sum_equals',
                'target_field': 'total',
                'source_fields': ['part1', 'part2']
            }
        ]
        
        validation_result = self.export_service.validate_consistency(
            inconsistent_data, consistency_rules
        )
        
        # Verify consistency validation
        self.assertFalse(validation_result['is_consistent'])
        self.assertEqual(validation_result['inconsistent_records'], 1)
    
    def test_export_data_integrity_check(self):
        """Test comprehensive data integrity check during export"""
        test_data = [
            {
                'client_id': 1,
                'loan_amount': Decimal('10000.00'),
                'interest_amount': Decimal('1000.00'),
                'total_amount': Decimal('11000.00'),
                'status': 'active'
            },
            {
                'client_id': 2,
                'loan_amount': Decimal('5000.00'),
                'interest_amount': Decimal('500.00'),
                'total_amount': Decimal('5600.00'),  # Inconsistent total
                'status': 'completed'
            }
        ]
        
        integrity_rules = {
            'required_fields': ['client_id', 'loan_amount', 'total_amount'],
            'data_types': {
                'client_id': int,
                'loan_amount': Decimal,
                'total_amount': Decimal
            },
            'consistency_checks': [
                {
                    'rule': 'sum_equals',
                    'target_field': 'total_amount',
                    'source_fields': ['loan_amount', 'interest_amount']
                }
            ]
        }
        
        # Perform comprehensive integrity check
        integrity_result = self.export_service.check_data_integrity(test_data, integrity_rules)
        
        # Verify integrity check results
        self.assertIn('overall_status', integrity_result)
        self.assertIn('type_validation', integrity_result)
        self.assertIn('completeness_validation', integrity_result)
        self.assertIn('consistency_validation', integrity_result)
        
        # Should detect the inconsistent total in second record
        self.assertFalse(integrity_result['consistency_validation']['is_consistent'])
    
    def test_checksum_generation(self):
        """Test checksum generation for exported data"""
        test_data = [
            {'id': 1, 'name': 'John', 'amount': 1000},
            {'id': 2, 'name': 'Jane', 'amount': 2000}
        ]
        
        # Generate checksum
        checksum1 = self.export_service.generate_data_checksum(test_data)
        
        # Generate checksum for same data
        checksum2 = self.export_service.generate_data_checksum(test_data)
        
        # Checksums should be identical for same data
        self.assertEqual(checksum1, checksum2)
        
        # Modify data and generate new checksum
        modified_data = test_data.copy()
        modified_data[0]['amount'] = 1500
        checksum3 = self.export_service.generate_data_checksum(modified_data)
        
        # Checksum should be different for modified data
        self.assertNotEqual(checksum1, checksum3)
    
    def test_export_audit_trail(self):
        """Test audit trail generation for exports"""
        export_metadata = {
            'user_id': 1,
            'export_type': 'excel',
            'filename': 'test_export.xlsx',
            'record_count': 100,
            'timestamp': timezone.now(),
            'filters_applied': {'status': 'active'},
            'checksum': 'abc123def456'
        }
        
        # Create audit trail entry
        audit_entry = self.export_service.create_export_audit_entry(export_metadata)
        
        # Verify audit entry
        self.assertIsNotNone(audit_entry)
        self.assertIn('export_id', audit_entry)
        self.assertIn('timestamp', audit_entry)
        self.assertEqual(audit_entry['record_count'], 100)
        self.assertEqual(audit_entry['checksum'], 'abc123def456')