from openai import OpenAI
from twilio.rest import Client
from nexusmart import settings
from django.core.mail import EmailMessage
from django.contrib.auth import get_user_model
from django.template.loader import render_to_string

from .models import Cart, CartItem
from weasyprint import HTML
from weasyprint.text.fonts import FontConfiguration
import datetime

User = get_user_model()

def _get_customer_profile(user):
    customer_profile, _ = User.objects.get_or_create(username=user.username)
    return customer_profile


def send_customer_reply_notification(ticket, reply_text, channel='email', attachment=None):
    profile = getattr(ticket.user, 'profile', None)
    customer_phone = profile.phone if profile and profile.phone else None
    
    attachment_html = ""
    if attachment:
        attachment_url = attachment.url  # Full media URL (e.g., /media/ticket_attachments/file.pdf)
        attachment_html = f"""
        <p><strong>📎 Attachment:</strong> 
            <a href="{attachment_url}" target="_blank" style="color:#007bff;">Download File</a>
        </p>
        """
    
    context = {
        'ticket': ticket,
        'reply_text': reply_text,
        'customer_name': ticket.user.username,
        'attachment_html': attachment_html,
    }
    
    # Email with attachment link
    subject = f"Update on Your Support Ticket #{ticket.id} - Banshix"
    html_message = render_to_string('shop/ticket_reply_email.html', context)
    
    email = EmailMessage(
        subject=subject,
        body=html_message,
        from_email=settings.DEFAULT_FROM_EMAIL,
        to=[ticket.user.email],
    )
    email.content_subtype = "html"
    email.send(fail_silently=False)
    
    # WhatsApp (text only - no file attachment via Twilio in this simple setup)
    if channel == 'whatsapp' and customer_phone:
        try:
            client = Client(settings.TWILIO_ACCOUNT_SID, settings.TWILIO_AUTH_TOKEN)
            whatsapp_body = f"""
            *Banshix Support Update - Ticket #{ticket.id}*

            {reply_text}

            { 'Attachment available in your email.' if attachment else '' }

            Status: {ticket.status}
                        """.strip()
            client.messages.create(
                body=whatsapp_body,
                from_=settings.TWILIO_WHATSAPP_NUMBER,
                to=f"whatsapp:{customer_phone}"
            )
        except Exception as e:
            print(f"WhatsApp failed: {e}")
            

def send_offer_submission_notification(offer_request):
    subject = f"New Offer Submitted for {offer_request.product.name}"
    context = {
        'offer': offer_request,
        'support_email': getattr(settings, 'SUPPORT_EMAIL', settings.DEFAULT_FROM_EMAIL),
        'offer_link': f"http://127.0.0.1:8000/manage/admin/offers/"
    }
    html_message = render_to_string('shop/email_offer_submission.html', context)
    email = EmailMessage(
        subject=subject,
        body=html_message,
        from_email=settings.DEFAULT_FROM_EMAIL,
        to=[getattr(settings, 'SUPPORT_EMAIL', settings.DEFAULT_FROM_EMAIL)],
    )
    email.content_subtype = 'html'
    try:
        email.send(fail_silently=False)
    except Exception as e:
        print(f"Failed to send offer submission notification: {e}")


def send_offer_status_update_notification(offer_request):
    subject = f"Update on Your Offer for {offer_request.product.name}"
    context = {
        'offer': offer_request,
        'status_label': offer_request.status,
    }
    html_message = render_to_string('shop/email_offer_status_update.html', context)
    email = EmailMessage(
        subject=subject,
        body=html_message,
        from_email=settings.DEFAULT_FROM_EMAIL,
        to=[offer_request.user.email],
    )
    email.content_subtype = 'html'
    try:
        email.send(fail_silently=False)
    except Exception as e:
        print(f"Failed to send offer status update notification: {e}")


def send_staff_customer_reply_notification(ticket, message):
    try:
        subject = f"New Customer Reply on Ticket #{ticket.id}"
        body = f"Customer {ticket.user.username} replied:\n\n{message}\n\nView ticket: http://127.0.0.1:8000/admin/shop/ticket/{ticket.id}/"
        email = EmailMessage(subject, body, settings.DEFAULT_FROM_EMAIL, [settings.SUPPORT_EMAIL])
        email.send(fail_silently=True)
    except Exception as e:
        print(f"Staff notification failed: {e}")  

def send_order_confirmation_email(request, order):
    """Send order confirmation email with WeasyPrint-generated PDF invoice attached"""
    items = order.items.all()

    # Prepare context for the invoice template
    context = {
        'order': order,
        'items': items,
        'user': request.user,
        'today': datetime.date.today(),
    }

    # Render HTML string from template
    html_string = render_to_string('shop/invoice.html', context)

    # Generate PDF using WeasyPrint
    font_config = FontConfiguration()
    html = HTML(string=html_string, base_url=request.build_absolute_uri('/'))
    
    try:
        pdf_bytes = html.write_pdf(font_config=font_config)
    except Exception as e:
        # Log error and silently fail (don't break checkout flow)
        print(f"PDF generation failed: {e}")
        return

    # Email setup
    subject = f'Order Confirmation #{order.id} - Banshix'
    body = render_to_string('shop/email_order_confirmation.html', {'order': order})

    email = EmailMessage(
        subject=subject,
        body=body,
        from_email=settings.DEFAULT_FROM_EMAIL,
        to=[request.user.email],
    )
    email.content_subtype = "html"

    # Attach the PDF
    email.attach(
        filename=f'invoice_{order.id}.pdf',
        content=pdf_bytes,
        mimetype='application/pdf'
    )

    # Send email
    try:
        email.send(fail_silently=False)
        print(f"Order confirmation email sent successfully for Order #{order.id}")
    except Exception as e:
        print(f"Failed to send email for Order #{order.id}: {e}")
        # In production, you should log this properly instead of printing
        

def sync_cart_to_db(request):
    if not request.user.is_authenticated:
        return

    session_cart = request.session.get('cart', {})
    cart, _ = Cart.objects.get_or_create(user=request.user)

    for pid, item in session_cart.items():
        CartItem.objects.update_or_create(
            cart=cart,
            product_id=pid,
            defaults={'quantity': item['quantity']}
        )  
        
        
from django.conf import settings

def get_currency(request):
    """Get current currency from session or default"""
    return request.session.get('currency', settings.DEFAULT_CURRENCY)

def set_currency(request, currency):
    """Set currency in session"""
    if currency in settings.CURRENCIES:
        request.session['currency'] = currency
        request.session.modified = True


def convert_price(price, request=None, to_currency=None):
    """Convert price to current user currency"""
    if request:
        to_currency = request.session.get('currency', 'USD')
    
    if to_currency == 'USD':
        return round(price, 2)
    
    rate = settings.CURRENCIES[to_currency]['rate']
    return round(price * rate, 2)



def get_currency_symbol(currency=None, request=None):
    if request:
        currency = get_currency(request)
    return settings.CURRENCIES.get(currency, settings.CURRENCIES['USD'])['symbol']


from decimal import Decimal, ROUND_UP, ROUND_DOWN


def split_amount_into_chunks(total_amount, max_limit, decimals=2):
    """
    Split `total_amount` into the minimal number of chunks such that each chunk
    is <= max_limit. Returns a list of Decimal chunk amounts (rounded to `decimals`).

    Example: total=8000000, max_limit=7390000 -> [4000000.00, 4000000.00]
    """
    total = Decimal(str(total_amount))
    max_limit = Decimal(str(max_limit))

    if total <= max_limit:
        quant = Decimal('1').scaleb(-decimals)
        return [total.quantize(quant)]

    # compute needed chunks
    chunks_needed = int((total / max_limit).to_integral_value(rounding=ROUND_UP))

    # base chunk amount (floor to decimals)
    quant = Decimal('1').scaleb(-decimals)
    base_amount = (total / Decimal(chunks_needed)).quantize(quant, rounding=ROUND_DOWN)

    chunks = [base_amount for _ in range(chunks_needed)]

    # distribute remainder to the last chunk
    remainder = total - sum(chunks)
    if remainder > 0:
        chunks[-1] = (chunks[-1] + remainder).quantize(quant)

    return chunks



      