"""
Synchronous Task Functions for Report Scheduler
================================================

These are synchronous versions of the Celery tasks that can be called
directly by APScheduler. They run in background threads to avoid blocking.
"""

import logging
from datetime import datetime, timedelta
from dateutil.relativedelta import relativedelta
from django.utils import timezone
from django.core.mail import EmailMultiAlternatives
from django.template.loader import render_to_string
from django.conf import settings

from apps.business.models import Business
from apps.reporting.models import ReportLog, ReportPreferences, FinancialReport, ReportStatus
from apps.reporting.services import (
    WeeklyReportService, 
    ReportPreferencesService,
    ReportingService
)
from apps.notifications.email_report_service import EmailReportService
import json

logger = logging.getLogger(__name__)

def send_weekly_reports():
    """
    Send weekly reports to all businesses with enabled preferences.
    This should be scheduled to run weekly (e.g., Monday mornings).
    
    Returns:
        dict: Result with sent and failed counts
    """
    logger.info("Starting weekly report sending task")
    
    # Get all businesses with enabled report preferences
    preferences = ReportPreferences.objects.filter(
        enabled=True,
        frequency='WEEKLY'
    ).select_related('business')
    
    sent_count = 0
    failed_count = 0
    
    for pref in preferences:
        try:
            # COMMENT OUT OR REMOVE THIS SCHEDULE CHECK:
            # if not ReportPreferencesService.should_send_report(pref.business):
            #     logger.info(f"Skipping report for {pref.business.name} - not scheduled for now")
            #     continue
            
            # Check if there's business activity (if required)
            if pref.send_only_if_activity:
                report_service = WeeklyReportService(pref.business)
                report_data = report_service.generate_report()
                
                # Check if there was any activity
                has_activity = (
                    report_data['sales_performance']['total_sales'] > 0 or
                    report_data['credit_management']['total_outstanding'] > 0
                )
                
                if not has_activity:
                    logger.info(f"Skipping report for {pref.business.name} - no activity")
                    continue
            
            # Send the report
            result = send_business_weekly_report(pref.business.id)
            if result.get('status') == 'sent':
                sent_count += 1
            else:
                failed_count += 1
            
        except Exception as e:
            logger.error(f"Error processing weekly report for {pref.business.name}: {str(e)}", exc_info=True)
            failed_count += 1
    
    logger.info(f"Weekly report task completed. Sent: {sent_count}, Failed: {failed_count}")
    return {'sent': sent_count, 'failed': failed_count}

def send_business_weekly_report(business_id):
    """
    Send weekly report for a specific business.
    
    Args:
        business_id: ID of the business
        
    Returns:
        dict: Result with status and details
    """
    try:
        business = Business.objects.get(id=business_id)
        preferences = ReportPreferencesService.get_or_create_preferences(business)
        
        if not preferences.recipients:
            logger.warning(f"No recipients configured for {business.name}")
            return {'status': 'skipped', 'reason': 'no_recipients'}
        
        # Generate report data
        report_service = WeeklyReportService(business)
        report_data = report_service.generate_report()
        print(f"report_data: {report_data}")
        
        # Get or create email service
        email_service = EmailReportService()
        
        # Send email
        success = email_service.send_weekly_report(
            business=business,
            report_data=report_data,
            recipients=preferences.recipients
        )
        
        if success:
            # Create log entry
            ReportLog.objects.create(
                business=business,
                report_type='WEEKLY',
                period_start=report_data['metadata']['week_start'],
                period_end=report_data['metadata']['week_end'],
                recipients=preferences.recipients,
                status='SENT',
                report_data_snapshot={
                    'total_revenue': report_data['sales_performance']['total_revenue'],
                    'total_outstanding': report_data['credit_management']['total_outstanding'],
                    'low_stock_count': report_data['inventory_alerts']['low_stock_count'],
                }
            )
            
            # Mark as sent in preferences
            preferences.mark_as_sent()
            
            logger.info(f"Successfully sent weekly report for {business.name}")
            return {'status': 'sent', 'business_id': business_id}
        else:
            raise Exception("Email sending failed")
            
    except Business.DoesNotExist:
        logger.error(f"Business {business_id} not found")
        return {'status': 'failed', 'reason': 'business_not_found'}
        
    except Exception as e:
        logger.error(f"Error sending weekly report for business {business_id}: {str(e)}", exc_info=True)
        
        # Create failed log entry
        try:
            business = Business.objects.get(id=business_id)
            preferences = business.report_preferences
            
            ReportLog.objects.create(
                business=business,
                report_type='WEEKLY',
                recipients=preferences.recipients if hasattr(business, 'report_preferences') else [],
                status='FAILED',
                error_message=str(e)
            )
        except Exception as log_error:
            logger.error(f"Error creating log entry: {str(log_error)}")
        
        return {'status': 'failed', 'error': str(e)}


def send_report_now(business_id, recipients=None):
    """
    Send report immediately (on-demand).
    
    Args:
        business_id: ID of the business
        recipients: Optional list of recipient emails (overrides preferences)
        
    Returns:
        dict: Result with status
    """
    try:
        business = Business.objects.get(id=business_id)
        preferences = ReportPreferencesService.get_or_create_preferences(business)
        
        # Use provided recipients or fall back to preferences
        recipient_list = recipients if recipients else preferences.recipients
        
        if not recipient_list:
            logger.warning(f"No recipients for immediate report send: {business.name}")
            return {'status': 'failed', 'reason': 'no_recipients'}
        
        # Generate report data
        report_service = WeeklyReportService(business)
        report_data = report_service.generate_report()
        
        # Send email
        email_service = EmailReportService()
        success = email_service.send_weekly_report(
            business=business,
            report_data=report_data,
            recipients=recipient_list
        )
        
        if success:
            # Create log entry
            ReportLog.objects.create(
                business=business,
                report_type='CUSTOM',
                period_start=report_data['metadata']['week_start'],
                period_end=report_data['metadata']['week_end'],
                recipients=recipient_list,
                status='SENT',
                report_data_snapshot={
                    'total_revenue': report_data['sales_performance']['total_revenue'],
                    'total_outstanding': report_data['credit_management']['total_outstanding'],
                }
            )
            
            logger.info(f"Successfully sent immediate report for {business.name}")
            return {'status': 'sent', 'business_id': business_id}
        else:
            raise Exception("Email sending failed")
            
    except Exception as e:
        logger.error(f"Error sending immediate report for business {business_id}: {str(e)}", exc_info=True)
        
        # Create failed log
        try:
            business = Business.objects.get(id=business_id)
            ReportLog.objects.create(
                business=business,
                report_type='CUSTOM',
                recipients=recipients or [],
                status='FAILED',
                error_message=str(e)
            )
        except Exception:
            pass
        
        return {'status': 'failed', 'error': str(e)}


def send_test_report_email(business_id, recipient_email):
    """
    Send a test report email with actual report data.
    
    Args:
        business_id: ID of the business
        recipient_email: Email address to send test to
        
    Returns:
        dict: Result with status
    """
    logger.info(f"Starting test email task for business {business_id}, recipient: {recipient_email}")
    
    try:
        business = Business.objects.get(id=business_id)
        logger.info(f"Found business: {business.name}")
        
        # Get or create preferences
        preferences = ReportPreferencesService.get_or_create_preferences(business)
        
        # Generate actual report data
        logger.info("Generating report data...")
        report_service = WeeklyReportService(business)
        report_data = report_service.generate_report()
        logger.info(f"Report generated with {len(report_data)} sections")
        
        # Send email
        logger.info(f"Sending email to {recipient_email}")
        email_service = EmailReportService()
        
        success = email_service.send_weekly_report(
            business=business,
            report_data=report_data,
            recipients=[recipient_email]
        )
        
        if success:
            logger.info(f"Email sent successfully!")
            
            # Create log entry
            ReportLog.objects.create(
                business=business,
                report_type='TEST',
                period_start=report_data['metadata']['week_start'],
                period_end=report_data['metadata']['week_end'],
                recipients=[recipient_email],
                status='SENT',
                report_data_snapshot={
                    'total_revenue': report_data['sales_performance']['total_revenue'],
                    'total_outstanding': report_data['credit_management']['total_outstanding'],
                    'low_stock_count': report_data['inventory_alerts']['low_stock_count'],
                }
            )
            
            return {'status': 'success', 'recipient': recipient_email}
        else:
            raise Exception("Email sending failed")
            
    except Business.DoesNotExist:
        logger.error(f"Business {business_id} not found")
        return {'status': 'failed', 'reason': 'business_not_found'}
        
    except Exception as e:
        logger.error(f"Error sending test email: {str(e)}", exc_info=True)
        
        # Create failed log
        try:
            business = Business.objects.get(id=business_id)
            ReportLog.objects.create(
                business=business,
                report_type='TEST',
                recipients=[recipient_email],
                status='FAILED',
                error_message=str(e)[:500]
            )
        except Exception as log_error:
            logger.error(f"Error creating log entry: {str(log_error)}")
        
        return {'status': 'failed', 'error': str(e)}


def generate_all_monthly_reports():
    """
    Generate monthly reports for all active businesses.
    This should run on the first day of each month.
    
    Returns:
        dict: Result with businesses processed count
    """
    try:
        active_businesses = Business.objects.filter(is_active=True)
        
        logger.info(f"Generating monthly reports for {active_businesses.count()} businesses")
        
        for business in active_businesses:
            try:
                generate_monthly_sales_report(business.id)
            except Exception as e:
                logger.error(f"Error generating monthly report for {business.name}: {str(e)}")
        
        return {
            'status': 'success',
            'businesses_processed': active_businesses.count()
        }
    
    except Exception as exc:
        logger.error(f"Error in generate_all_monthly_reports: {str(exc)}", exc_info=True)
        return {'status': 'failed', 'error': str(exc)}


def generate_monthly_sales_report(business_id, month=None, year=None):
    """
    Generate monthly sales report for a business.
    
    Args:
        business_id: ID of the business
        month: Month (1-12), defaults to last month
        year: Year, defaults to current year
        
    Returns:
        dict: Result with report_id
    """
    try:
        if month is None or year is None:
            # Default to last month
            today = timezone.now().date()
            first_of_month = today.replace(day=1)
            last_month = first_of_month - timedelta(days=1)
            month = last_month.month
            year = last_month.year
        
        # Calculate date range
        from datetime import date
        start_date = date(year, month, 1)
        
        # Last day of month
        if month == 12:
            end_date = date(year + 1, 1, 1) - timedelta(days=1)
        else:
            end_date = date(year, month + 1, 1) - timedelta(days=1)
        
        # Generate report
        return generate_report(
            business_id,
            'MONTHLY_SALES',
            start_date.isoformat(),
            end_date.isoformat()
        )
    
    except Exception as exc:
        logger.error(f"Error in monthly sales report: {str(exc)}", exc_info=True)
        return {'status': 'failed', 'error': str(exc)}


def generate_report(business_id, report_type, start_date, end_date, configuration=None, report_id=None):
    """
    Generate a financial report.
    
    Args:
        business_id: ID of the business
        report_type: Type of report to generate
        start_date: Start date (ISO format string)
        end_date: End date (ISO format string)
        configuration: Optional report configuration
        report_id: Optional ID of existing report to update
        
    Returns:
        dict: Result with report_id and status
    """
    try:
        # Convert date strings to date objects
        if isinstance(start_date, str):
            start_date = datetime.fromisoformat(start_date).date()
        if isinstance(end_date, str):
            end_date = datetime.fromisoformat(end_date).date()
        
        # Get or create report record
        if report_id:
            report = FinancialReport.objects.get(id=report_id)
            report.status = ReportStatus.PROCESSING
            report.save()
        else:
            report = FinancialReport.objects.create(
                title=f"{report_type} - {start_date} to {end_date}",
                report_type=report_type,
                business_id=business_id,
                date_range_start=start_date,
                date_range_end=end_date,
                status=ReportStatus.PROCESSING
            )
        
        # Generate report
        report_service = ReportingService(business_id)
        report_data = report_service.generate_report(
            report_type,
            start_date,
            end_date,
            configuration or {}
        )
        
        # Update report record
        report.report_data = json.loads(json.dumps(report_data, default=str))

        report.mark_completed()
        
        logger.info(f"Successfully generated report {report.id} for business {business_id}")
        
        return {
            'status': 'success',
            'report_id': report.id,
            'report_type': report_type
        }
    
    except Exception as exc:
        logger.error(f"Error generating report: {str(exc)}", exc_info=True)
        
        if report_id:
            try:
                report = FinancialReport.objects.get(id=report_id)
                report.mark_failed(str(exc))
            except:
                pass
        
        return {'status': 'failed', 'error': str(exc)}


def check_low_stock_all_businesses():
    """
    Check low stock for all active businesses.
    This should run weekly.
    
    Returns:
        dict: Result with businesses processed count
    """
    try:
        active_businesses = Business.objects.filter(is_active=True)
        
        logger.info(f"Checking low stock for {active_businesses.count()} businesses")
        
        for business in active_businesses:
            try:
                generate_low_stock_alert(business.id)
            except Exception as e:
                logger.error(f"Error checking low stock for {business.name}: {str(e)}")
        
        return {
            'status': 'success',
            'businesses_processed': active_businesses.count()
        }
    
    except Exception as exc:
        logger.error(f"Error in check_low_stock_all_businesses: {str(exc)}", exc_info=True)
        return {'status': 'failed', 'error': str(exc)}


def generate_low_stock_alert(business_id, threshold=30):
    """
    Generate low stock alert for a business.
    
    Args:
        business_id: ID of the business
        threshold: Stock level threshold
        
    Returns:
        dict: Result with report_id
    """
    try:
        today = timezone.now().date()
        
        return generate_report(
            business_id,
            'LOW_STOCK_ALERT',
            today.isoformat(),
            today.isoformat(),
            configuration={'threshold': threshold}
        )
    
    except Exception as exc:
        logger.error(f"Error in low stock alert: {str(exc)}", exc_info=True)
        return {'status': 'failed', 'error': str(exc)}


def check_warranty_expiry_all_businesses():
    """
    Check warranty expiry for all active businesses.
    This should run daily.
    
    Returns:
        dict: Result with businesses processed count
    """
    try:
        active_businesses = Business.objects.filter(is_active=True)
        
        logger.info(f"Checking warranty expiry for {active_businesses.count()} businesses")
        
        for business in active_businesses:
            try:
                generate_warranty_expiry_report(business.id)
            except Exception as e:
                logger.error(f"Error checking warranty for {business.name}: {str(e)}")
        
        return {
            'status': 'success',
            'businesses_processed': active_businesses.count()
        }
    
    except Exception as exc:
        logger.error(f"Error in check_warranty_expiry_all_businesses: {str(exc)}", exc_info=True)
        return {'status': 'failed', 'error': str(exc)}


def generate_warranty_expiry_report(business_id, days_ahead=90):
    """
    Generate warranty expiry report.
    
    Args:
        business_id: ID of the business
        days_ahead: Number of days to look ahead
        
    Returns:
        dict: Result with report_id
    """
    try:
        today = timezone.now().date()
        end_date = today + timedelta(days=days_ahead)
        
        return generate_report(
            business_id,
            'WARRANTY_EXPIRY',
            today.isoformat(),
            end_date.isoformat()
        )
    
    except Exception as exc:
        logger.error(f"Error in warranty expiry report: {str(exc)}", exc_info=True)
        return {'status': 'failed', 'error': str(exc)}


def cleanup_old_reports(days_to_keep=90):
    """
    Clean up old report files and records.
    
    Args:
        days_to_keep: Number of days to keep reports
        
    Returns:
        dict: Result with deleted count
    """
    try:
        cutoff_date = timezone.now() - timedelta(days=days_to_keep)
        
        old_reports = FinancialReport.objects.filter(
            created_at__lt=cutoff_date,
            status=ReportStatus.COMPLETED
        )
        
        count = old_reports.count()
        old_reports.delete()
        
        logger.info(f"Cleaned up {count} old reports")
        
        return {
            'status': 'success',
            'reports_deleted': count
        }
    
    except Exception as exc:
        logger.error(f"Error in cleanup_old_reports: {str(exc)}", exc_info=True)
        return {'status': 'failed', 'error': str(exc)}


def cleanup_old_report_logs():
    """
    Clean up old report logs (older than 90 days).
    
    Returns:
        dict: Result with deleted count
    """
    from datetime import timedelta
    
    cutoff_date = timezone.now() - timedelta(days=90)
    
    deleted_count, _ = ReportLog.objects.filter(
        created_at__lt=cutoff_date
    ).delete()
    
    logger.info(f"Cleaned up {deleted_count} old report logs")
    return {'deleted_count': deleted_count}