import allure
import requests
from json import JSONDecodeError
from oslo_log import log as logging

logger = logging.getLogger(__name__)


class Requests:
    def __init__(self, base_url=None, header=None):
        self.base_url = base_url
        self.header = header

    def get_request(self, url, header):
        logger.debug("Making GET request...")
        logger.debug(f"GET URL: {url}")
        try:
            response = requests.get(url=url, headers=header)
            # Record the status code in the logger instead of printing
            logger.debug(f"Response status code: {response.status_code}")
        except requests.RequestException as e:
            # Record the RequestException url in the logger instead of printing
            logger.error('RequestException url: ' + url)
            logger.error(e)
            return
        except Exception as e:
            # Record the Exception url in the logger instead of printing
            logger.error('Exception url: ' + url)
            logger.error(e)
            return

        response_dicts = dict()
        response_dicts['code'] = response.status_code
        try:
            response_dicts['body'] = response.json()
        except JSONDecodeError:
            # Record the JSONDecodeError in the logger instead of printing
            logger.warning('Response has no content or could not be serialized')
            response_dicts['body'] = ''
        response_dicts['text'] = response.text

        logger.debug("GET request completed.")
        return response_dicts

    def post_request(self, url, data, header):
        logger.debug("Making POST request...")
        logger.debug(f"POST URL: {url}")
        logger.debug(f"Data: {data}")
        try:
            response = requests.post(url=url, json=data, headers=header)
            # Record the status code and headers in the logger
            logger.debug(f"Response status code: {response.status_code}")
            logger.debug(f"Response headers: {response.headers}")

        except requests.RequestException as e:
            # Record the RequestException url in the logger instead of printing
            logger.error('RequestException url: ' + url)
            logger.error(e)
            return
        except Exception as e:
            # Record the Exception url in the logger instead of printing
            logger.error('Exception url: ' + url)
            logger.error(e)
            return

        response_dicts = dict()
        response_dicts['code'] = response.status_code
        try:
            response_dicts['body'] = response.json()
        except JSONDecodeError:
            # Record the JSONDecodeError in the logger instead of printing
            logger.warning('Response has no content or could not be serialized')
            response_dicts['body'] = ''
        response_dicts['text'] = response.text
        # Include headers in the response dictionary
        response_dicts['headers'] = dict(response.headers)

        logger.debug("POST request completed.")
        return response_dicts

    def put_request(self, url, data, header):
        try:
            response = requests.put(url=url, json=data, headers=header)
        except requests.RequestException as e:
            print('RequestException url: ' + url)
            print(e)
            return
        except Exception as e:
            print('Exception url: ' + url)
            print(e)
            return

        response_dicts = dict()
        response_dicts['code'] = response.status_code
        try:
            response_dicts['body'] = response.json()
        except JSONDecodeError:
            print('Response has no content or could not be serialized')
            response_dicts['body'] = ''
        response_dicts['text'] = response.text

        return response_dicts

    def delete_request(self, url, header):
        try:
            response = requests.delete(url=url, headers=header)
        except requests.RequestException as e:
            print('RequestException url: ' + url)
            print(e)
            return
        except Exception as e:
            print('Exception url: ' + url)
            print(e)
            return

        response_dicts = dict()
        response_dicts['code'] = response.status_code
        try:
            response_dicts['body'] = response.json()
        except JSONDecodeError:
            print('Response has no content or could not be serialized')
            response_dicts['body'] = ''
        response_dicts['text'] = response.text

        return response_dicts

    def head_request(self, url, header):
        try:
            response = requests.head(url=url, headers=header)
        except requests.RequestException as e:
            print('RequestException url: ' + url)
            print(e)
            return
        except Exception as e:
            print('Exception url: ' + url)
            print(e)
            return

        response_dicts = dict()
        response_dicts['code'] = response.status_code
        try:
            response_dicts['body'] = response.json()
        except JSONDecodeError:
            print('Response has no content or could not be serialized')
            response_dicts['body'] = ''
        response_dicts['text'] = response.text

        return response_dicts

    @allure.step('REQUEST')
    def request_api(self, method, path, header=None, extra_header=None, data=None):
        if header is None:
            header = self.header
        if extra_header:
            if header:
                header.update(extra_header)
            else:
                header = extra_header

        if method == 'GET':
            response = self.get_request(url=self.base_url + path, header=header)
        elif method == 'POST':
            response = self.post_request(url=self.base_url + path, data=data, header=header)
        elif method == 'PUT':
            response = self.put_request(url=self.base_url + path, data=data, header=header)
        elif method == 'DELETE':
            response = self.delete_request(url=self.base_url + path, header=header)
        elif method == 'HEAD':
            response = self.head_request(url=self.base_url + path, header=header)
        else:
            raise ValueError('This method is not supported : {}'.format(method))

        # Attach the response to the report
        allure.attach(response['text'], 'RESPONSE', allure.attachment_type.JSON)
        return response
