import uuid
import requests

from django.shortcuts import render, redirect
from django.contrib.auth.decorators import login_required
from django.contrib import messages
from django.http import JsonResponse
from django.views.decorators.csrf import csrf_exempt
from django.conf import settings
from django.utils.timezone import now

from .models import Organization, TopUpOrder, Coupon, TOPUP_PACKS, GST_PERCENT


# ------------------------------------------------------------------ #
# TOP-UP PAGE
# ------------------------------------------------------------------ #
@login_required(login_url='/login/')
def topup_page(request):
    org = request.user.org
    if not org:
        return redirect('dashboard')

    # Only allow top-up for paid plans
    if org.is_trial or org.trial_expired:
        messages.error(request, 'Top-up is available only for paid plan subscribers.')
        return redirect('upgrade')

    # Calculate amounts with GST for each pack
    packs_with_amounts = {}
    for key, pack in TOPUP_PACKS.items():
        gst   = round((pack['price'] * GST_PERCENT) / 100)
        total = pack['price'] + gst
        packs_with_amounts[key] = {
            **pack,
            'gst':   gst,
            'total': total,
        }

    return render(request, 'accounts/topup.html', {
        'org':   org,
        'packs': packs_with_amounts,
    })


# ------------------------------------------------------------------ #
# AJAX — APPLY COUPON ON TOPUP
# ------------------------------------------------------------------ #
@login_required(login_url='/login/')
def topup_apply_coupon(request):
    if request.method != 'POST':
        return JsonResponse({'success': False, 'error': 'Invalid request.'})

    code = request.POST.get('code', '').strip().upper()
    pack = request.POST.get('pack', '')

    if not code:
        return JsonResponse({'success': False, 'error': 'Please enter a coupon code.'})

    if pack not in TOPUP_PACKS:
        return JsonResponse({'success': False, 'error': 'Invalid pack selected.'})

    try:
        coupon = Coupon.objects.get(code=code)
    except Coupon.DoesNotExist:
        return JsonResponse({'success': False, 'error': 'Invalid coupon code.'})

    is_valid, msg = coupon.is_valid()
    if not is_valid:
        return JsonResponse({'success': False, 'error': msg})

    original = TOPUP_PACKS[pack]['price']
    discount = int(coupon.calculate_discount(original))
    after    = original - discount
    gst      = round((after * GST_PERCENT) / 100)
    total    = after + gst

    return JsonResponse({
        'success':  True,
        'message':  f'Coupon applied! You save ₹{discount}.',
        'discount': discount,
        'gst':      gst,
        'total':    total,
        'is_free':  total == 0,
    })


# ------------------------------------------------------------------ #
# CREATE CASHFREE ORDER FOR TOP-UP
# ------------------------------------------------------------------ #
@login_required(login_url='/login/')
def create_topup_order(request):
    if request.method != 'POST':
        return JsonResponse({'success': False, 'error': 'Invalid request.'})

    org         = request.user.org
    pack_key    = request.POST.get('pack', '')
    coupon_code = request.POST.get('coupon_code', '').strip().upper()

    if pack_key not in TOPUP_PACKS:
        return JsonResponse({'success': False, 'error': 'Invalid pack selected.'})

    pack = TOPUP_PACKS[pack_key]

    coupon_obj    = None
    discount      = 0
    if coupon_code:
        try:
            coupon_obj = Coupon.objects.get(code=coupon_code)
            is_valid, msg = coupon_obj.is_valid()
            if not is_valid:
                return JsonResponse({'success': False, 'error': msg})
            discount = int(coupon_obj.calculate_discount(pack['price']))
        except Coupon.DoesNotExist:
            return JsonResponse({'success': False, 'error': 'Invalid coupon code.'})

    after_discount = pack['price'] - discount
    gst            = round((after_discount * GST_PERCENT) / 100)
    total          = after_discount + gst

    # Free via coupon
    if total == 0:
        return JsonResponse({'success': True, 'is_free': True, 'pack': pack_key, 'coupon': coupon_code})

    order_id = f"TUP-{uuid.uuid4().hex[:12].upper()}"

    TopUpOrder.objects.create(
        org              = org,
        pack             = pack_key,
        verifications    = pack['verifications'],
        original_amount  = pack['price'],
        discount_amount  = discount,
        gst_amount       = gst,
        final_amount     = total,
        coupon           = coupon_obj,
        gateway_order_id = order_id,
        status           = 'pending',
    )

    cf_env   = getattr(settings, 'CASHFREE_ENV', 'sandbox')
    base_url = (
        'https://sandbox.cashfree.com/pg'
        if cf_env == 'sandbox'
        else 'https://api.cashfree.com/pg'
    )

    payload = {
        'order_id':       order_id,
        'order_amount':   total,
        'order_currency': 'INR',
        'customer_details': {
            'customer_id':    str(org.id),
            'customer_email': org.email,
            'customer_phone': org.phone or '9999999999',
            'customer_name':  request.user.name,
        },
        'order_meta': {
            'return_url': f"{settings.SITE_URL}/topup/success/?order_id={order_id}",
            'notify_url': f"{settings.SITE_URL}/topup/webhook/",
        },
        'order_note': f"Avighna — Top-up {pack['label']} ({pack['verifications']} verifications)",
    }

    headers = {
        'Content-Type':    'application/json',
        'x-api-version':   '2023-08-01',
        'x-client-id':     settings.CASHFREE_APP_ID,
        'x-client-secret': settings.CASHFREE_SECRET_KEY,
    }

    try:
        response = requests.post(f'{base_url}/orders', json=payload, headers=headers, timeout=10)
        data     = response.json()

        if response.status_code != 200 or 'payment_session_id' not in data:
            return JsonResponse({'success': False, 'error': data.get('message', 'Failed to create order.')})

        return JsonResponse({
            'success':            True,
            'is_free':            False,
            'payment_session_id': data['payment_session_id'],
            'order_id':           order_id,
            'amount':             total,
        })

    except Exception as e:
        return JsonResponse({'success': False, 'error': 'Payment gateway error. Please try again.'})


# ------------------------------------------------------------------ #
# FREE TOP-UP (100% coupon)
# ------------------------------------------------------------------ #
@login_required(login_url='/login/')
def activate_free_topup(request):
    if request.method != 'POST':
        return redirect('topup_page')

    org         = request.user.org
    pack_key    = request.POST.get('pack', '')
    coupon_code = request.POST.get('coupon_code', '').strip().upper()

    if pack_key not in TOPUP_PACKS:
        return redirect('topup_page')

    pack       = TOPUP_PACKS[pack_key]
    coupon_obj = None

    if coupon_code:
        try:
            coupon_obj = Coupon.objects.get(code=coupon_code)
        except Coupon.DoesNotExist:
            messages.error(request, 'Invalid coupon.')
            return redirect('topup_page')

    TopUpOrder.objects.create(
        org             = org,
        pack            = pack_key,
        verifications   = pack['verifications'],
        original_amount = pack['price'],
        discount_amount = pack['price'],
        gst_amount      = 0,
        final_amount    = 0,
        coupon          = coupon_obj,
        gateway         = 'free_coupon',
        status          = 'success',
    )

    if coupon_obj:
        coupon_obj.apply()

    org.add_topup(pack['verifications'])

    messages.success(request, f'{pack["verifications"]} verifications added to your account for free!')
    return redirect('dashboard')


# ------------------------------------------------------------------ #
# TOP-UP PAYMENT SUCCESS
# ------------------------------------------------------------------ #
@login_required(login_url='/login/')
def topup_success(request):
    order_id = request.GET.get('order_id', '')
    org      = request.user.org

    if not order_id or not org:
        return redirect('dashboard')

    try:
        order = TopUpOrder.objects.get(gateway_order_id=order_id, org=org)
    except TopUpOrder.DoesNotExist:
        return redirect('dashboard')

    cf_env   = getattr(settings, 'CASHFREE_ENV', 'sandbox')
    base_url = (
        'https://sandbox.cashfree.com/pg'
        if cf_env == 'sandbox'
        else 'https://api.cashfree.com/pg'
    )

    headers = {
        'x-api-version':   '2023-08-01',
        'x-client-id':     settings.CASHFREE_APP_ID,
        'x-client-secret': settings.CASHFREE_SECRET_KEY,
    }

    try:
        response = requests.get(
            f'{base_url}/orders/{order_id}/payments',
            headers=headers, timeout=10
        )
        data = response.json()

        cf_status = None
        if isinstance(data, list) and data:
            cf_status = data[0].get('payment_status', '')
        elif isinstance(data, dict):
            cf_status = data.get('payment_status', '')

        if cf_status == 'SUCCESS':
            _activate_topup(order)
            return render(request, 'accounts/topup_success.html', {
                'org':   org,
                'order': order,
            })
        else:
            order.status = 'failed'
            order.save(update_fields=['status'])
            return render(request, 'accounts/topup_failed.html', {'org': org})

    except Exception:
        # Fallback for sandbox
        _activate_topup(order)
        return render(request, 'accounts/topup_success.html', {
            'org': org, 'order': order
        })


def _activate_topup(order):
    if order.status == 'success':
        return
    order.status = 'success'
    order.save(update_fields=['status'])
    if order.coupon:
        order.coupon.apply()
    order.org.add_topup(order.verifications)


# ------------------------------------------------------------------ #
# TOP-UP WEBHOOK
# ------------------------------------------------------------------ #
@csrf_exempt
def topup_webhook(request):
    if request.method != 'POST':
        return JsonResponse({'status': 'error'}, status=400)

    try:
        import hmac, hashlib, json
        body      = request.body.decode('utf-8')
        signature = request.headers.get('x-webhook-signature', '')
        timestamp = request.headers.get('x-webhook-timestamp', '')
        secret    = settings.CASHFREE_SECRET_KEY
        raw       = timestamp + body
        expected  = hmac.new(
            secret.encode(), raw.encode(), hashlib.sha256
        ).hexdigest()

        if not hmac.compare_digest(expected, signature):
            return JsonResponse({'status': 'invalid signature'}, status=400)

        data     = json.loads(body)
        event    = data.get('type', '')
        order_id = data.get('data', {}).get('order', {}).get('order_id', '')

        if event == 'PAYMENT_SUCCESS_WEBHOOK' and order_id.startswith('TUP-'):
            try:
                order = TopUpOrder.objects.get(gateway_order_id=order_id)
                _activate_topup(order)
            except TopUpOrder.DoesNotExist:
                pass

        return JsonResponse({'status': 'ok'})

    except Exception as e:
        return JsonResponse({'status': 'error', 'detail': str(e)}, status=500)
