"""
Notification utilities for sending emails to users at different stages of leave and overtime requests.
"""
from django.core.mail import send_mail, EmailMultiAlternatives
from django.template.loader import render_to_string
from django.utils.html import strip_tags
from django.conf import settings
from django.contrib.auth.models import User, Group
import logging

from accounts.models import Employee

logger = logging.getLogger(__name__)


def get_site_url(request=None):
    """
    Get the site URL from the request or settings.
    
    Args:
        request: The HTTP request object (optional)
    
    Returns:
        str: The site URL
    """
    # First try to get the URL from the request
    if request:
        return f"{request.scheme}://{request.get_host()}"
    
    # Then try to get it from the Site framework
    try:
        from django.contrib.sites.models import Site
        site = Site.objects.get_current()
        protocol = 'https' if settings.SECURE_SSL_REDIRECT else 'http'
        return f"{protocol}://{site.domain}"
    except Exception as e:
        logger.warning(f"Could not get site URL from Site framework: {e}")
    
    # Finally, use the production URL as a fallback
    return "https://smarthr.ictaz.org.zm"


def get_hr_emails():
    """Get email addresses of all HR managers."""
    # First try to get users from HR Manager group
    hr_group = Group.objects.filter(name='HR Manager').first()
    if hr_group:
        hr_users = hr_group.user_set.all()
        emails = [user.email for user in hr_users if user.email]
        if emails:
            return emails
    
    # If no group or no emails found, try by employee role
    from accounts.models import Employee
    hr_employees = Employee.objects.filter(role='HR')
    return [employee.user.email for employee in hr_employees if employee.user.email]


def get_registrar_emails():
    """Get email addresses of all Registrars."""
    # First try to get users from Registrar group
    registrar_group = Group.objects.filter(name='Registrar').first()
    if registrar_group:
        registrar_users = registrar_group.user_set.all()
        emails = [user.email for user in registrar_users if user.email]
        if emails:
            logger.info(f"Found Registrar emails from group: {emails}")
            return emails
        else:
            logger.warning("No emails found in Registrar group")
    else:
        logger.warning("Registrar group not found")
    
    # If no group or no emails found, try by employee role
    from accounts.models import Employee
    registrar_employees = Employee.objects.filter(role='REG')
    emails = [employee.user.email for employee in registrar_employees if employee.user.email]
    
    if emails:
        logger.info(f"Found Registrar emails from role: {emails}")
    else:
        logger.warning("No Registrar emails found from role either")
        
    return emails


def get_finance_emails():
    """Get email addresses of all Finance department users."""
    # First try to get users from Finance group
    finance_group = Group.objects.filter(name='Finance').first()
    if finance_group:
        finance_users = finance_group.user_set.all()
        emails = [user.email for user in finance_users if user.email]
        if emails:
            return emails
    
    # If no group or no emails found, try by employee role
    from accounts.models import Employee
    finance_employees = Employee.objects.filter(role='FIN')
    return [employee.user.email for employee in finance_employees if employee.user.email]


def send_html_email(subject, html_content, recipient_list, from_email=None):
    """
    Send an HTML email with plain text fallback.
    """
    if not recipient_list:
        # Don't attempt to send if there are no recipients
        logger.warning(f"No recipients provided for email: {subject}")
        return 0
        
    if not from_email:
        from_email = settings.DEFAULT_FROM_EMAIL or 'noreply@ictaz.org'
    
    # Create plain text version
    plain_message = strip_tags(html_content)
    
    # Log email sending attempt
    import logging
    logger = logging.getLogger(__name__)
    logger.info(f"Sending email: {subject} to {recipient_list}")
    
    # Create email message
    email = EmailMultiAlternatives(
        subject=subject,
        body=plain_message,
        from_email=from_email,
        to=recipient_list
    )
    
    # Attach HTML content
    email.attach_alternative(html_content, "text/html")
    
    # Send email
    try:
        result = email.send()
        logger.info(f"Email sent successfully: {result}")
        return result
    except Exception as e:
        logger.error(f"Failed to send email: {e}")
        return 0


# ===== LEAVE REQUEST NOTIFICATIONS =====

def notify_leave_submission(leave_request, request=None):
    """
    Send notification when a leave request is submitted.
    
    Args:
        leave_request: The LeaveRequest instance
        request: The HTTP request object (optional)
    """
    # Get the site URL for links
    site_url = get_site_url(request)
    # Notify employee (confirmation)
    employee_subject = f"Leave Request Submitted - {leave_request.leave_type}"
    employee_html = render_to_string('notifications/leave/employee_submission.html', {
        'leave_request': leave_request,
        'employee': leave_request.employee,
        'site_url': site_url
    })
    send_html_email(
        subject=employee_subject,
        html_content=employee_html,
        recipient_list=[leave_request.employee.user.email]
    )
    
    # Notify HR (new request)
    hr_emails = get_hr_emails()
    if hr_emails:
        hr_subject = f"New Leave Request - {leave_request.employee.user.get_full_name()}"
        hr_html = render_to_string('notifications/leave/hr_new_request.html', {
            'leave_request': leave_request,
            'employee': leave_request.employee,
            'site_url': site_url
        })
        send_html_email(
            subject=hr_subject,
            html_content=hr_html,
            recipient_list=hr_emails
        )


def notify_leave_hr_approval(leave_request, request=None):
    """
    Send notification when HR approves a leave request.
    
    Args:
        leave_request: The LeaveRequest instance
        request: The HTTP request object (optional)
    """
    logger.info(f"Sending HR approval notification for leave request {leave_request.id}")
    
    # Get the site URL for links
    site_url = get_site_url(request)
    # Notify employee
    employee_subject = f"Leave Request HR Approved - {leave_request.leave_type}"
    employee_html = render_to_string('notifications/leave/employee_hr_approved.html', {
        'leave_request': leave_request,
        'employee': leave_request.employee,
        'site_url': site_url
    })
    send_html_email(
        subject=employee_subject,
        html_content=employee_html,
        recipient_list=[leave_request.employee.user.email]
    )
    
    # Notify Registrar
    registrar_emails = get_registrar_emails()
    if registrar_emails:
        registrar_subject = f"Leave Request Pending Approval - {leave_request.employee.user.get_full_name()}"
        registrar_html = render_to_string('notifications/leave/registrar_new_request.html', {
            'leave_request': leave_request,
            'employee': leave_request.employee,
            'site_url': site_url
        })
        send_html_email(
            subject=registrar_subject,
            html_content=registrar_html,
            recipient_list=registrar_emails
        )


def notify_leave_hr_rejection(leave_request, request=None):
    """
    Send notification when HR rejects a leave request.
    
    Args:
        leave_request: The LeaveRequest instance
        request: The HTTP request object (optional)
    """
    # Get the site URL for links
    site_url = get_site_url(request)
    # Notify employee
    employee_subject = f"Leave Request Rejected by HR - {leave_request.leave_type}"
    employee_html = render_to_string('notifications/leave/employee_hr_rejected.html', {
        'leave_request': leave_request,
        'employee': leave_request.employee,
        'site_url': site_url
    })
    send_html_email(
        subject=employee_subject,
        html_content=employee_html,
        recipient_list=[leave_request.employee.user.email]
    )


def notify_leave_registrar_approval(leave_request, request=None):
    """
    Send notification when Registrar approves a leave request.
    
    Args:
        leave_request: The LeaveRequest instance
        request: The HTTP request object (optional)
    """
    logger.info(f"Sending Registrar approval notification for leave request {leave_request.id}")
    
    # Get the site URL for links
    site_url = get_site_url(request)
    # Notify employee
    employee_subject = f"Leave Request Approved - {leave_request.leave_type}"
    employee_html = render_to_string('notifications/leave/employee_final_approved.html', {
        'leave_request': leave_request,
        'employee': leave_request.employee,
        'site_url': site_url
    })
    send_html_email(
        subject=employee_subject,
        html_content=employee_html,
        recipient_list=[leave_request.employee.user.email]
    )
    
    # Notify HR (for record keeping)
    hr_emails = get_hr_emails()
    if hr_emails:
        hr_subject = f"Leave Request Approved - {leave_request.employee.user.get_full_name()}"
        hr_html = render_to_string('notifications/leave/hr_final_approved.html', {
            'leave_request': leave_request,
            'employee': leave_request.employee,
            'site_url': site_url
        })
        send_html_email(
            subject=hr_subject,
            html_content=hr_html,
            recipient_list=hr_emails
        )


def notify_leave_registrar_rejection(leave_request, request=None):
    """
    Send notification when Registrar rejects a leave request.
    
    Args:
        leave_request: The LeaveRequest instance
        request: The HTTP request object (optional)
    """
    # Get the site URL for links
    site_url = get_site_url(request)
    # Notify employee
    employee_subject = f"Leave Request Rejected - {leave_request.leave_type}"
    employee_html = render_to_string('notifications/leave/employee_final_rejected.html', {
        'leave_request': leave_request,
        'employee': leave_request.employee,
        'site_url': site_url
    })
    send_html_email(
        subject=employee_subject,
        html_content=employee_html,
        recipient_list=[leave_request.employee.user.email]
    )
    
    # Notify HR (for record keeping)
    hr_emails = get_hr_emails()
    if hr_emails:
        hr_subject = f"Leave Request Rejected - {leave_request.employee.user.get_full_name()}"
        hr_html = render_to_string('notifications/leave/hr_final_rejected.html', {
            'leave_request': leave_request,
            'employee': leave_request.employee,
            'site_url': site_url
        })
        send_html_email(
            subject=hr_subject,
            html_content=hr_html,
            recipient_list=hr_emails
        )


def notify_leave_upcoming(leave_request, request=None):
    """
    Send reminder notification before leave starts.
    
    Args:
        leave_request: The LeaveRequest instance
        request: The HTTP request object (optional)
    """
    # Get the site URL for links
    site_url = get_site_url(request)
    # Notify employee
    employee_subject = f"Upcoming Leave Reminder - {leave_request.leave_type}"
    employee_html = render_to_string('notifications/leave/employee_upcoming.html', {
        'leave_request': leave_request,
        'employee': leave_request.employee
    })
    send_html_email(
        subject=employee_subject,
        html_content=employee_html,
        recipient_list=[leave_request.employee.user.email]
    )


# ===== OVERTIME REQUEST NOTIFICATIONS =====

def notify_overtime_submission(overtime_request, request=None):
    """
    Send notification when an overtime request is submitted.
    
    Args:
        overtime_request: The OvertimeRequest instance
        request: The HTTP request object (optional)
    """
    # Get the site URL for links
    site_url = get_site_url(request)
    
    # Notify employee (confirmation)
    employee_subject = f"Overtime Request Submitted - {overtime_request.date}"
    employee_html = render_to_string('notifications/overtime/employee_submission.html', {
        'overtime_request': overtime_request,
        'employee': overtime_request.employee,
        'request': request,
        'site_url': site_url
    })
    send_html_email(
        subject=employee_subject,
        html_content=employee_html,
        recipient_list=[overtime_request.employee.user.email]
    )
    
    # Notify HR (new request)
    hr_emails = get_hr_emails()
    if hr_emails:
        hr_subject = f"New Overtime Request - {overtime_request.employee.user.get_full_name()}"
        hr_html = render_to_string('notifications/overtime/hr_new_request.html', {
            'overtime_request': overtime_request,
            'employee': overtime_request.employee,
            'site_url': site_url
        })
        send_html_email(
            subject=hr_subject,
            html_content=hr_html,
            recipient_list=hr_emails
        )


def notify_overtime_hr_approval(overtime_request, request=None):
    """
    Send notification when HR approves an overtime request.
    
    Args:
        overtime_request: The OvertimeRequest instance
        request: The HTTP request object (optional)
    """
    logger.info(f"Sending HR approval notification for overtime request {overtime_request.id}")
    
    # Get the site URL for links
    site_url = get_site_url(request)
    # Notify employee
    employee_subject = f"Overtime Request HR Approved - {overtime_request.date}"
    employee_html = render_to_string('notifications/overtime/employee_hr_approved.html', {
        'overtime_request': overtime_request,
        'employee': overtime_request.employee,
        'request': request,
        'site_url': site_url
    })
    send_html_email(
        subject=employee_subject,
        html_content=employee_html,
        recipient_list=[overtime_request.employee.user.email]
    )
    
    # Notify Registrar
    registrar_emails = get_registrar_emails()
    if registrar_emails:
        registrar_subject = f"Overtime Request Pending Approval - {overtime_request.employee.user.get_full_name()}"
        registrar_html = render_to_string('notifications/overtime/registrar_new_request.html', {
            'overtime_request': overtime_request,
            'employee': overtime_request.employee,
            'request': request,
            'site_url': site_url
        })
        send_html_email(
            subject=registrar_subject,
            html_content=registrar_html,
            recipient_list=registrar_emails
        )


def notify_overtime_hr_rejection(overtime_request, request=None):
    """
    Send notification when HR rejects an overtime request.
    
    Args:
        overtime_request: The OvertimeRequest instance
        request: The HTTP request object (optional)
    """
    # Get the site URL for links
    site_url = get_site_url(request)
    # Notify employee
    employee_subject = f"Overtime Request Rejected by HR - {overtime_request.date}"
    employee_html = render_to_string('notifications/overtime/employee_hr_rejected.html', {
        'overtime_request': overtime_request,
        'employee': overtime_request.employee,
        'site_url': site_url
    })
    send_html_email(
        subject=employee_subject,
        html_content=employee_html,
        recipient_list=[overtime_request.employee.user.email]
    )


def notify_overtime_registrar_approval(overtime_request, request=None):
    """
    Send notification when Registrar approves an overtime request.
    
    Args:
        overtime_request: The OvertimeRequest instance
        request: The HTTP request object (optional)
    """
    logger.info(f"Sending Registrar approval notification for overtime request {overtime_request.id}")
    
    # Get the site URL for links
    site_url = get_site_url(request)
    # Notify employee
    employee_subject = f"Overtime Request Approved - {overtime_request.date}"
    employee_html = render_to_string('notifications/overtime/employee_registrar_approved.html', {
        'overtime_request': overtime_request,
        'employee': overtime_request.employee,
        'site_url': site_url
    })
    send_html_email(
        subject=employee_subject,
        html_content=employee_html,
        recipient_list=[overtime_request.employee.user.email]
    )
    
    # Notify HR (for record keeping)
    hr_emails = get_hr_emails()
    if hr_emails:
        hr_subject = f"Overtime Request Approved - {overtime_request.employee.user.get_full_name()}"
        hr_html = render_to_string('notifications/overtime/hr_registrar_approved.html', {
            'overtime_request': overtime_request,
            'employee': overtime_request.employee,
            'site_url': site_url
        })
        send_html_email(
            subject=hr_subject,
            html_content=hr_html,
            recipient_list=hr_emails
        )
    
    # Notify Finance (for payment processing)
    finance_emails = get_finance_emails()
    if finance_emails:
        finance_subject = f"Overtime Payment Required - {overtime_request.employee.user.get_full_name()}"
        finance_html = render_to_string('notifications/overtime/finance_payment.html', {
            'overtime_request': overtime_request,
            'employee': overtime_request.employee,
            'site_url': site_url
        })
        send_html_email(
            subject=finance_subject,
            html_content=finance_html,
            recipient_list=finance_emails
        )


def notify_overtime_registrar_rejection(overtime_request, request=None):
    """
    Send notification when Registrar rejects an overtime request.
    
    Args:
        overtime_request: The OvertimeRequest instance
        request: The HTTP request object (optional)
    """
    # Get the site URL for links
    site_url = get_site_url(request)
    # Notify employee
    employee_subject = f"Overtime Request Rejected - {overtime_request.date}"
    employee_html = render_to_string('notifications/overtime/employee_registrar_rejected.html', {
        'overtime_request': overtime_request,
        'employee': overtime_request.employee,
        'site_url': site_url
    })
    send_html_email(
        subject=employee_subject,
        html_content=employee_html,
        recipient_list=[overtime_request.employee.user.email]
    )
    
    # Notify HR (for record keeping)
    hr_emails = get_hr_emails()
    if hr_emails:
        hr_subject = f"Overtime Request Rejected - {overtime_request.employee.user.get_full_name()}"
        hr_html = render_to_string('notifications/overtime/hr_registrar_rejected.html', {
            'overtime_request': overtime_request,
            'employee': overtime_request.employee,
            'site_url': site_url
        })
        send_html_email(
            subject=hr_subject,
            html_content=hr_html,
            recipient_list=hr_emails
        )


def notify_overtime_payment_processed(overtime_request, request=None):
    """
    Send notification when payment for overtime is processed.
    
    Args:
        overtime_request: The OvertimeRequest instance
        request: The HTTP request object (optional)
    """
    # Get the site URL for links
    site_url = get_site_url(request)
    # Notify employee
    employee_subject = f"Overtime Payment Processed - {overtime_request.date}"
    employee_html = render_to_string('notifications/overtime/employee_payment.html', {
        'overtime_request': overtime_request,
        'employee': overtime_request.employee,
        'site_url': site_url
    })
    send_html_email(
        subject=employee_subject,
        html_content=employee_html,
        recipient_list=[overtime_request.employee.user.email]
    )
    
    # Notify HR (for record keeping)
    hr_emails = get_hr_emails()
    if hr_emails:
        hr_subject = f"Overtime Payment Processed - {overtime_request.employee.user.get_full_name()}"
        hr_html = render_to_string('notifications/overtime/hr_payment.html', {
            'overtime_request': overtime_request,
            'employee': overtime_request.employee,
            'site_url': site_url
        })
        send_html_email(
            subject=hr_subject,
            html_content=hr_html,
            recipient_list=hr_emails
        )
