import json
import requests
from datacloud.dev_utils.logging.logger import get_basic_logger


logger = get_basic_logger(__name__)


class Segment(object):

    __slots__ = ['segment_name', 'segment_id']

    def __init__(self, segment_name, segment_id=None):
        self.segment_name = segment_name
        self.segment_id = segment_id

    def __str__(self):
        return '{} {}'.format(self.segment_name, self.segment_id)

    def __repr__(self):
        return self.__str__()


class _Endpoints(object):
    """Api endpoints wrapper

    api description: https://st.yandex-team.ru/AUDIENCE-163#1494964678000
    """
    def __init__(self):
        self._url = 'https://api-audience.yandex.ru/v1/management'
        self.upload_file_url = self._url + '/client/segments/upload_file'
        self.upload_csv_file_url = self._url + '/segments/upload_csv_file'
        self.confirm_url = self._url + '/segment/{segment_id}/confirm?ulogin={user_login}'
        self.delete_url = self._url + '/client/segment/{segment_id}?ulogin={user_login}'
        self.replace_segment = self._url + '/segment/{segment_id}/modify_data?modification_type=replace'  # noqa
        self.list_segments = self._url + '/client/segments?ulogin={target_user_login}'
        self.share_segment = self._url + '/segment/{segment_id}/grant'
        self.revoke_segment = self._url + '/segment/{segment_id}/grant?user_login={user_login}'


class AudienceApi(object):
    """Class to manage segments in Audience
    """
    def __init__(self, yt_client, user_login, token, verbose=True):
        """
        Attributes:
            user_login (str): Audience account to manage segments
            verbose (bool): Print logs or not
            yt_client (yt.wrapper.YtClient, optional)
        """
        self.yt_client = yt_client
        self.user_login = user_login
        self._token = token
        self.verbose = verbose
        self.api = _Endpoints()

    def log_message(self, msg):
        if self.verbose:
            logger.info(msg)

    @staticmethod
    def _assert_data(data):
        assert len(data) > 1, 'Data is empty'
        assert data[0] == 'phone,email'

    def _upload_id_values(self, url, data):
        self.log_message('Start upload_id_values')
        self._assert_data(data)
        response = requests.post(
            url,
            params={'ulogin': self.user_login},
            headers={'Authorization': self._token},
            files={'file': ('data-to-upload', '\n'.join(data))}
        )
        self.log_message('Response:\n{}'.format(response))
        return response

    def upload_id_values(self, data):
        return self._upload_id_values(self.api.upload_csv_file_url, data)

    def replace_id_values(self, segment_id, data):
        return self._upload_id_values(
            self.api.replace_segment.format(segment_id=segment_id), data)

    def confirm(self, segment_id, segment_name, content_type='crm', is_hashed=True):
        self.log_message('Start confirm {} {}'.format(segment_id, segment_name))
        response = requests.post(
            self.api.confirm_url.format(segment_id=segment_id,
                                        user_login=self.user_login),
            headers={'Authorization': self._token},
            data=json.dumps({
                'segment': {
                    'id': segment_id,
                    'name': segment_name,
                    'hashed': is_hashed,
                    'content_type': content_type,
                }
            })
        )
        self.log_message('End confirm {} {}'.format(segment_id, segment_name))
        return response

    def get_segment_id_from_response(self, response_obj):
        """Get Audience Segment Id from http response

        Attributes:
            response_obj (requests.response)
        """
        res_json = response_obj.json()
        segment_id = res_json['segment']['id']
        self.log_message('segment id: {}'.format(segment_id))
        return segment_id

    def share(self, segment_id, user_id):
        user_id = str(user_id)
        response = requests.put(
            self.api.share_segment.format(segment_id=segment_id),
            headers={'Authorization': self._token},
            data=json.dumps({
                'grant': {'user_login': user_id},
            }),
        )
        return response
        self.log_message('Response:\n{}'.format(response))
        print(response.json())

    def revoke(self, segment_id, user_id):
        user_id = str(user_id)
        response = requests.delete(
            self.api.revoke_segment.format(segment_id=segment_id, user_login=user_id),
            headers={'Authorization': self._token},
        )
        return response
        self.log_message('Response:\n{}'.format(response))
        print(response.json())
