import json
import os
import re
from typing import Union
import logging

import boto3
from botocore.exceptions import ClientError
from django.conf import settings

from . import MessageWrapper as MessageWrapperBase


class MessageWrapper(MessageWrapperBase):

    def __init__(self, **kwargs):
        region: str = kwargs.get('region', 'af-south-1')
        self.sns_resource = boto3.resource('sns', region_name=region)

    def create_topic(self, topic: str):
        """
        Create a topic with the supplied topic, environment aware
        """
        try:
            _topic = self.sns_resource.create_topic(Name=self._get_env_topic(topic))
        except ClientError as e:
            raise
        else:
            return _topic

    def subscribe(self, topic: str, protocol: str = 'http', endpoint: str = None) -> bool:
        """
        Get a topic ARN by topic
        """
        _topic = self.create_topic(topic=topic)
        try:
            arn = _topic.subscribe(
                Protocol=protocol,
                Endpoint=endpoint,
                # Attributes={'cliennt': 'sil', 'environment': 'DEV1'},
                ReturnSubscriptionArn=True
            )
        except ClientError:
            raise
        return arn

    def unsubscribe(self, topic: str, topic_link: str = None, *args, **kwargs) -> bool:
        pass

    def publish(self, topic: str, message: Union[str, dict], subject: str = None, payload: dict = None, *args, **kwargs):
        _topic = self.create_topic(topic)
        payload = dict() if payload is None else payload
        payload['payload'] = message
        self._inject_source_name(payload)
        params = dict(Message=json.dumps(payload))
        if subject is not None:
            params['Subject'] = subject
        res = _topic.publish(**params)
        return res

    def delete_topic(self, topic: str) -> bool:
        pass

    def _get_env_topic(self, topic):
        env = os.environ.get('RUNTIME_ENVIRON',
                             settings.__dict__.get('RUNTIME_ENVIRON', settings.__dict__.get('MAVEN_SECTION', 'DEV')))
        logging.warning(f'Using environment {env}')
        env = re.sub('[^A-Za-z_]', '', env)  # remove non-alpha chars
        env_topic = f"{env.lower()}_{topic}"
        return env_topic

    @staticmethod
    def _inject_source_name(params):
        source = settings.__dict__.get('MICROSERVICE_NAME', settings.__dict__.get('CLIENT', 'unknown'))
        params['source'] = source

