import logging
import requests

from django.conf import settings
from django.core.files.base import ContentFile
from django.utils import timezone
from django.utils.functional import cached_property

from intranet.femida.src.hh.exceptions import (
    HeadhunterError,
    HeadhunterOauthError,
    HeadhunterTokenExpiredError,
)
from intranet.femida.src.hh.models import HHOauthToken


logger = logging.getLogger(__name__)


class HeadhunterAPI:

    def __init__(self, user):
        self.user = user
        self._cached_resumes = {}

    @cached_property
    def access_token(self):
        token = HHOauthToken.objects.filter(user=self.user).first()
        if not token:
            raise HeadhunterOauthError('hh_token_not_found')
        if token.expiry_date <= timezone.now():
            raise HeadhunterTokenExpiredError
        return token.access_token

    @property
    def headers(self):
        return {
            'User-Agent': settings.HH_USER_AGENT,
            'Authorization': 'Bearer %s' % self.access_token,
        }

    def _request(self, method, url, params=None, data=None, files=None):
        if not url.startswith('http'):
            url = settings.HH_API_URL + url

        try:
            response = requests.request(
                method=method,
                url=url,
                params=params,
                data=data,
                files=files,
                timeout=10,
                headers=self.headers,
            )
        except (requests.ConnectionError, requests.Timeout):
            logger.exception('HH is not responding')
            raise HeadhunterError('hh_no_response')

        try:
            response_data = response.json()
        except ValueError:
            logger.exception('Error during parsing HH response')
            raise HeadhunterError('hh_invalid_response')

        if 'errors' in response_data:
            logger.error('Error during HH request: %s', response_data['errors'])
            error = response_data['errors'][0]
            if error['type'] == 'oauth':
                if error['value'] == 'token_expired':
                    raise HeadhunterTokenExpiredError
                raise HeadhunterOauthError
            raise HeadhunterError('hh_%s' % error['type'])

        return response_data

    def _post(self, url, data=None, files=None):
        return self._request('POST', url, data=data, files=files)

    def _get(self, url, params=None):
        return self._request('GET', url, params=params)

    def get_me(self):
        return self._get('me')

    def get_resume(self, resume_id):
        if resume_id not in self._cached_resumes:
            url = 'resumes/{id}'.format(id=resume_id)
            self._cached_resumes[resume_id] = self._get(url)
        return self._cached_resumes[resume_id]

    def get_full_resume(self, resume_id):
        data = self.get_resume(resume_id)
        hidden_fields = {field['id'] for field in data['hidden_fields']}
        has_missing_fields = 'names_and_photo' in hidden_fields
        # если can_view_full_info = False, значит в резюме не открыты контакты
        is_contacts_request_required = (
            not data['can_view_full_info']
            and not has_missing_fields
        )
        if is_contacts_request_required:
            logger.info('Getting resume %s with contacts', resume_id)
            url = data['actions']['get_with_contact']['url']
            data = self._get(url)

        data['has_missing_fields'] = has_missing_fields
        return data

    def download_resume_by_url(self, url):
        response = requests.get(
            url=url,
            headers=self.headers,
            timeout=30,
        )
        return ContentFile(
            content=response.content,
            name='resume',
        )

    def download_resume_by_type(self, resume_id, file_type):
        data = self.get_resume(resume_id)
        return self.download_resume_by_url(data['download'][file_type]['url'])

    def __repr__(self):
        return f'HeadhunterAPI for {self.user.username}'
