"""
Client Analytics Dashboard Views

Views for displaying client growth analytics, demographic analysis,
lifecycle analytics, and loan officer performance dashboards.
"""

from django.shortcuts import render, get_object_or_404
from django.contrib.auth.decorators import login_required
from django.http import JsonResponse, HttpResponse
from django.views.decorators.http import require_http_methods
from django.contrib import messages
from django.utils import timezone
from django.db.models import Q, Sum
from django.shortcuts import redirect
from datetime import datetime, timedelta
import json

from users.models import CustomUser, Branch
from users.client_growth_analytics import ClientGrowthAnalytics
from users.decorators import role_required


@login_required
@role_required(['admin', 'team_leader', 'auditor'])
def client_analytics_dashboard(request):
    """
    Main client analytics dashboard view
    """
    analytics_service = ClientGrowthAnalytics()
    
    # Get filter parameters
    branch_id = request.GET.get('branch_id')
    period = request.GET.get('period', 'monthly')
    months = int(request.GET.get('months', 12))
    
    # Get acquisition trends
    acquisition_data = analytics_service.get_acquisition_trends(
        branch_id=branch_id,
        period=period,
        months=months
    )
    
    # Get demographic analysis
    demographic_filters = {}
    if branch_id:
        demographic_filters['branch_id'] = branch_id
    
    demographic_data = analytics_service.get_demographic_analysis(
        filters=demographic_filters
    )
    
    # Get lifecycle analytics for active clients
    lifecycle_data = analytics_service.get_lifecycle_analytics(
        client_segment='active'
    )
    
    # Get branches for filter dropdown
    branches = Branch.objects.filter(is_active=True).order_by('name')
    
    context = {
        'acquisition_data': acquisition_data,
        'demographic_data': demographic_data,
        'lifecycle_data': lifecycle_data,
        'branches': branches,
        'selected_branch': branch_id,
        'selected_period': period,
        'selected_months': months,
        'page_title': 'Client Analytics Dashboard',
        'dashboard_type': 'client_analytics'
    }
    
    return render(request, 'users/client_analytics_dashboard.html', context)


@login_required
@role_required(['admin', 'team_leader', 'auditor'])
def acquisition_trends_api(request):
    """
    API endpoint for acquisition trends data
    """
    analytics_service = ClientGrowthAnalytics()
    
    branch_id = request.GET.get('branch_id')
    period = request.GET.get('period', 'monthly')
    months = int(request.GET.get('months', 12))
    
    try:
        data = analytics_service.get_acquisition_trends(
            branch_id=branch_id,
            period=period,
            months=months
        )
        return JsonResponse(data)
    except Exception as e:
        return JsonResponse({'error': str(e)}, status=500)


@login_required
@role_required(['admin', 'team_leader', 'auditor'])
def demographic_analysis_api(request):
    """
    API endpoint for demographic analysis data
    """
    analytics_service = ClientGrowthAnalytics()
    
    # Build filters from request parameters
    filters = {}
    if request.GET.get('branch_id'):
        filters['branch_id'] = request.GET.get('branch_id')
    if request.GET.get('status'):
        filters['status'] = request.GET.get('status')
    if request.GET.get('start_date') and request.GET.get('end_date'):
        filters['date_range'] = {
            'start': datetime.strptime(request.GET.get('start_date'), '%Y-%m-%d').date(),
            'end': datetime.strptime(request.GET.get('end_date'), '%Y-%m-%d').date()
        }
    
    try:
        data = analytics_service.get_demographic_analysis(filters=filters)
        return JsonResponse(data)
    except Exception as e:
        return JsonResponse({'error': str(e)}, status=500)


@login_required
@role_required(['admin', 'team_leader', 'auditor'])
def lifecycle_analytics_api(request):
    """
    API endpoint for lifecycle analytics data
    """
    analytics_service = ClientGrowthAnalytics()
    
    client_segment = request.GET.get('segment', 'active')
    
    try:
        data = analytics_service.get_lifecycle_analytics(client_segment=client_segment)
        return JsonResponse(data)
    except Exception as e:
        return JsonResponse({'error': str(e)}, status=500)


@login_required
@role_required(['admin', 'team_leader', 'auditor'])
def officer_performance_dashboard(request):
    """
    Loan officer performance comparison dashboard
    """
    analytics_service = ClientGrowthAnalytics()
    
    # Get filter parameters
    officer_id = request.GET.get('officer_id')
    period = request.GET.get('period', 'monthly')
    months = int(request.GET.get('months', 6))
    
    # Get officer performance data
    performance_data = analytics_service.get_officer_performance(
        officer_id=officer_id,
        period=period,
        months=months
    )
    
    # Get all loan officers for filter dropdown
    officers = CustomUser.objects.filter(
        role__in=['loan_officer', 'team_leader'],
        is_active=True
    ).order_by('first_name', 'last_name')
    
    context = {
        'performance_data': performance_data,
        'officers': officers,
        'selected_officer': officer_id,
        'selected_period': period,
        'selected_months': months,
        'page_title': 'Loan Officer Performance Dashboard',
        'dashboard_type': 'officer_performance'
    }
    
    return render(request, 'users/officer_performance_dashboard.html', context)


@login_required
@role_required(['admin', 'team_leader', 'auditor'])
def officer_performance_api(request):
    """
    API endpoint for officer performance data
    """
    analytics_service = ClientGrowthAnalytics()
    
    officer_id = request.GET.get('officer_id')
    period = request.GET.get('period', 'monthly')
    months = int(request.GET.get('months', 6))
    
    try:
        data = analytics_service.get_officer_performance(
            officer_id=officer_id,
            period=period,
            months=months
        )
        return JsonResponse(data)
    except Exception as e:
        return JsonResponse({'error': str(e)}, status=500)


@login_required
@role_required(['admin', 'team_leader', 'loan_officer'])
def client_journey_mapping(request, client_id):
    """
    Individual client journey mapping view
    """
    client = get_object_or_404(CustomUser, id=client_id, role='borrower')
    
    # Check if user can view this client
    if request.user.role == 'loan_officer' and client.portfolio_manager != request.user:
        messages.error(request, "You don't have permission to view this client's journey.")
        return redirect('users:client_list')
    
    # Get client's journey data
    from loans.models import Loan, LoanApplication
    from django.db import models
    
    # Timeline events
    timeline_events = []
    
    # Registration
    timeline_events.append({
        'date': client.created_at,
        'event': 'Client Registration',
        'description': f'Client registered in the system',
        'type': 'registration',
        'icon': 'fa-user-plus'
    })
    
    # KYC completion
    if client.is_verified:
        timeline_events.append({
            'date': client.verification_date or client.created_at,
            'event': 'KYC Verification',
            'description': 'Client verification completed',
            'type': 'verification',
            'icon': 'fa-check-circle'
        })
    
    # Portfolio assignment
    if client.portfolio_manager and client.assigned_date:
        timeline_events.append({
            'date': client.assigned_date,
            'event': 'Portfolio Assignment',
            'description': f'Assigned to {client.portfolio_manager.get_full_name()}',
            'type': 'assignment',
            'icon': 'fa-user-tie'
        })
    
    # Loan applications
    applications = LoanApplication.objects.filter(borrower=client).order_by('created_at')
    for app in applications:
        timeline_events.append({
            'date': app.created_at,
            'event': 'Loan Application',
            'description': f'Applied for KES {app.amount:,.2f} loan',
            'type': 'application',
            'icon': 'fa-file-alt',
            'amount': app.amount,
            'status': app.status
        })
    
    # Loans
    loans = Loan.objects.filter(borrower=client).order_by('created_at')
    for loan in loans:
        timeline_events.append({
            'date': loan.created_at,
            'event': 'Loan Disbursement',
            'description': f'Loan of KES {loan.principal_amount:,.2f} disbursed',
            'type': 'disbursement',
            'icon': 'fa-money-bill-wave',
            'amount': loan.principal_amount,
            'loan_id': loan.id
        })
        
        if loan.status == 'paid':
            timeline_events.append({
                'date': loan.updated_at,
                'event': 'Loan Completion',
                'description': f'Loan fully repaid',
                'type': 'completion',
                'icon': 'fa-check-double',
                'loan_id': loan.id
            })
    
    # Sort timeline by date
    timeline_events.sort(key=lambda x: x['date'])
    
    # Calculate client metrics
    total_borrowed = loans.aggregate(total=models.Sum('principal_amount'))['total'] or 0
    total_paid = loans.aggregate(total=models.Sum('amount_paid'))['total'] or 0
    active_loans = loans.filter(status='active').count()
    completed_loans = loans.filter(status='paid').count()
    
    context = {
        'client': client,
        'timeline_events': timeline_events,
        'client_metrics': {
            'total_applications': applications.count(),
            'approved_applications': applications.filter(status='approved').count(),
            'total_loans': loans.count(),
            'active_loans': active_loans,
            'completed_loans': completed_loans,
            'total_borrowed': total_borrowed,
            'total_paid': total_paid,
            'days_as_client': (timezone.now().date() - client.created_at.date()).days
        },
        'page_title': f'Client Journey - {client.get_full_name()}',
        'dashboard_type': 'client_journey'
    }
    
    return render(request, 'users/client_journey_mapping.html', context)


@login_required
@role_required(['admin', 'team_leader', 'auditor'])
def export_analytics_data(request):
    """
    Export analytics data to Excel/CSV
    """
    analytics_service = ClientGrowthAnalytics()
    export_type = request.GET.get('type', 'acquisition')  # acquisition, demographic, lifecycle, officer
    format_type = request.GET.get('format', 'excel')  # excel, csv
    
    try:
        if export_type == 'acquisition':
            data = analytics_service.get_acquisition_trends(
                branch_id=request.GET.get('branch_id'),
                period=request.GET.get('period', 'monthly'),
                months=int(request.GET.get('months', 12))
            )
            filename = f'client_acquisition_trends_{timezone.now().strftime("%Y%m%d")}'
            
        elif export_type == 'demographic':
            filters = {}
            if request.GET.get('branch_id'):
                filters['branch_id'] = request.GET.get('branch_id')
            data = analytics_service.get_demographic_analysis(filters=filters)
            filename = f'client_demographics_{timezone.now().strftime("%Y%m%d")}'
            
        elif export_type == 'lifecycle':
            data = analytics_service.get_lifecycle_analytics(
                client_segment=request.GET.get('segment', 'active')
            )
            filename = f'client_lifecycle_{timezone.now().strftime("%Y%m%d")}'
            
        elif export_type == 'officer':
            data = analytics_service.get_officer_performance(
                officer_id=request.GET.get('officer_id'),
                period=request.GET.get('period', 'monthly'),
                months=int(request.GET.get('months', 6))
            )
            filename = f'officer_performance_{timezone.now().strftime("%Y%m%d")}'
        
        else:
            return JsonResponse({'error': 'Invalid export type'}, status=400)
        
        if format_type == 'excel':
            # Import pandas and create Excel export
            import pandas as pd
            from io import BytesIO
            
            output = BytesIO()
            
            with pd.ExcelWriter(output, engine='openpyxl') as writer:
                # Convert data to DataFrame and write to Excel
                if export_type == 'acquisition':
                    df = pd.DataFrame(data['trend_data'])
                    df.to_excel(writer, sheet_name='Acquisition Trends', index=False)
                    
                    summary_df = pd.DataFrame([data['summary']])
                    summary_df.to_excel(writer, sheet_name='Summary', index=False)
                    
                elif export_type == 'demographic':
                    # Create separate sheets for each demographic category
                    for category, category_data in data.items():
                        if isinstance(category_data, dict) and category != 'filters_applied':
                            df = pd.DataFrame([
                                {'Category': k, 'Count': v['count'], 'Percentage': v['percentage']}
                                for k, v in category_data.items()
                            ])
                            sheet_name = category.replace('_', ' ').title()[:31]  # Excel sheet name limit
                            df.to_excel(writer, sheet_name=sheet_name, index=False)
                
                elif export_type == 'officer':
                    # Officer performance data
                    df = pd.DataFrame(data['performance_data'])
                    df.to_excel(writer, sheet_name='Officer Performance', index=False)
            
            output.seek(0)
            
            response = HttpResponse(
                output.getvalue(),
                content_type='application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'
            )
            response['Content-Disposition'] = f'attachment; filename="{filename}.xlsx"'
            return response
            
        else:  # CSV format
            import csv
            from io import StringIO
            
            output = StringIO()
            
            if export_type == 'acquisition':
                writer = csv.DictWriter(output, fieldnames=data['trend_data'][0].keys() if data['trend_data'] else [])
                writer.writeheader()
                writer.writerows(data['trend_data'])
            
            response = HttpResponse(output.getvalue(), content_type='text/csv')
            response['Content-Disposition'] = f'attachment; filename="{filename}.csv"'
            return response
            
    except Exception as e:
        return JsonResponse({'error': f'Export failed: {str(e)}'}, status=500)