from django.shortcuts import render, redirect, get_object_or_404
from django.contrib.auth.decorators import login_required
from django.http import JsonResponse, HttpResponse
from django.views.decorators.csrf import csrf_exempt
from django.views.decorators.http import require_http_methods
from django.contrib import messages
from django.urls import reverse
from django.utils import timezone
from datetime import timedelta
import json
import logging

from tenants.models import Tenant
from .models import Subscription, MpesaPayment
from .mpesa import MpesaAPI

logger = logging.getLogger(__name__)

@login_required
def subscription_plans(request):
    """Display subscription plans"""
    tenant = request.user.tenant_memberships.first()
    if tenant:
        tenant = tenant.tenant

    plans = [
        {
            'name': 'Basic',
            'code': 'basic',
            'price': 2000,
            'features': [
                '1 Shop',
                '3 Users',
                'Basic Reports',
                'Email Support'
            ]
        },
        {
            'name': 'Standard',
            'code': 'standard',
            'price': 5000,
            'features': [
                '3 Shops',
                '10 Users',
                'Advanced Reports',
                'Phone Support',
                'Multi-location Support'
            ]
        },
        {
            'name': 'Premium',
            'code': 'premium',
            'price': 10000,
            'features': [
                'Unlimited Shops',
                'Unlimited Users',
                'All Reports',
                'Priority Support',
                'API Access',
                'Custom Features'
            ]
        }
    ]

    return render(request, 'billing/subscription_plans.html', {
        'plans': plans,
        'current_tenant': tenant
    })

@login_required
def initiate_subscription(request, plan_code):
    """Initiate subscription payment"""
    if request.method == 'POST':
        tenant_membership = request.user.tenant_memberships.first()
        if not tenant_membership or tenant_membership.role not in ['owner', 'admin']:
            messages.error(request, 'You do not have permission to manage subscriptions.')
            return redirect('billing:subscription_plans')

        tenant = tenant_membership.tenant
        phone_number = request.POST.get('phone_number')

        if not phone_number:
            messages.error(request, 'Phone number is required.')
            return redirect('billing:subscription_plans')

        # Get plan details
        plan_prices = {
            'basic': 2000,
            'standard': 5000,
            'premium': 10000,
        }

        amount = plan_prices.get(plan_code)
        if not amount:
            messages.error(request, 'Invalid plan selected.')
            return redirect('billing:subscription_plans')

        # Create subscription record
        start_date = timezone.now()
        end_date = start_date + timedelta(days=30)  # 30-day subscription

        # Schema separation provides tenant isolation - no tenant assignment needed
        subscription = Subscription.objects.create(
            plan=plan_code,
            amount=amount,
            start_date=start_date,
            end_date=end_date,
            payment_status='pending'
        )

        # Create M-Pesa payment record
        mpesa_payment = MpesaPayment.objects.create(
            subscription=subscription,
            phone_number=phone_number,
            amount=amount,
            status='pending'
        )

        # Initiate M-Pesa payment
        mpesa_api = MpesaAPI()
        callback_url = request.build_absolute_uri(reverse('billing:mpesa_callback'))

        result = mpesa_api.stk_push(
            phone_number=phone_number,
            amount=amount,
            account_reference=f"SUB-{subscription.id}",
            transaction_desc=f"Subscription {plan_code.title()} Plan",
            callback_url=callback_url
        )

        if result.get('success'):
            mpesa_payment.merchant_request_id = result.get('merchant_request_id')
            mpesa_payment.checkout_request_id = result.get('checkout_request_id')
            mpesa_payment.save()

            messages.success(request, 'Payment request sent to your phone. Please complete the payment.')
            return redirect('billing:payment_status', payment_id=mpesa_payment.id)
        else:
            mpesa_payment.status = 'failed'
            mpesa_payment.result_desc = result.get('message')
            mpesa_payment.save()

            messages.error(request, f"Payment failed: {result.get('message')}")
            return redirect('billing:subscription_plans')

    return redirect('billing:subscription_plans')

@login_required
def payment_status(request, payment_id):
    """Handle M-Pesa payment status and callbacks"""
    payment_id = request.GET.get('payment_id')
    status = request.GET.get('status', 'pending')

    context = {
        'payment_id': payment_id,
        'status': status,
    }

    if status == 'success' and payment_id:
        try:
            # Update subscription status
            payment = MpesaPayment.objects.get(id=payment_id)
            if payment.status == 'pending':
                payment.status = 'completed'
                payment.save()

                # Activate tenant subscription
                tenant = payment.subscription.tenant
                tenant.status = 'active'
                tenant.subscription_ends_at = timezone.now() + timedelta(days=30)
                tenant.save()

                context['tenant'] = tenant
                context['message'] = 'Payment successful! Your subscription is now active.'

        except MpesaPayment.DoesNotExist:
            context['message'] = 'Payment record not found.'

    return render(request, 'billing/payment_status.html', context)

@csrf_exempt
@require_http_methods(["POST"])
def mpesa_callback(request):
    """Handle M-Pesa callback"""
    try:
        data = json.loads(request.body)
        logger.info(f"M-Pesa callback received: {data}")

        # Extract callback data
        stk_callback = data.get('Body', {}).get('stkCallback', {})
        merchant_request_id = stk_callback.get('MerchantRequestID')
        checkout_request_id = stk_callback.get('CheckoutRequestID')
        result_code = stk_callback.get('ResultCode')
        result_desc = stk_callback.get('ResultDesc')

        # Find the payment record
        try:
            payment = MpesaPayment.objects.get(
                checkout_request_id=checkout_request_id
            )
        except MpesaPayment.DoesNotExist:
            logger.error(f"Payment not found for checkout_request_id: {checkout_request_id}")
            return HttpResponse("OK")

        if result_code == 0:  # Success
            # Extract payment details
            callback_metadata = stk_callback.get('CallbackMetadata', {}).get('Item', [])

            amount = None
            mpesa_receipt_number = None
            transaction_date = None
            phone_number = None

            for item in callback_metadata:
                name = item.get('Name')
                value = item.get('Value')

                if name == 'Amount':
                    amount = value
                elif name == 'MpesaReceiptNumber':
                    mpesa_receipt_number = value
                elif name == 'TransactionDate':
                    transaction_date = value
                elif name == 'PhoneNumber':
                    phone_number = value

            # Update payment record
            payment.status = 'success'
            payment.mpesa_receipt_number = mpesa_receipt_number
            payment.result_desc = result_desc
            if transaction_date:
                try:
                    from datetime import datetime
                    payment.transaction_date = datetime.strptime(str(transaction_date), '%Y%m%d%H%M%S')
                except:
                    payment.transaction_date = timezone.now()
            payment.save()

            # Update subscription
            subscription = payment.subscription
            subscription.payment_status = 'paid'
            subscription.paid_at = timezone.now()
            subscription.mpesa_reference = mpesa_receipt_number
            subscription.save()

            # Update tenant status
            tenant = subscription.tenant
            tenant.status = 'active'
            tenant.plan = subscription.plan
            tenant.subscription_ends_at = subscription.end_date
            tenant.save()

            logger.info(f"Payment successful for subscription {subscription.id}")

        else:  # Failed
            payment.status = 'failed'
            payment.result_desc = result_desc
            payment.save()

            logger.warning(f"Payment failed for subscription {payment.subscription.id}: {result_desc}")

        return HttpResponse("OK")

    except Exception as e:
        logger.error(f"M-Pesa callback error: {e}")
        return HttpResponse("ERROR", status=500)

@login_required
def subscription_history(request):
    """View subscription history"""
    # Schema separation provides tenant isolation - no tenant filtering needed
    subscriptions = Subscription.objects.all().order_by('-created_at')

    return render(request, 'billing/subscription_history.html', {
        'subscriptions': subscriptions
    })

@login_required
def subscription_detail(request, subscription_id):
    """View subscription detail"""
    # Schema separation provides tenant isolation - no tenant filtering needed
    subscription = get_object_or_404(Subscription, id=subscription_id)
    
    return render(request, 'billing/subscription_detail.html', {
        'subscription': subscription
    })

@login_required
def retry_payment(request, subscription_id):
    """Retry failed payment"""
    # Schema separation provides tenant isolation - no tenant filtering needed
    subscription = get_object_or_404(
        Subscription, 
        id=subscription_id, 
        payment_status='failed'
    )
    
    if request.method == 'POST':
        phone_number = request.POST.get('phone_number')
        if not phone_number:
            messages.error(request, 'Phone number is required.')
            return redirect('billing:subscription_detail', subscription_id=subscription.id)

        # Create new M-Pesa payment record for retry
        mpesa_payment = MpesaPayment.objects.create(
            subscription=subscription,
            phone_number=phone_number,
            amount=subscription.amount,
            status='pending'
        )

        # Initiate M-Pesa payment
        mpesa_api = MpesaAPI()
        callback_url = request.build_absolute_uri(reverse('billing:mpesa_callback'))

        result = mpesa_api.stk_push(
            phone_number=phone_number,
            amount=subscription.amount,
            account_reference=f"RETRY-{subscription.id}",
            transaction_desc=f"Retry {subscription.get_plan_display()} Plan",
            callback_url=callback_url
        )

        if result.get('success'):
            mpesa_payment.merchant_request_id = result.get('merchant_request_id')
            mpesa_payment.checkout_request_id = result.get('checkout_request_id')
            mpesa_payment.save()

            messages.success(request, 'Payment retry initiated. Please complete the payment on your phone.')
            return redirect('billing:payment_status', payment_id=mpesa_payment.id)
        else:
            mpesa_payment.status = 'failed'
            mpesa_payment.result_desc = result.get('message')
            mpesa_payment.save()

            messages.error(request, f"Payment retry failed: {result.get('message')}")
            return redirect('billing:subscription_detail', subscription_id=subscription.id)

    return render(request, 'billing/retry_payment.html', {
        'subscription': subscription
    })

def tenant_expired(request, tenant_code):
    """Show tenant expiry page with payment details"""
    try:
        tenant = Tenant.objects.get(tenant_code=tenant_code, status='expired')
    except Tenant.DoesNotExist:
        messages.error(request, 'Tenant not found or not expired.')
        return redirect('landing:home')
    
    return render(request, 'billing/tenant_expired.html', {
        'tenant': tenant
    })