import logging

from rest_framework.decorators import api_view, authentication_classes, permission_classes
from rest_framework.permissions import IsAuthenticated

from app.encryption.hashid import CFHashIds
from backend.authentication import JWTOrAPIKeyAuthentication

from app.api import api
from app.api.response_builder import ResponseBuilder
from app.loan_application.loan_application import LoanApplication
from app.loan_offer.loan_offer import LoanOffer
from app.util import util

log = logging.getLogger(__name__)


def validate_loan_offer(first_name, last_name, email, phone_number, merchant_id, center_id, product_id, loan_amount):
    if not (first_name and last_name and email and phone_number and merchant_id and center_id and product_id
            and loan_amount):
        return api.INVALID_INPUT

    return api.SUCCESS


def validate_get_applicable_offer_input(application_id):
    if not application_id:
        return api.INVALID_INPUT, None

    loan_application = LoanApplication.get_loan_application(hashed_loan_application_id=application_id)
    if not loan_application:
        return api.INVALID_INPUT, None

    return api.SUCCESS, loan_application


@api_view(['GET'])
@authentication_classes((JWTOrAPIKeyAuthentication,))
@permission_classes((IsAuthenticated,))
def get_applicable_offer_details(request):
    data = request.GET
    response_builder = ResponseBuilder()

    application_id = data.get('application_id')

    status, loan_application = validate_get_applicable_offer_input(application_id)
    if util.is_status_failed(status):
        return response_builder.get_bad_request_response(status)

    status, offers = LoanOffer.get_applicable_offers(loan_application)
    if util.is_status_failed(status):
        return response_builder.get_ok200_fail_response(status)

    result = {
        "amount": LoanApplication(loan_application).get_amount(),
        "emi_summary": offers
    }

    return response_builder.success().ok_200().message('Loan offers fetched').result_object(result).get_response()


def validate_update_loan_offer_inputs(loan_offer_id, loan_application_id):
    if not (loan_offer_id and loan_application_id):
        return api.INVALID_INPUT, None, None

    loan_application = LoanApplication.get_loan_application(hashed_loan_application_id=loan_application_id)
    if not loan_application:
        log.debug("Loan application not found")
        return api.INVALID_INPUT, None, None

    loan_offer = LoanOffer.get_loan_offer(
        LoanApplication.get_application_id_from_hash(loan_application_id), loan_offer_id)
    if not loan_offer:
        log.debug("Loan offer not found")
        return api.INVALID_INPUT, None, None

    return api.SUCCESS, loan_application, loan_offer


@api_view(['POST'])
@authentication_classes((JWTOrAPIKeyAuthentication,))
@permission_classes((IsAuthenticated,))
def update_offer_details(request):
    data = request.data
    response_builder = ResponseBuilder()

    loan_offer_id = data.get('offer_id')
    loan_application_id = data.get('application_id')
    loan_application_id = CFHashIds().encode(int(loan_application_id)) if str(loan_application_id).isnumeric() else loan_application_id
    source = data.get('source')

    status, loan_application, loan_offer = validate_update_loan_offer_inputs(loan_offer_id, loan_application_id)
    if util.is_status_failed(status):
        if source == 'no_touch':
            return (response_builder.solar_fail().ok_200().message('Please pass all the required parameter')
                    .get_solar_response())
        return response_builder.get_bad_request_response(status)

    status = LoanOffer(loan_offer).update_loan_offer(loan_application, request.headers.get('Origin'))
    if util.is_status_failed(status):
        if source == 'no_touch':
            return (response_builder.solar_fail().ok_200().message('Please pass all the required parameter')
                    .get_solar_response())
        return response_builder.get_ok200_fail_response(status)
    if source == 'no_touch':
        return response_builder.solar_success().ok_200().message('Loan offer updated').get_solar_response()
    return response_builder.success().ok_200().message('Loan offer updated').get_response()


def validate_get_loan_offer_details_inputs(loan_application_id):
    if not loan_application_id:
        return api.INVALID_INPUT, None

    loan_application = LoanApplication.get_loan_application(hashed_loan_application_id=loan_application_id)
    if not loan_application:
        return api.INVALID_INPUT, None

    return api.SUCCESS, loan_application


@api_view(['GET'])
@authentication_classes((JWTOrAPIKeyAuthentication,))
@permission_classes((IsAuthenticated,))
def get_loan_offer_details(request):
    data = request.GET
    response_builder = ResponseBuilder()

    loan_application_id = data.get('application_id')

    status, loan_application = validate_get_loan_offer_details_inputs(loan_application_id)
    if util.is_status_failed(status):
        return response_builder.get_bad_request_response(status)

    status, offer_details = LoanOffer.get_loan_offer_details(loan_application)
    if util.is_status_failed(status):
        return response_builder.get_ok200_fail_response(status)

    result = {
        "offer": offer_details
    }
    return response_builder.success().ok_200().message('Loan offer updated').result_object(result).get_response()


@api_view(['POST'])
def get_loan_summary(request):
    data = request.data
    response_builder = ResponseBuilder()

    loan_application_id = CFHashIds().encode(int(data.get('application_id')))

    status, loan_application = validate_get_loan_offer_details_inputs(loan_application_id)
    if util.is_status_failed(status):
        return response_builder.get_bad_request_response(status)

    status, offer_details = LoanOffer.get_loan_offer_details(loan_application)
    if util.is_status_failed(status):
        return response_builder.get_ok200_fail_response(status)

    result = {
        "offer": offer_details
    }
    return response_builder.solar_success().ok_200().message('Loan summary').result_object(result).get_solar_response()