import json
import logging

import requests
from django.conf import settings

from app.api import api
from app.api.api_accessor import APIAccessor
from app.util import util
from django.template.loader import get_template
from xhtml2pdf import pisa

log = logging.getLogger(__name__)


class CreditFairAccessor(APIAccessor):
    STATUS_SUCCESS = "OK"
    STATUS_FAIL = "FAIL"

    TOKEN_AUTH_ERROR = "CF10034"
    CODE_DOCUMENT_ALREADY_UPLOADED = 'CF10044'
    CODE_DOCUMENT_ALREADY_EXISTS = 'CF11409'

    URL_UPLOAD_DOCUMENT = f"{settings.EMI_CHECKOUT_END_POINT}/api/upload-document"
    URL_CREATE_CUSTOMER = f"{settings.EMI_CHECKOUT_END_POINT}/api/create-customer"
    BUREAU_RESPONSE = f"{settings.BUREAU_END_POINT}/api/get-bureau-response"
    AUTO_DECISION_RESPONSE = settings.AUTO_DECISION_END_POINT + "/api/run-auto-decision?application_id={}"

    @classmethod
    def upload_document(cls, loan_application_id, document_name, document_format, document_content, document_password,
                        bearer_token, client_id, client_secret):
        data = {
            "application_id": loan_application_id,
            "docName": document_name,
            "docFormat": document_format,
            "docPassword": document_password,
            "docContent": document_content
        }
        headers = cls.get_authorization_headers(bearer_token, client_id, client_secret)

        log.debug(f"Request data: {loan_application_id} {document_name} {document_format} {document_password is None}")

        status, response = cls.request_skip_logging(
            requests.request, method="post", url=cls.URL_UPLOAD_DOCUMENT, data=json.dumps(data), headers=headers)

        if util.is_status_failed(status) and response.json().get('error') == 'Bad Request':
            log.error('Unable to upload document')
            return api.UNABLE_TO_UPLOAD_DOCUMENT
        elif util.is_status_failed(status) and \
                response.json().get('error', {}).get('code') not in [CreditFairAccessor.CODE_DOCUMENT_ALREADY_UPLOADED,
                                                                     CreditFairAccessor.CODE_DOCUMENT_ALREADY_EXISTS]:
            log.error('Unable to upload document')
            return api.UNABLE_TO_UPLOAD_DOCUMENT
        elif util.is_status_failed(status) and response.json().get('error', {}).get(
                'code') == CreditFairAccessor.TOKEN_AUTH_ERROR:
            log.error('Invalid user token')
            return api.AUTHORIZATION_FAILED

        return api.SUCCESS

    @classmethod
    def create_customer(cls, phone_number, email, first_name, last_name, merchant_id, center_id, product_id,
                        loan_amount, gender, pincode):
        data = {
            "first_name": first_name,
            "last_name": last_name,
            "email": email,
            "phone": phone_number,
            "merchant_id": merchant_id,
            "center_id": center_id,
            "product_id": product_id,
            "loan_amount": loan_amount,
            "gender": gender,
            "pincode": pincode
        }

        headers = {
            'X-Client-Id': settings.CREDIT_FAIR_CLIENT_ID,
            'X-Client-Secret': settings.CREDIT_FAIR_CLIENT_SECRET,
            'Content-Type': 'application/json'
        }

        status, response = cls.request(requests.request, method="post", url=cls.URL_CREATE_CUSTOMER,
                                       data=json.dumps(data), headers=headers)

        if util.is_status_failed(status) or not response.get("data", {}).get("application_id"):
            if response.status_code == 409 and response.json().get("error", {}).get(
                    "message", {}) == "User already exists":
                return api.USER_ALREADY_EXISTS, ''

            log.debug('Unable to create customer')
            return api.UNABLE_TO_CREATE_CUSTOMER, ''

        return api.SUCCESS, response['data']['application_id']

    @classmethod
    def get_authorization_headers(cls, bearer_token, client_id=None, client_secret=None):
        if bearer_token:
            return {
                "Content-Type": "application/json",
                "Authorization": bearer_token
            }
        else:
            return {
                "Content-Type": "application/json",
                "X-Client-Id": client_id,
                "X-Client-Secret": client_secret
            }

    @classmethod
    def fetch_bureau(cls, application_id, applicant_type, first_name, last_name, pan, dob, mobile_number,
                     address_street, address_city, address_state, address_pincode, loan_amount, bearer_token,
                     client_id, client_secret):
        data = {
            "application_id": application_id,
            "applicant_type": applicant_type,
            "request_type": "customer",
            "first_name": first_name,
            "last_name": last_name,
            "pan_card": pan,
            "document_type": "PAN_DETAILED",
            "consent": "Y",
            "mobile_number": mobile_number,
            "gender": "1",
            "dob": dob,
            "address": address_street,
            "state": address_state,
            "city": address_city,
            "postal_code": address_pincode,
            "loan_amount": loan_amount,
            "vendor": "piggy"
        }

        headers = cls.get_authorization_headers(bearer_token, client_id, client_secret)

        status, response = cls.request(
            requests.request, method="post", url=cls.BUREAU_RESPONSE, data=json.dumps(data), headers=headers)

        if util.is_status_failed(status):
            return api.UNABLE_TO_FETCH_BUREAU_RESPONSE

        return api.SUCCESS

    @classmethod
    def run_auto_decision(cls, application_id, bearer_token, client_id, client_secret):
        url = cls.AUTO_DECISION_RESPONSE.format(application_id)
        if bearer_token:
            headers = {
                "Authorization": bearer_token
            }
        else:
            headers = {
                "X-Client-Id": client_id,
                "X-Client-Secret": client_secret
            }

        status, response = cls.request(requests.request, method="get", url=url, headers=headers)

        if util.is_status_failed(status):
            return api.UNABLE_TO_RUN_AUTO_DECISION

        if response.get('message') == "Approved":
            return api.SUCCESS

        return api.UNABLE_TO_RUN_AUTO_DECISION
