import logging
from urllib.parse import unquote_plus

from django.conf import settings
from django.http import HttpResponseRedirect
from django.shortcuts import render
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.payment.accessor.payment_accessor import PaymentTransactionAccessor
from paytmchecksum import PaytmChecksum
from app.payment.mandate import Payment
from app.user.user import User
from app.loan_offer.loan_offer import LoanOffer
from app.util import util
import json

log = logging.getLogger(__name__)


def order_payment(request):
    # http://127.0.0.1:8000/v1/order/payment/?application_id=4ewpdErX6A1yDY1qvmy2
    # TODO check cookie for auth
    hashed_application_id = request.GET.get("application_id")
    redirect_url = request.GET.get("redirect_url")

    settings.REDIRECT_FRONTEND_HOME_URL = settings.CREDITFAIR_FRONTEND_HOME_URL

    if redirect_url:
        settings.REDIRECT_FRONTEND_HOME_URL = redirect_url

    application_id = LoanApplication.get_application_id_from_hash(hashed_application_id)
    if not application_id:
        return HttpResponseRedirect(
            f"{settings.FRONTEND_HOME_URL}/customer/loan/application/error/?message=Invalid Loan Application")

    loan_application = LoanApplication.get_loan_application(application_id)
    if not loan_application:
        return HttpResponseRedirect(
            f"{settings.FRONTEND_HOME_URL}/customer/loan/application/error/?message=Invalid Loan Application")

    redirect_url = f"{settings.BACKEND_HOME_URL}/v1/order/payment/call_back/"

    status, recorded_transactions_details = LoanApplication(loan_application).record_payment_transactions()
    if util.is_status_failed(status):
        return HttpResponseRedirect(
            f"{settings.FRONTEND_HOME_URL}/v1/customer/loan/application/error/?message=Invalid Loan Application")

    status, payment_context, response = LoanApplication(loan_application).get_paytm_payment_context(
        redirect_url,
        recorded_transactions_details.get('online_processing_id'),
        recorded_transactions_details.get('online_advanced_id'))
    if util.is_status_failed(status):
        return HttpResponseRedirect(
            f"{settings.FRONTEND_HOME_URL}/v1/customer/loan/application/error/?message=Invalid Loan Application")

    Payment.update_order_id_in_transactions(payment_context['order_id'], recorded_transactions_details)

    if not payment_context:
        return HttpResponseRedirect(
            f"{settings.FRONTEND_HOME_URL}/v1/customer/loan/application/error/?message=Invalid Loan Application")

    return render(request, "paytm_place_order.html", payment_context)


def validate_setup_mandate_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(['POST'])
@authentication_classes((JWTOrAPIKeyAuthentication,))
@permission_classes((IsAuthenticated,))
def setup_mandate(request):
    response_builder = ResponseBuilder()
    data = request.data

    loan_application_id = data.get("application_id")
    if loan_application_id.isnumeric():
        loan_application_id = int(loan_application_id)
    loan_application_id = CFHashIds().encode(loan_application_id) if CFHashIds().encode(loan_application_id) != '' else loan_application_id
    redirect_url = data.get("redirect_url", "")
    source = data.get('source')
    status, loan_application = validate_setup_mandate_inputs(loan_application_id)
    if util.is_status_failed(status):
        return response_builder.get_bad_request_response(status)

    loan_application = LoanApplication(loan_application)
    application_id = loan_application.get_loan_application_id()

    emi_calculation = LoanOffer.get_emi_calculation(application_id)
    if not emi_calculation:
        log.error('Emi calculations not found')
        return response_builder.get_bad_request_response(api.MANDATE_SETUP_REQUEST_FAILED)

    status, mandate_setup_link = loan_application.get_mandate_setup_link(
        application_id, emi_calculation, redirect_url)
    if util.is_status_failed(status):
        return response_builder.get_ok200_fail_response(status)

    result = {
        'mandate_registration_url': mandate_setup_link
    }

    if source == 'no_touch':
        return response_builder.solar_success().ok_200().message('Mandate link generated').result_object(result).get_solar_response()
    return response_builder.success().ok_200().message(
        'Mandate link generated').result_object(result).get_response()


def validate_generate_payment_link_inputs(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(['POST'])
@authentication_classes((JWTOrAPIKeyAuthentication,))
@permission_classes((IsAuthenticated,))
def generate_payment_link(request):
    response_builder = ResponseBuilder()
    data = request.data

    application_id = data.get('application_id')
    if str(application_id).isnumeric():
        application_id = int(application_id)
    application_id = CFHashIds().encode(application_id) if CFHashIds().encode(application_id) != '' else application_id
    redirect_url = data.get('redirect_url')
    source = data.get('source')

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

    is_payment_required = LoanApplication(loan_application).is_payment_required()

    payment_link = None
    if is_payment_required:
        payment_link = LoanApplication(loan_application).get_payment_link(redirect_url)

    result = {
        'payment_link': payment_link,
        'is_payment_required': is_payment_required
    }

    if source == 'no_touch':
        return (response_builder.solar_success().ok_200().message('Payment link generated').result_object(result)
                .get_solar_response())

    return response_builder.success().ok_200().message('Payment link generated').result_object(result).get_response()


@api_view(['POST', 'GET'])
def call_back(request):
    # {'BANKNAME': ['OTHERS'], 'BANKTXNID': ['777001310151559'], 'CHECKSUMHASH': ['kpK0c0FKFo2QT7rJK/qIQrokzYbPJZNVB9C
    # r4HJzKvK4JEqaiSA5wgyI6lRPukiGt0Pbc9DwQpkCINSsQUHn03/iZzgnmKzz+JEwk/xkzAM='],
    #  'CURRENCY': ['INR'], 'GATEWAYNAME': ['HDFC'], 'MID': ['KMglob21546666561510'], 'ORDERID': ['8fb8fb37c3'],
    #  'PAYMENTMODE': ['DC'], RESPCODE': ['810'], 'RESPMSG': ['Payment failed due to a technical error. Please try
    #  after some time.'], 'STATUS': ['TXN_FAILURE'], 'TXNAMOUNT': ['33399.00'], 'TXNDATE': ['2023-09-08 09:23:32.0'],
    #  'TXNID': ['20230908011650000906836261153896702']}

    if request.method == 'GET':
        return HttpResponseRedirect(
            f"{settings.REDIRECT_FRONTEND_HOME_URL}/payment/redirect/url/?paymentStatus=TXN_FAILURE")

    data = request.data

    checksum = data.get('CHECKSUMHASH')
    order_id = data.get('ORDERID')
    payment_status = data.get('STATUS')

    dict_data = dict(data)
    dict_data.pop('CHECKSUMHASH')
    normalized_data = {key: value[0] for key, value in dict_data.items()}

    status = PaytmChecksum.verifySignature(normalized_data, settings.PAYTM_MERCHANT_KEY, checksum)

    if util.is_status_failed(status):
        Payment.update_online_payment_transaction_status(order_id, "TXN_FAILURE")
        return HttpResponseRedirect(
            f"{settings.REDIRECT_FRONTEND_HOME_URL}/payment/redirect/url/?paymentStatus=TXN_FAILURE")

    Payment.update_online_payment_transaction_status(order_id, payment_status)

    if settings.REDIRECT_FRONTEND_HOME_URL.split('/')[-1] == 'customer':
        return HttpResponseRedirect(
            f"{settings.REDIRECT_FRONTEND_HOME_URL}/payment/redirect/url/?paymentStatus={payment_status}")
    else:
        if '?' in settings.REDIRECT_FRONTEND_HOME_URL:
            return HttpResponseRedirect(
                f"{settings.REDIRECT_FRONTEND_HOME_URL}&paymentStatus={payment_status}")
        else:
            return HttpResponseRedirect(
                f"{settings.REDIRECT_FRONTEND_HOME_URL}?paymentStatus={payment_status}")
