from apps.calls.repositories import NotificationRepository
from apps.calls.models import NotificationType
from apps.permissions.models import UserCompanyRole, Role
from apps.core.models import User
import logging

logger = logging.getLogger(__name__)


class NotificationService:

    @staticmethod
    def list_notifications(user, qs = None):
        if qs is None:
            qs = NotificationRepository.base_queryset()

        if user.is_superuser:
            return qs.order_by('-created_at')

        return NotificationRepository.list_for_user(user)

    @staticmethod
    def get_notification(user, notif_id):
        return NotificationRepository.get_by_id(notif_id, user)

    @staticmethod
    def mark_as_read(user, notif_id):
        notif = NotificationService.get_notification(user, notif_id)

        if notif is None:
            return None
        return NotificationRepository.mark_as_read(notif)

    @staticmethod
    def get_chief_admins_for_company(company):
        """Get all users with Chief Admin role for a given company"""
        try:
            chief_admin_role = Role.objects.filter(
                company=company,
                name='Chief Admin',
                is_active=True
            ).first()

            if not chief_admin_role:
                logger.warning(f"No Chief Admin role found for company: {company.name}")
                return []

            user_company_roles = UserCompanyRole.objects.filter(
                company=company,
                role=chief_admin_role,
                is_active=True
            ).select_related('user')

            chief_admins = [ucr.user for ucr in user_company_roles if ucr.user.is_active]
            return chief_admins
        except Exception as e:
            logger.error(f"Error getting chief admins for company {company.name}: {str(e)}")
            return []

    @staticmethod
    def get_service_managers_for_company(company):
        """Get all users with Service Manager role for a given company"""
        try:
            service_manager_role = Role.objects.filter(
                company=company,
                name='Service Manager',
                is_active=True
            ).first()

            if not service_manager_role:
                logger.warning(f"No Service Manager role found for company: {company.name}")
                return []

            user_company_roles = UserCompanyRole.objects.filter(
                company=company,
                role=service_manager_role,
                is_active=True
            ).select_related('user')

            service_managers = [ucr.user for ucr in user_company_roles if ucr.user.is_active]
            return service_managers
        except Exception as e:
            logger.error(f"Error getting service managers for company {company.name}: {str(e)}")
            return []

    @staticmethod
    def _get_advisor_name(user):
        """Helper method to safely get advisor name"""
        if not user:
            return "Unknown"
        try:
            if hasattr(user, 'profile') and user.profile:
                return user.profile.full_name
            else:
                return user.username or user.email
        except Exception:
            return user.username or user.email

    @staticmethod
    def _send_notification_to_managers(managers, user, call, display_name, customer_phone, title, role_name, company):
        """Helper method to send notifications to managers/admins"""
        for manager in managers:
            if user and manager.id == user.id:
                continue
                
            try:
                advisor_name = NotificationService._get_advisor_name(user)
                company_name = company.name if company else "Unknown Company"
                manager_message = f"Advisor {advisor_name} from {company_name} missed a call from {display_name}"
                NotificationRepository.create_notification(
                    recipient=manager,
                    notification_type=NotificationType.MISSED_CALL,
                    title=title,
                    message=manager_message,
                    call=call
                )
                logger.info(f"Missed call notification sent to {role_name}: {manager.email}")
            except Exception as e:
                logger.error(f"Error sending notification to {role_name} {manager.email}: {str(e)}")

    @staticmethod
    def send_missed_call_notification(call, user, company, customer_name, customer_phone):
        """
        Send missed call notifications to advisor, all chief admins, and service managers of the company.
        
        Args:
            call: Call object
            user: User object (the user who missed the call)
            company: Company object
            customer_name: str (customer name or None)
            customer_phone: str (customer phone number)
        """
        try:
            display_name = customer_name if customer_name else "Unknown Customer"
            company_name = company.name if company else "Unknown Company"
            
            message = f"Missed call from {display_name}"
            title = "Missed Call"

            if user:
                try:
                    NotificationRepository.create_notification(
                        recipient=user,
                        notification_type=NotificationType.MISSED_CALL,
                        title=title,
                        message=message,
                        call=call
                    )
                    logger.info(f"Missed call notification sent to advisor: {user.email}")
                except Exception as e:
                    logger.error(f"Error sending notification to advisor {user.email}: {str(e)}")

            chief_admins = NotificationService.get_chief_admins_for_company(company)
            NotificationService._send_notification_to_managers(
                chief_admins, user, call, display_name, customer_phone, title, "chief admin", company
            )

            service_managers = NotificationService.get_service_managers_for_company(company)
            NotificationService._send_notification_to_managers(
                service_managers, user, call, display_name, customer_phone, title, "service manager", company
            )

        except Exception as e:
            logger.error(f"Error in send_missed_call_notification: {str(e)}")

    @staticmethod
    def send_message_notification(user, title='', message=''):
        """
        Send message notifications to advisor of company.

        Args:
            user: User object (the user who missed the call)
            title: str (notification title)
            message: str (notification message)
        """
        if user is None:
            logger.error("Cannot send notification — user is None")
            return

        try:
            NotificationRepository.create_notification(
                recipient=user,
                notification_type=NotificationType.MESSAGE,
                title=title,
                message=message,
            )
            logger.info(f"Message notification sent to {user.email}")

        except Exception as e:
            logger.exception(
                "Failed to send message notification to %s: %s",
                user.email, str(e)
            )
