import logging
import subprocess

from rest_framework.exceptions import APIException

_log = logging.getLogger(__name__)


class AMCServiceException(APIException):
    pass


class AMCService:
    MAPPING_SERVICE = {
        'nginx': 'nginx.service',
        'elasticsearch': 'elasticsearch.service',
        'gunicorn': 'amcgunicorn.service',
        'celery': 'amccelery.service',
        'celerybeat': 'amccelerybeat.service',
        'correlator': 'amccorrelator.service',
        'vector': 'amcvector.service',
        'postgresql': 'postgresql.service'
    }

    def __init__(self, service_name):
        self.service = service_name

        try:
            self.system_service_name = self.MAPPING_SERVICE[service_name]
        except KeyError:
            raise AMCServiceException({'status': 'error', 'detail': f'Unable to work with "{service_name}" service'})

    def get_status(self):
        """
            Check whether any of the specified units are active (i.e. running).
        """
        command = ['sudo', 'systemctl', 'is-active', f'{self.system_service_name}']
        action = 'get status'
        return self._run_cmd(command, action)

    def reboot(self):
        """
            Reload service if they support it. If not, stop and then start them instead
            If the services are not running yet, they will be started
        """
        command = ['sudo', 'systemctl', 'reload-or-restart', f'{self.system_service_name}']
        action = 'reboot'
        return self._run_cmd(command, action)

    def _run_cmd(self, cmd, action='perform operation'):
        subproc = subprocess.run(cmd, capture_output=True)
        if subproc.returncode != 0:  # usually 0 is the correct exit code
            error = subproc.stderr or subproc.stdout
            _log.error(f"Can't {action} '{self.service}': {error.decode('utf-8')}")
            raise AMCServiceException({'status': 'error',
                                       'detail': f"Can't {action} '{self.service}': {error.decode('utf-8').strip()}"})
        output = subproc.stdout.decode().strip()
        return output
