# sales/views/receipts.py
import logging
import json
import csv
import string
from datetime import datetime, timedelta
from decimal import Decimal
import qrcode
import base64
from io import BytesIO

from django.shortcuts import render, redirect, get_object_or_404
from django.contrib import messages
from django.contrib.auth.decorators import login_required
from django.http import JsonResponse, HttpResponse
from django.views.decorators.csrf import csrf_exempt
from django.utils import timezone
from django.db import transaction
from django.db.models import Sum, Count, Q, F
from django.core.exceptions import PermissionDenied

from inventory.models import Product
from core.models import (
    SystemSettings, CustomField, DynamicFormData,
    SubscriptionPlan, License, Branch,
)
from core.utils import check_limit_or_block, filter_orders_by_user_branch
from accounts.decorators import role_required
from sales.models import (
    POSOrder, POSOrderItem, PaymentTransaction,
    DailySalesSummary, UnusualTransaction, Customer,
)
from sales.forms import POSOrderForm, POSOrderItemForm

logger = logging.getLogger(__name__)

BASE36_ALPHABET = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"


def _to_base36(num: int) -> str:
    """Convert positive int to base36 (same as JS toString(36))."""
    if num == 0:
        return "0"
    result = ""
    while num > 0:
        num, rem = divmod(num, 36)
        result = BASE36_ALPHABET[rem] + result
    return result


def generate_verification_code(order: POSOrder, system_settings: SystemSettings = None) -> str:
    """
    Generate the same verification code as the JS on the receipt template.
    Raw string: order_number | created_at(YmdHis) | business_name
    Hash: 32-bit int, multiplied by 31 each step, base36, padded to 8, SP-XXXX-XXXX.
    """
    if system_settings is None:
        system_settings = SystemSettings.objects.first()

    business_name = system_settings.business_name if system_settings else ""
    created_str = order.created_at.strftime("%Y%m%d%H%M%S")

    raw = f"{order.order_number}|{created_str}|{business_name}"

    # Same hashing approach as JS
    h = 0
    for ch in raw:
        h = (h * 31 + ord(ch)) & 0xFFFFFFFF  # 32-bit

    code = _to_base36(h).upper()
    code = code.rjust(8, "0")[-8:]  # pad to 8, keep last 8
    return f"SP-{code[:4]}-{code[4:]}"
    
    
    

from django.utils import timezone  # already imported earlier in your file

def verify_order(request):
    """
    Public verification page for QR scans.
    URL: /sales/verify-order/?order=<order_number>
    """
    order_number = request.GET.get("order", "").strip()
    system_settings = SystemSettings.objects.first()

    order = None
    verification_code = None
    is_valid = False

    if order_number:
        order = POSOrder.objects.filter(order_number=order_number).first()
        if order:
            verification_code = generate_verification_code(order, system_settings)
            is_valid = True

    context = {
        "order_number": order_number,
        "order": order,
        "verification_code": verification_code,
        "is_valid": is_valid,
        "system_settings": system_settings,
    }
    return render(request, "sales/verify_order.html", context)




from rest_framework.authtoken.models import Token
from django.conf import settings

def print_receipt(request, order_id):
    """Print HTML receipt (with QR) for completed order"""
    if not request.user.is_authenticated:
        token_key = request.GET.get('token')
        if token_key:
            try:
                token = Token.objects.get(key=token_key)
                request.user = token.user
            except Token.DoesNotExist:
                return redirect(f"{settings.LOGIN_URL}?next={request.path}")
        else:
            return redirect(f"{settings.LOGIN_URL}?next={request.path}")

    order = get_object_or_404(POSOrder, id=order_id)
    order_items = POSOrderItem.objects.filter(order=order).select_related('product')

    # Get system settings for receipt
    system_settings = SystemSettings.objects.first()

    # --- Generate QR code for HTML receipt ---
    qr_code_b64 = None
    try:
        # If you have a real verify view, better: reverse('sales:verify_order') + querystring
        qr_data = request.build_absolute_uri(
            f"/sales/verify-order/?order={order.order_number}"
        )

        qr = qrcode.QRCode(
            version=1,
            box_size=4,   # smaller boxes so it fits nicely in the 90x90px area
            border=1,
        )
        qr.add_data(qr_data)
        qr.make(fit=True)

        img = qr.make_image(fill_color="black", back_color="white")
        buffer = BytesIO()
        img.save(buffer, format="PNG")
        qr_code_b64 = base64.b64encode(buffer.getvalue()).decode("ascii")
    except Exception as e:
        # Optional: log instead of print in production
        logger.warning("QR generation error: %s", e)

    context = {
        'order': order,
        'order_items': order_items,
        'system_settings': system_settings,
        'qr_code': qr_code_b64,
        'currency_symbol': system_settings.currency_symbol if system_settings else '₦',
        'user_role': request.user.role,
        'user_name': request.user.get_full_name() or request.user.username,
    }
    return render(request, 'sales/receipt.html', context)

@login_required

def repeat_sale(request, order_id):
    """Create a new order with same items as the original order"""
    original_order = get_object_or_404(POSOrder, id=order_id)
    
    # Create new order
    new_order = POSOrder.objects.create(
        order_number=f"GPOS-{timezone.now().strftime('%m%d%H%M')}-{''.join(__import__('random').choices(__import__('string').ascii_uppercase+__import__('string').digits,k=5))}",
        total_amount=0,
        final_amount=0,
        cashier=request.user.username,
        payment_method='cash'
    )
    
    # Copy items
    for item in original_order.items.all():
        # Check if product still exists and has sufficient stock
        if item.product.stock_quantity >= item.quantity:
            POSOrderItem.objects.create(
                order=new_order,
                product=item.product,
                quantity=item.quantity,
                unit_price=item.unit_price,
                total_price=item.total_price
            )
            # Update stock
            item.product.stock_quantity -= item.quantity
            item.product.save()
        else:
            messages.warning(request, f'Insufficient stock for {item.product.name}')
    
    # Recalculate totals
    order_items = POSOrderItem.objects.filter(order=new_order)
    subtotal = sum(item.total_price for item in order_items)
    tax_amount = subtotal * 0.075
    final_total = subtotal + tax_amount
    
    new_order.total_amount = subtotal
    new_order.tax_amount = tax_amount
    new_order.final_amount = final_total
    new_order.save()
    
    # Set as current order
    request.session['current_order_id'] = new_order.id
    
    messages.success(request, 'Sale repeated successfully!')
    return redirect('sales:pos')

from django.shortcuts import render
from django.contrib.auth.decorators import login_required
from django.utils import timezone
from datetime import timedelta
from django.db.models import Sum, Count
from sales.models import POSOrder, DailySalesSummary

@login_required
@role_required(['admin', 'manager'])

def generate_receipt_with_qr(request, order_id):
    """Generate receipt with QR code for verification"""
    import qrcode
    from reportlab.pdfgen import canvas
    from reportlab.lib.pagesizes import A4
    from reportlab.lib.colors import Color
    from io import BytesIO

    order = get_object_or_404(POSOrder, id=order_id)
    order_items = POSOrderItem.objects.filter(order=order).select_related('product')

    # Get system settings
    system_settings = SystemSettings.objects.first()

    # Generate QR code
    qr_data = f"{request.build_absolute_uri('/sales/verify-order/')}?order={order.order_number}"
    qr = qrcode.QRCode(version=1, box_size=10, border=5)
    qr.add_data(qr_data)
    qr.make(fit=True)

    img = qr.make_image(fill_color="black", back_color="white")
    buffer = BytesIO()
    img.save(buffer, format='PNG')
    qr_image = buffer.getvalue()

    # Create PDF
    buffer = BytesIO()
    p = canvas.Canvas(buffer, pagesize=A4)
    width, height = A4

    # -------------------------
    # BACKGROUND TEXTURE
    # -------------------------
    p.saveState()

    texture_color = Color(0.85, 0.85, 0.85, alpha=0.15)  # VERY light grey
    p.setFillColor(texture_color)
    p.setFont("Helvetica", 22)

    # Repeat the order number diagonally across the page
    for y in range(0, int(height), 120):
        for x in range(0, int(width), 250):
            p.drawString(x, y, str(order.order_number))

    p.restoreState()

    # -------------------------
    # HEADER (More Nigerian POS Style)
    # -------------------------
    p.setFont("Helvetica-Bold", 20)
    p.drawString(40, height - 60, system_settings.business_name or "MODERN POS")

    p.setFont("Helvetica", 11)
    p.drawString(40, height - 82, system_settings.business_address or "")

    p.setFont("Helvetica-Bold", 12)
    p.drawString(40, height - 110, f"ORDER RECEIPT - #{order.order_number}")

    p.setFont("Helvetica", 10)
    p.drawString(40, height - 130, f"Date: {order.created_at.strftime('%Y-%m-%d %H:%M')}")
    p.drawString(250, height - 130, f"Cashier: {order.cashier}")

    # -------------------------
    # ITEMS SECTION
    # -------------------------
    p.setFont("Helvetica-Bold", 12)
    y_position = height - 170
    p.drawString(40, y_position, "ITEMS PURCHASED")

    p.setFont("Helvetica", 10)
    y_position -= 20

    for item in order_items:
        p.drawString(40, y_position, f"{item.quantity} x {item.product.name}")
        p.drawRightString(400, y_position, f"₦{item.total_price}")
        y_position -= 16

    # -------------------------
    # TOTALS
    # -------------------------
    y_position -= 10
    p.line(40, y_position, 400, y_position)
    y_position -= 20

    p.setFont("Helvetica-Bold", 11)
    p.drawString(40, y_position, f"Subtotal:")
    p.drawRightString(400, y_position, f"₦{order.total_amount}")

    y_position -= 18
    p.drawString(40, y_position, "Tax:")
    p.drawRightString(400, y_position, f"₦{order.tax_amount}")

    y_position -= 18
    p.drawString(40, y_position, "Total Amount:")
    p.drawRightString(400, y_position, f"₦{order.final_amount}")

    y_position -= 18
    p.drawString(40, y_position, f"Payment Method:")
    p.drawRightString(400, y_position, order.get_payment_method_display())

    # -------------------------
    # QR CODE
    # -------------------------
    if qr_image:
        p.setFont("Helvetica", 10)
        p.drawString(40, y_position - 40, "Scan to verify order:")
        p.drawImage(BytesIO(qr_image), 40, y_position - 140, width=110, height=110)

    # -------------------------
    # FOOTER
    # -------------------------
    p.setFont("Helvetica-Oblique", 10)
    p.drawString(40, 40, system_settings.receipt_footer or "Thank you for your patronage!")

    p.showPage()
    p.save()

    buffer.seek(0)
    return HttpResponse(buffer.getvalue(), content_type='application/pdf')

