"""
API Views for Reports Dashboard
Provides JSON endpoints for dynamic data loading and chart generation
"""
from django.http import JsonResponse
from django.views.decorators.http import require_http_methods
from django.contrib.auth.decorators import login_required
from django.views.decorators.csrf import csrf_exempt
from django.utils.decorators import method_decorator
from django.views import View
from django.core.paginator import Paginator
from django.db.models import Q
import json
from datetime import datetime, timedelta
from .comprehensive_reports import reports_service
from .chart_service import chart_service


@method_decorator(login_required, name='dispatch')
class DashboardDataAPI(View):
    """
    Enhanced API endpoint for dynamic dashboard data loading
    """
    
    def get(self, request):
        try:
            # Get filter parameters
            period = request.GET.get('period', 'today')
            branch_id = request.session.get('selected_branch_id')
            report_type = request.GET.get('report_type', 'all')
            
            # Generate dashboard data based on parameters
            if report_type == 'all':
                dashboard_data = reports_service.generate_comprehensive_dashboard_data(branch_id=branch_id)
            elif report_type == 'loans_due':
                dashboard_data = {
                    'loans_due_today': reports_service.get_loans_due_report(today_only=True, branch_id=branch_id)
                }
            elif report_type == 'delinquent':
                dashboard_data = {
                    'delinquent_loans': reports_service.get_delinquent_loans_report(branch_id=branch_id)
                }
            elif report_type == 'processing_fees':
                dashboard_data = {
                    'processing_fees': reports_service.get_processing_fees_report(period='current_month', branch_id=branch_id)
                }
            elif report_type == 'interest_income':
                dashboard_data = {
                    'interest_income': reports_service.get_interest_income_report(branch_id=branch_id)
                }
            else:
                dashboard_data = reports_service.generate_comprehensive_dashboard_data(branch_id=branch_id)
            
            return JsonResponse({
                'success': True,
                'data': dashboard_data,
                'timestamp': datetime.now().isoformat()
            })
            
        except Exception as e:
            return JsonResponse({
                'success': False,
                'error': str(e),
                'timestamp': datetime.now().isoformat()
            }, status=500)


@method_decorator(login_required, name='dispatch')
class ReportFilterAPI(View):
    """
    API endpoint for filtering report data
    """
    
    def post(self, request):
        try:
            data = json.loads(request.body)
            report_type = data.get('report_type')
            filters = data.get('filters', {})
            branch_id = request.session.get('selected_branch_id')
            
            # Apply filters based on report type
            if report_type == 'loans_due':
                start_date = filters.get('start_date')
                end_date = filters.get('end_date')
                today_only = filters.get('today_only', False)
                
                if start_date:
                    start_date = datetime.strptime(start_date, '%Y-%m-%d').date()
                if end_date:
                    end_date = datetime.strptime(end_date, '%Y-%m-%d').date()
                
                report_data = reports_service.get_loans_due_report(
                    start_date=start_date,
                    end_date=end_date,
                    today_only=today_only,
                    branch_id=branch_id
                )
                
            elif report_type == 'delinquent_loans':
                days_filter = filters.get('days_filter')
                report_data = reports_service.get_delinquent_loans_report(
                    days_overdue_filter=days_filter,
                    branch_id=branch_id
                )
                
            elif report_type == 'loans_in_arrears':
                arrears_filter = filters.get('arrears_filter')
                report_data = reports_service.get_loans_in_arrears_report(
                    arrears_amount_filter=arrears_filter,
                    branch_id=branch_id
                )
                
            elif report_type == 'processing_fees':
                period = filters.get('period', 'current_month')
                start_date = filters.get('start_date')
                end_date = filters.get('end_date')
                
                if start_date:
                    start_date = datetime.strptime(start_date, '%Y-%m-%d').date()
                if end_date:
                    end_date = datetime.strptime(end_date, '%Y-%m-%d').date()
                
                report_data = reports_service.get_processing_fees_report(
                    start_date=start_date,
                    end_date=end_date,
                    period=period,
                    branch_id=branch_id
                )
                
            elif report_type == 'interest_income':
                period = filters.get('period', 'current_month')
                start_date = filters.get('start_date')
                end_date = filters.get('end_date')
                
                if start_date:
                    start_date = datetime.strptime(start_date, '%Y-%m-%d').date()
                if end_date:
                    end_date = datetime.strptime(end_date, '%Y-%m-%d').date()
                
                report_data = reports_service.get_interest_income_report(
                    start_date=start_date,
                    end_date=end_date,
                    period=period,
                    branch_id=branch_id
                )
                
            elif report_type == 'registration_fees':
                period = filters.get('period', 'current_month')
                start_date = filters.get('start_date')
                end_date = filters.get('end_date')
                
                if start_date:
                    start_date = datetime.strptime(start_date, '%Y-%m-%d').date()
                if end_date:
                    end_date = datetime.strptime(end_date, '%Y-%m-%d').date()
                
                report_data = reports_service.get_all_time_registration_fees_report(
                    start_date=start_date,
                    end_date=end_date,
                    period=period,
                    branch_id=branch_id
                )
                
            else:
                return JsonResponse({
                    'success': False,
                    'error': 'Invalid report type'
                }, status=400)
            
            return JsonResponse({
                'success': True,
                'data': report_data,
                'timestamp': datetime.now().isoformat()
            })
            
        except Exception as e:
            return JsonResponse({
                'success': False,
                'error': str(e),
                'timestamp': datetime.now().isoformat()
            }, status=500)


@method_decorator(login_required, name='dispatch')
class PaginatedDataAPI(View):
    """
    API endpoint for paginated data loading
    """
    
    def get(self, request):
        try:
            report_type = request.GET.get('report_type')
            page = int(request.GET.get('page', 1))
            per_page = int(request.GET.get('per_page', 25))
            branch_id = request.session.get('selected_branch_id')
            
            # Get the appropriate report data
            if report_type == 'loans_due':
                report_data = reports_service.get_loans_due_report(branch_id=branch_id)
                items = report_data['loans']
            elif report_type == 'delinquent_loans':
                report_data = reports_service.get_delinquent_loans_report(branch_id=branch_id)
                items = report_data['loans']
            elif report_type == 'loans_in_arrears':
                report_data = reports_service.get_loans_in_arrears_report(branch_id=branch_id)
                items = report_data['loans']
            else:
                return JsonResponse({
                    'success': False,
                    'error': 'Invalid report type'
                }, status=400)
            
            # Paginate the results
            paginator = Paginator(items, per_page)
            page_obj = paginator.get_page(page)
            
            return JsonResponse({
                'success': True,
                'data': {
                    'items': list(page_obj),
                    'pagination': {
                        'current_page': page_obj.number,
                        'total_pages': paginator.num_pages,
                        'total_items': paginator.count,
                        'has_next': page_obj.has_next(),
                        'has_previous': page_obj.has_previous(),
                        'per_page': per_page
                    }
                },
                'timestamp': datetime.now().isoformat()
            })
            
        except Exception as e:
            return JsonResponse({
                'success': False,
                'error': str(e),
                'timestamp': datetime.now().isoformat()
            }, status=500)


@login_required
@require_http_methods(["GET"])
def real_time_refresh_api(request):
    """
    API endpoint for real-time data refresh
    """
    try:
        branch_id = request.session.get('selected_branch_id')
        
        # Get summary metrics for real-time updates
        dashboard_data = reports_service.generate_comprehensive_dashboard_data(branch_id=branch_id)
        
        # Extract key metrics for real-time display
        real_time_data = {
            'summary_metrics': dashboard_data.get('summary_metrics', {}),
            'loans_due_today_count': dashboard_data.get('loans_due_today', {}).get('summary', {}).get('today_due_count', 0),
            'delinquent_loans_count': dashboard_data.get('delinquent_loans', {}).get('summary', {}).get('total_delinquent_loans', 0),
            'processing_fees_today': dashboard_data.get('processing_fees_current_month', {}).get('summary', {}).get('total_processing_fees', 0),
            'interest_income_today': dashboard_data.get('interest_income_current_month', {}).get('summary', {}).get('total_interest_income', 0),
            'timestamp': datetime.now().isoformat()
        }
        
        return JsonResponse({
            'success': True,
            'data': real_time_data
        })
        
    except Exception as e:
        return JsonResponse({
            'success': False,
            'error': str(e)
        }, status=500)


@login_required
@require_http_methods(["GET"])
def search_api(request):
    """
    API endpoint for searching across reports
    """
    try:
        query = request.GET.get('q', '').strip()
        report_type = request.GET.get('report_type', 'all')
        branch_id = request.session.get('selected_branch_id')
        
        if not query:
            return JsonResponse({
                'success': False,
                'error': 'Search query is required'
            }, status=400)
        
        results = []
        
        # Search in loans due
        if report_type in ['all', 'loans_due']:
            loans_due_data = reports_service.get_loans_due_report(branch_id=branch_id)
            for loan in loans_due_data['loans']:
                if (query.lower() in loan.get('borrower__first_name', '').lower() or
                    query.lower() in loan.get('borrower__last_name', '').lower() or
                    query.lower() in loan.get('loan_number', '').lower() or
                    query.lower() in loan.get('borrower__phone_number', '').lower()):
                    results.append({
                        'type': 'loans_due',
                        'data': loan
                    })
        
        # Search in delinquent loans
        if report_type in ['all', 'delinquent_loans']:
            delinquent_data = reports_service.get_delinquent_loans_report(branch_id=branch_id)
            for loan in delinquent_data['loans']:
                if (query.lower() in loan.get('borrower__first_name', '').lower() or
                    query.lower() in loan.get('borrower__last_name', '').lower() or
                    query.lower() in loan.get('loan_number', '').lower() or
                    query.lower() in loan.get('borrower__phone_number', '').lower()):
                    results.append({
                        'type': 'delinquent_loans',
                        'data': loan
                    })
        
        return JsonResponse({
            'success': True,
            'data': {
                'query': query,
                'results': results[:50],  # Limit to 50 results
                'total_found': len(results)
            }
        })
        
    except Exception as e:
        return JsonResponse({
            'success': False,
            'error': str(e)
        }, status=500)


@login_required
@require_http_methods(["POST"])
def export_filtered_data_api(request):
    """
    API endpoint for exporting filtered data
    """
    try:
        data = json.loads(request.body)
        report_type = data.get('report_type')
        export_format = data.get('format', 'excel')
        filters = data.get('filters', {})
        branch_id = request.session.get('selected_branch_id')
        
        # Generate export URL based on report type and filters
        export_url = f"/reports/export/{report_type}/"
        
        # Add filters as query parameters
        params = []
        for key, value in filters.items():
            if value:
                params.append(f"{key}={value}")
        
        if branch_id:
            params.append(f"branch_id={branch_id}")
        
        params.append(f"format={export_format}")
        
        if params:
            export_url += "?" + "&".join(params)
        
        return JsonResponse({
            'success': True,
            'data': {
                'export_url': export_url,
                'format': export_format,
                'report_type': report_type
            }
        })
        
    except Exception as e:
        return JsonResponse({
            'success': False,
            'error': str(e)
        }, status=500)


@login_required
@require_http_methods(["GET"])
def chart_data_api(request):
    """
    API endpoint for chart data generation
    """
    try:
        chart_type = request.GET.get('chart_type')
        branch_id = request.session.get('selected_branch_id')
        
        if chart_type == 'loan_performance':
            chart_data = chart_service.get_loan_performance_chart_data(branch_id=branch_id)
        elif chart_type == 'portfolio_distribution':
            chart_data = chart_service.get_portfolio_distribution_chart_data(branch_id=branch_id)
        elif chart_type == 'collection_rate':
            chart_data = chart_service.get_collection_rate_chart_data(branch_id=branch_id)
        elif chart_type == 'delinquency_trend':
            chart_data = chart_service.get_delinquency_trend_chart_data(branch_id=branch_id)
        elif chart_type == 'revenue_breakdown':
            chart_data = chart_service.get_revenue_breakdown_chart_data(branch_id=branch_id)
        else:
            return JsonResponse({
                'success': False,
                'error': 'Invalid chart type'
            }, status=400)
        
        return JsonResponse({
            'success': True,
            'data': chart_data,
            'timestamp': datetime.now().isoformat()
        })
        
    except Exception as e:
        return JsonResponse({
            'success': False,
            'error': str(e),
            'chart_data': {
                'labels': [],
                'datasets': [],
                'error': str(e)
            }
        }, status=200)  # Return 200 with error in data for graceful handling