"""
Event notification module for publishing events to AWS EventBridge.

This module provides functionality to send events to AWS EventBridge for
asynchronous processing and integration with other AWS services.
"""
import json
import logging
import os
import sys
from importlib.util import spec_from_file_location, module_from_spec
from ..notifications.teams_notifications import Notifications as ErrorNotifications

import boto3

logger = logging.getLogger(__name__)


class EventBridgePublisher(object):
    """
    Handles publishing events to AWS EventBridge.

    This class manages AWS credentials from environment configuration and provides
    methods to publish events to an AWS EventBridge event bus for downstream processing.
    """

    def __init__(self):
        self.region_name = self._get_env_var("AWS_REGION"),
        self.aws_access_key_id = self._get_env_var("AWS_ACCESS_KEY_ID"),
        self.aws_secret_access_key = self._get_env_var("AWS_SECRET_ACCESS_KEY")

    def _get_env_var(self, key: str) -> str:
        """
        Fetch a required variable from bw_config.py located in the root directory.

        Raises:
            FileNotFoundError: If bw_config.py is not found.
            AttributeError: If the requested key is not defined in the config.

        Returns:
            str: The value of the config variable.
        """
        config_path = os.path.join(os.getcwd(), "bw_config.py")

        if not os.path.exists(config_path):
            raise FileNotFoundError("`bw_config.py` file not found in the root directory. "
                                    "Please ensure the config file exists.")

        spec = spec_from_file_location("bw_config", config_path)
        bw_config = module_from_spec(spec)
        sys.modules["bw_config"] = bw_config
        spec.loader.exec_module(bw_config)

        if not hasattr(bw_config, key):
            raise AttributeError(f"`{key}` not found in bw_config.py. Please define it in the config.")

        return getattr(bw_config, key)

    def send_event_notification(self, event, source='user-event'):
        """
        Publish an event to AWS EventBridge.

        This method sends an event to the configured AWS EventBridge event bus.
        If an error occurs during publishing, it sends an error notification
        via Teams.

        Args:
            event (dict): The event payload to publish. Will be JSON-serialized.
            source (str, optional): The event source identifier. Defaults to 'user-event'.

        Note:
            - Requires AWS_EVENT_BUS_ARN configuration variable
            - Errors are logged and sent as Teams notifications
            - AWS client connection is properly closed after use
        """
        try:
            logger.info(f"In publish event")
            # Create AWS EventBridge client with configured credentials
            client = boto3.client("events",
                                  region_name=self.region_name,
                                  aws_access_key_id=self.aws_access_key_id,
                                  aws_secret_access_key=self.aws_secret_access_key)
            event_bus_arn = self._get_env_var("AWS_EVENT_BUS_ARN")

            if not event_bus_arn:
                raise ValueError("EventBusName is empty — invalid configuration.")

            # Publish event to EventBridge
            response = client.put_events(
                Entries=[
                    {
                        'Source': source,
                        'DetailType': 'user-preferences',
                        'Detail': json.dumps(event),
                        'EventBusName': event_bus_arn
                    }
                ]
            )
            client.close()
            logger.info(f"Event published - {response = }")
        except Exception as e:
            # Notify error via Teams on publishing failure
            error_notifications = ErrorNotifications('BW-essentials_error')
            error_notifications.notify_error(
                message="error via BW essentials while sending a event notification" + str(e),
                summary=f"event publish error {event = }")
