from decimal import Decimal, InvalidOperation
from django.contrib import messages
from django.db import transaction
from django.shortcuts import get_object_or_404, redirect, render
from django.utils import timezone
from django.views.decorators.http import require_POST
from .models import PRDetail, Tender, TenderVendorInvitation, TenderQuotation, TenderQuotationDetail

def _vendor_code(request):
    # Must be populated only by the authenticated vendor-login flow.
    return (request.session.get('vendor_code') or '').strip()

def vendor_login(request):
    # Frame only; connect to the approved vendor authentication source before external use.
    return render(request, 'vendor_portal/login.html')

def vendor_dashboard(request):
    code = _vendor_code(request)
    if not code:
        return redirect('vendor_portal_login')
    invitations = TenderVendorInvitation.objects.filter(vendor_code=code, is_active=True).order_by('-invited_at')
    quotations = TenderQuotation.objects.filter(vendor_code=code).order_by('-created_at')
    return render(request, 'vendor_portal/dashboard.html', {'invitations': invitations, 'quotations': quotations})

def vendor_invitation_detail(request, invitation_id):
    code = _vendor_code(request)
    if not code:
        return redirect('vendor_portal_login')
    invitation = get_object_or_404(TenderVendorInvitation, pk=invitation_id, vendor_code=code, is_active=True)
    tender = get_object_or_404(Tender, pk=invitation.tender_id)
    pr_details = PRDetail.objects.filter(pr_id=tender.pr_id).order_by('line_no')
    if request.method == 'POST':
        if invitation.deadline and timezone.now() > invitation.deadline:
            messages.error(request, 'Submission deadline has passed.')
            return redirect('vendor_invitation_detail', invitation_id=invitation.id)
        if invitation.response_status in {'CLOSED','WITHDRAWN'}:
            messages.error(request, 'This invitation is closed.')
            return redirect('vendor_invitation_detail', invitation_id=invitation.id)
        try:
            with transaction.atomic():
                version = (TenderQuotation.objects.filter(invitation_id=invitation.id).order_by('-version_no').values_list('version_no', flat=True).first() or 0) + 1
                status = 'SUBMITTED' if request.POST.get('action') == 'submit' else 'DRAFT'
                q = TenderQuotation.objects.create(
                    created_at=timezone.now(), updated_at=timezone.now(), invitation_id=invitation.id,
                    tender_id=tender.id, vendor_code=code, vendor_name=invitation.vendor_name,
                    quotation_no=(request.POST.get('quotation_no') or '').strip(),
                    quotation_date=request.POST.get('quotation_date') or None,
                    currency=(request.POST.get('currency') or 'USD').strip().upper(),
                    delivery_date=request.POST.get('delivery_date') or None,
                    payment_terms=(request.POST.get('payment_terms') or '').strip(),
                    delivery_terms=(request.POST.get('delivery_terms') or '').strip(),
                    remarks=(request.POST.get('remarks') or '').strip(), status=status,
                    submitted_at=timezone.now() if status == 'SUBMITTED' else None, version_no=version)
                total = Decimal('0')
                for line in pr_details:
                    raw = (request.POST.get(f'unit_price_{line.id}') or '').strip()
                    if not raw:
                        if status == 'SUBMITTED':
                            raise ValueError(f'Unit price required for line {line.line_no}.')
                        continue
                    try: price = Decimal(raw)
                    except InvalidOperation: raise ValueError(f'Invalid price for line {line.line_no}.')
                    if price < 0: raise ValueError('Unit price cannot be negative.')
                    qty = Decimal(str(line.quantity or 0)); amount = qty * price
                    TenderQuotationDetail.objects.create(created_at=timezone.now(), quotation_id=q.id,
                        pr_detail_id=line.id, line_no=line.line_no, description=line.description,
                        quantity=qty, uom=line.uom, unit_price=price, amount=amount)
                    total += amount
                q.total_amount = total
                q.save(update_fields=['total_amount'])
                if status == 'SUBMITTED':
                    invitation.response_status = 'SUBMITTED'
                    invitation.responded_at = timezone.now()
                    invitation.save(update_fields=['response_status','responded_at'])
            messages.success(request, 'Quotation submitted.' if status == 'SUBMITTED' else 'Draft saved.')
        except Exception as exc:
            messages.error(request, f'Unable to save quotation: {exc}')
        return redirect('vendor_invitation_detail', invitation_id=invitation.id)
    return render(request, 'vendor_portal/invitation_detail.html', {
        'invitation': invitation, 'tender': tender, 'pr_details': pr_details})

@require_POST
def vendor_quotation_history(request):
    if not _vendor_code(request):
        return redirect('vendor_portal_login')
    return redirect('vendor_portal_dashboard')
