"""
Survey analytics API views.

Provides endpoints for accessing survey engagement metrics:
- Engagement statistics
- Patient survey timelines
- Completion times
- Abandonment analysis
- Hourly activity
"""
import json
import os
from datetime import datetime
from django.conf import settings
from rest_framework import status, viewsets
from rest_framework.decorators import action
from rest_framework.response import Response
from rest_framework.permissions import IsAuthenticated
from django.http import FileResponse, HttpResponse

from .analytics import (
    get_survey_engagement_stats,
    get_patient_survey_timeline,
    get_survey_completion_times,
    get_survey_abandonment_analysis,
    get_hourly_survey_activity,
)
from .analytics_utils import (
    calculate_survey_analytics,
    generate_markdown_report,
    generate_html_report,
    generate_enhanced_survey_reports,
    generate_single_template_report,
)
from .models import SurveyInstance, SurveyTracking
from .serializers import SurveyInstanceSerializer, SurveyTrackingSerializer


class SurveyAnalyticsViewSet(viewsets.ViewSet):
    """
    Survey analytics API.
    
    Provides various metrics about survey engagement:
    - Engagement rates (open, completion, abandonment)
    - Time metrics (time to complete, time spent)
    - Patient timelines
    - Abandonment patterns
    - Hourly activity
    """
    permission_classes = [IsAuthenticated]
    
    @action(detail=False, methods=['get'])
    def engagement_stats(self, request):
        """
        Get overall survey engagement statistics.
        
        Query params:
        - survey_template_id: Filter by survey template (optional)
        - hospital_id: Filter by hospital (optional)
        - days: Number of days to look back (default: 30)
        """
        survey_template_id = request.query_params.get('survey_template_id')
        hospital_id = request.query_params.get('hospital_id')
        days = int(request.query_params.get('days', 30))
        
        try:
            stats = get_survey_engagement_stats(
                survey_template_id=survey_template_id,
                hospital_id=hospital_id,
                days=days
            )
            return Response(stats)
        except Exception as e:
            return Response(
                {'error': str(e)},
                status=status.HTTP_400_BAD_REQUEST
            )
    
    @action(detail=False, methods=['get'])
    def patient_timeline(self, request):
        """
        Get survey timeline for a specific patient.
        
        Query params:
        - patient_id: Required - Patient ID
        """
        patient_id = request.query_params.get('patient_id')
        
        if not patient_id:
            return Response(
                {'error': 'patient_id is required'},
                status=status.HTTP_400_BAD_REQUEST
            )
        
        try:
            timeline = get_patient_survey_timeline(patient_id)
            return Response({'timeline': timeline})
        except Exception as e:
            return Response(
                {'error': str(e)},
                status=status.HTTP_400_BAD_REQUEST
            )
    
    @action(detail=False, methods=['get'])
    def completion_times(self, request):
        """
        Get individual survey completion times.
        
        Query params:
        - survey_template_id: Filter by survey template (optional)
        - hospital_id: Filter by hospital (optional)
        - days: Number of days to look back (default: 30)
        """
        survey_template_id = request.query_params.get('survey_template_id')
        hospital_id = request.query_params.get('hospital_id')
        days = int(request.query_params.get('days', 30))
        
        try:
            completion_times = get_survey_completion_times(
                survey_template_id=survey_template_id,
                hospital_id=hospital_id,
                days=days
            )
            return Response({'completion_times': completion_times})
        except Exception as e:
            return Response(
                {'error': str(e)},
                status=status.HTTP_400_BAD_REQUEST
            )
    
    @action(detail=False, methods=['get'])
    def abandonment_analysis(self, request):
        """
        Analyze abandoned surveys to identify patterns.
        
        Query params:
        - survey_template_id: Filter by survey template (optional)
        - hospital_id: Filter by hospital (optional)
        - days: Number of days to look back (default: 30)
        """
        survey_template_id = request.query_params.get('survey_template_id')
        hospital_id = request.query_params.get('hospital_id')
        days = int(request.query_params.get('days', 30))
        
        try:
            analysis = get_survey_abandonment_analysis(
                survey_template_id=survey_template_id,
                hospital_id=hospital_id,
                days=days
            )
            return Response(analysis)
        except Exception as e:
            return Response(
                {'error': str(e)},
                status=status.HTTP_400_BAD_REQUEST
            )
    
    @action(detail=False, methods=['get'])
    def hourly_activity(self, request):
        """
        Get survey activity by hour.
        
        Query params:
        - hospital_id: Filter by hospital (optional)
        - days: Number of days to look back (default: 7)
        """
        hospital_id = request.query_params.get('hospital_id')
        days = int(request.query_params.get('days', 7))
        
        try:
            activity = get_hourly_survey_activity(
                hospital_id=hospital_id,
                days=days
            )
            return Response({'activity': activity})
        except Exception as e:
            return Response(
                {'error': str(e)},
                status=status.HTTP_400_BAD_REQUEST
            )
    
    @action(detail=False, methods=['get'])
    def summary_dashboard(self, request):
        """
        Get a comprehensive summary dashboard with all key metrics.
        
        Query params:
        - hospital_id: Filter by hospital (optional)
        - days: Number of days to look back (default: 30)
        """
        hospital_id = request.query_params.get('hospital_id')
        days = int(request.query_params.get('days', 30))
        
        try:
            # Get engagement stats
            engagement = get_survey_engagement_stats(
                hospital_id=hospital_id,
                days=days
            )
            
            # Get abandonment analysis
            abandonment = get_survey_abandonment_analysis(
                hospital_id=hospital_id,
                days=days
            )
            
            # Get top 10 fastest completions
            fastest_completions = get_survey_completion_times(
                hospital_id=hospital_id,
                days=days
            )[:10]
            
            # Get top 10 slowest completions
            slowest_completions = get_survey_completion_times(
                hospital_id=hospital_id,
                days=days
            )[-10:] if len(get_survey_completion_times(hospital_id=hospital_id, days=days)) > 10 else []
            
            return Response({
                'engagement': engagement,
                'abandonment': abandonment,
                'fastest_completions': fastest_completions,
                'slowest_completions': slowest_completions,
            })
        except Exception as e:
            return Response(
                {'error': str(e)},
                status=status.HTTP_400_BAD_REQUEST
            )
    
    @action(detail=False, methods=['post'])
    def generate_report(self, request):
        """
        Generate comprehensive survey analytics report.
        
        Request body (JSON):
        {
            "template": "Survey template name (optional)",
            "start_date": "YYYY-MM-DD (optional)",
            "end_date": "YYYY-MM-DD (optional)",
            "format": "json|html|markdown (optional, default: json)",
            "save": true/false (optional, default: false)
        }
        
        Returns:
        - If format=json: Returns analytics data as JSON
        - If format=html: Returns HTML content
        - If format=markdown: Returns Markdown content
        - If save=true: Also saves to file and returns file path
        """
        try:
            data = request.data
            template = data.get('template')
            start_date = data.get('start_date')
            end_date = data.get('end_date')
            report_format = data.get('format', 'json')
            save_to_file = data.get('save', False)
            
            # Parse dates if provided
            start_dt = None
            end_dt = None
            if start_date:
                start_dt = datetime.strptime(start_date, '%Y-%m-%d').date()
            if end_date:
                end_dt = datetime.strptime(end_date, '%Y-%m-%d').date()
            
            # Generate analytics data
            analytics_data = calculate_survey_analytics(
                template_name=template,
                start_date=start_dt,
                end_date=end_dt
            )
            
            # Format output
            if report_format == 'json':
                response_data = {
                    'success': True,
                    'data': analytics_data
                }
                
                if save_to_file:
                    # Save to JSON file
                    output_dir = getattr(settings, 'SURVEY_REPORTS_DIR', 'reports')
                    os.makedirs(output_dir, exist_ok=True)
                    filepath = os.path.join(output_dir, f'survey_analytics_data_{datetime.now().strftime("%Y%m%d_%H%M%S")}.json')
                    with open(filepath, 'w', encoding='utf-8') as f:
                        json.dump(analytics_data, f, indent=2, default=str)
                    response_data['saved_to'] = filepath
                
                return Response(response_data)
            
            elif report_format == 'html':
                # Generate HTML report
                html_content = generate_html_report(analytics_data)
                
                response_data = {
                    'success': True,
                    'content': html_content
                }
                
                if save_to_file:
                    # Save to HTML file
                    output_dir = getattr(settings, 'SURVEY_REPORTS_DIR', 'reports')
                    os.makedirs(output_dir, exist_ok=True)
                    filepath = os.path.join(output_dir, f'survey_analytics_report_{datetime.now().strftime("%Y%m%d_%H%M%S")}.html')
                    with open(filepath, 'w', encoding='utf-8') as f:
                        f.write(html_content)
                    response_data['saved_to'] = filepath
                
                return Response(response_data)
            
            elif report_format == 'markdown':
                # Generate Markdown report
                markdown_content = generate_markdown_report(analytics_data)
                
                response_data = {
                    'success': True,
                    'content': markdown_content
                }
                
                if save_to_file:
                    # Save to Markdown file
                    output_dir = getattr(settings, 'SURVEY_REPORTS_DIR', 'reports')
                    os.makedirs(output_dir, exist_ok=True)
                    filepath = os.path.join(output_dir, f'survey_analytics_report_{datetime.now().strftime("%Y%m%d_%H%M%S")}.md')
                    with open(filepath, 'w', encoding='utf-8') as f:
                        f.write(markdown_content)
                    response_data['saved_to'] = filepath
                
                return Response(response_data)
            
            else:
                return Response(
                    {'error': f'Invalid format: {report_format}. Use json, html, or markdown.'},
                    status=status.HTTP_400_BAD_REQUEST
                )
        
        except Exception as e:
            import traceback
            traceback.print_exc()
            return Response(
                {'error': str(e)},
                status=status.HTTP_400_BAD_REQUEST
            )
    
    @action(detail=False, methods=['get'])
    def available_reports(self, request):
        """
        List available survey analytics reports.
        
        Returns list of JSON, HTML, and Markdown reports in the reports directory.
        """
        try:
            output_dir = getattr(settings, 'SURVEY_REPORTS_DIR', 'reports')
            
            if not os.path.exists(output_dir):
                return Response({
                    'success': True,
                    'reports': []
                })
            
            reports = []
            for filename in os.listdir(output_dir):
                filepath = os.path.join(output_dir, filename)
                if os.path.isfile(filepath):
                    stat = os.stat(filepath)
                    report_type = 'unknown'
                    if filename.endswith('.json'):
                        report_type = 'json'
                    elif filename.endswith('.html'):
                        report_type = 'html'
                    elif filename.endswith('.md'):
                        report_type = 'markdown'
                    
                    reports.append({
                        'filename': filename,
                        'type': report_type,
                        'size': stat.st_size,
                        'created': datetime.fromtimestamp(stat.st_ctime).isoformat(),
                        'modified': datetime.fromtimestamp(stat.st_mtime).isoformat(),
                    })
            
            # Sort by creation date (newest first)
            reports.sort(key=lambda x: x['created'], reverse=True)
            
            return Response({
                'success': True,
                'reports': reports
            })
        
        except Exception as e:
            return Response(
                {'error': str(e)},
                status=status.HTTP_400_BAD_REQUEST
            )
    
    @action(detail=False, methods=['post'])
    def generate_enhanced_reports(self, request):
        """
        Generate enhanced survey analytics reports - one per survey template.
        
        Creates separate HTML reports for each survey template with:
        - Detailed question-level analysis
        - Individual charts per question
        - Performance insights and recommendations
        - Master index page linking all reports
        
        Request body (JSON):
        {
            "template": "Survey template name (optional - if not provided, generates for all)",
            "start_date": "YYYY-MM-DD (optional)",
            "end_date": "YYYY-MM-DD (optional)"
        }
        
        Returns:
        {
            "success": true,
            "reports_dir": "/path/to/reports/reports_20240208_123045",
            "index_url": "/surveys/reports/reports_20240208_123045/index.html",
            "reports": [
                {
                    "template_name": "Inpatient Satisfaction",
                    "filename": "inpatient_satisfaction.html",
                    "size": 15234
                }
            ]
        }
        """
        try:
            data = request.data
            template = data.get('template')
            start_date = data.get('start_date')
            end_date = data.get('end_date')
            
            # Parse dates if provided
            start_dt = None
            end_dt = None
            if start_date:
                start_dt = datetime.strptime(start_date, '%Y-%m-%d').date()
            if end_date:
                end_dt = datetime.strptime(end_date, '%Y-%m-%d').date()
            
            # Generate enhanced reports
            result = generate_enhanced_survey_reports(
                template_name=template,
                start_date=start_dt,
                end_date=end_dt
            )
            
            # Build URLs for accessing reports
            import os
            from django.conf import settings
            
            reports_dir_name = os.path.basename(result['reports_dir'])
            
            return Response({
                'success': True,
                'message': f"Generated {len(result['individual_reports'])} reports",
                'reports_dir': result['reports_dir'],
                'index_path': result['index_path'],
                'summary_path': result['summary_path'],
                'reports': result['individual_reports'],
                'view_url': f"/surveys/enhanced-reports/{reports_dir_name}/"
            })
            
        except Exception as e:
            import traceback
            traceback.print_exc()
            return Response(
                {'error': str(e)},
                status=status.HTTP_400_BAD_REQUEST
            )


class SurveyTrackingViewSet(viewsets.ReadOnlyModelViewSet):
    """
    Survey tracking events API.
    
    View detailed tracking events for surveys:
    - Page views
    - Completions
    - Abandonments
    - Device/browser information
    """
    queryset = SurveyTracking.objects.select_related(
        'survey_instance',
        'survey_instance__patient',
        'survey_instance__survey_template'
    ).order_by('-created_at')
    serializer_class = SurveyTrackingSerializer
    permission_classes = [IsAuthenticated]
    filterset_fields = ['survey_instance', 'event_type', 'device_type', 'browser']
    search_fields = ['ip_address', 'user_agent']
    
    @action(detail=False, methods=['get'])
    def by_survey(self, request):
        """
        Get tracking events for a specific survey instance.
        
        Query params:
        - survey_instance_id: Required - SurveyInstance ID
        """
        survey_instance_id = request.query_params.get('survey_instance_id')
        
        if not survey_instance_id:
            return Response(
                {'error': 'survey_instance_id is required'},
                status=status.HTTP_400_BAD_REQUEST
            )
        
        try:
            tracking_events = self.queryset.filter(
                survey_instance_id=survey_instance_id
            )
            
            # Serialize and return
            serializer = self.get_serializer(tracking_events, many=True)
            return Response(serializer.data)
        except Exception as e:
            return Response(
                {'error': str(e)},
                status=status.HTTP_400_BAD_REQUEST
            )
