from django.db.models.query import FlatValuesListIterable
from django.shortcuts import render, get_object_or_404, redirect
from django.contrib.auth.decorators import login_required
from django.urls import reverse
from django.utils import timezone
from decimal import Decimal
from django.template import Template, Context
from django.utils.safestring import mark_safe
from processes.models import ProcessInstance, StepInstance
from common.consts import UserRoles
from .models import ContractTemplate, ContractInstance
from invoices.models import Invoice, Quote
from _helpers.utils import jalali_converter2
from django.http import JsonResponse
from processes.utils import get_scoped_instance_or_404
def build_contract_context(instance: ProcessInstance) -> dict:
    representative = instance.representative
    profile = getattr(representative, 'profile', None)
    well = instance.well
    # Compute prepayment from Quote-linked invoice payments
    quote = Quote.objects.filter(process_instance=instance).first()
    invoice = Invoice.objects.filter(quote=quote).first() if quote else None
    payments_qs = invoice.payments.filter(is_deleted=False, direction='in').all() if invoice else []
    total_paid = sum((p.amount for p in payments_qs), Decimal('0'))
    try:
        latest_payment_date = max((p.payment_date for p in payments_qs)) if payments_qs else None
    except Exception:
        latest_payment_date = None
    
    individual = True if profile and profile.user_type == 'individual' else False
    company_national_id = profile.company_national_id if profile and profile.user_type == 'legal' else None
    company_name = profile.company_name if profile and profile.user_type == 'legal' else None
    return {
        'customer_full_name': mark_safe(f"{representative.get_full_name() if representative else ''}"),
        'registration_number': mark_safe(f"{instance.broker.company.registration_number if instance.broker and instance.broker.company else ''}"),
        'national_code': mark_safe(f"{profile.national_code if profile else ''}"),
        'address': mark_safe(f"{profile.address if profile else ''}"),
        'phone': mark_safe(f"{profile.phone_number_1 if profile else ''}"),
        'phone2': mark_safe(f"{profile.phone_number_2 if profile else ''}"),
        'water_subscription_number': mark_safe(f"{well.water_subscription_number if well else ''}"),
        'electricity_subscription_number': mark_safe(f"{well.electricity_subscription_number if well else ''}"),
        'water_meter_serial_number': mark_safe(f"{well.water_meter_serial_number if well else ''}"),
        'well_power': mark_safe(f"{well.well_power if well else ''}"),
        'request_code': mark_safe(f"{instance.code}"),
        'today': mark_safe(f"{jalali_converter2(timezone.now())}"),
        'company_name': mark_safe(f"{instance.broker.company.name if instance.broker and instance.broker.company else ''}"),
        'city_name': mark_safe(f"{instance.broker.affairs.county.city.name if instance.broker and instance.broker.affairs and instance.broker.affairs.county and instance.broker.affairs.county.city else ''}"),
        'card_number': mark_safe(f"{instance.representative.profile.card_number if instance.representative else ''}"),
        'account_number': mark_safe(f"{instance.representative.profile.account_number if instance.representative else ''}"),
        'bank_name': mark_safe(f"{instance.representative.profile.get_bank_name_display() if instance.representative else ''}"),
        'prepayment_amount': mark_safe(f"{int(total_paid):,}"),
        'prepayment_date': mark_safe(f"{jalali_converter2(latest_payment_date)}") if latest_payment_date else '',
        'user_type': mark_safe(f"{profile.get_user_type_display() if profile else ''}"),
        'individual': individual,
        'company_national_id': mark_safe(f"{company_national_id if company_national_id else ''}"),
        'company_name': mark_safe(f"{company_name if company_name else ''}"),
    }
@login_required
def contract_step(request, instance_id, step_id):
    instance = get_scoped_instance_or_404(request, instance_id)
    # Resolve step navigation
    step = get_object_or_404(instance.process.steps, id=step_id)
    previous_step = instance.process.steps.filter(order__lt=step.order).last()
    next_step = instance.process.steps.filter(order__gt=step.order).first()
    step_instance = StepInstance.objects.filter(process_instance=instance, step=step).first()
    profile = getattr(request.user, 'profile', None)
    is_broker = False
    can_view_contract_body = True
    try:
        is_broker = bool(profile and profile.has_role(UserRoles.BROKER))
        if profile and profile.has_role(UserRoles.INSTALLER):
            can_view_contract_body = False
    except Exception:
        pass
    template_obj = ContractTemplate.objects.first()
    if not template_obj:
        return render(request, 'contracts/contract_missing.html', {'instance': instance})
    ctx = build_contract_context(instance)
    rendered = Template(template_obj.body).render(Context(ctx))
    contract, _ = ContractInstance.objects.get_or_create(
        process_instance=instance,
        defaults={
            'template': template_obj,
            'rendered_body': rendered,
            'created_by': request.user,
        }
    )
    # keep latest rendering if template changed (optional)
    contract.template = template_obj
    contract.rendered_body = rendered
    contract.save()
    # If user submits to go next, only broker can complete and go to next
    if request.method == 'POST':
        if not is_broker:
            return JsonResponse({'success': False, 'message': 'شما مجوز تایید این مرحله را ندارید'}, status=403)
        step_instance, _ = StepInstance.objects.update_or_create(
            process_instance=instance,
            step=step,
            defaults={'status': 'completed', 'completed_at': timezone.now()}
        )
        if next_step:
            # instance.current_step = next_step
            instance.save()
            return redirect('processes:step_detail', instance_id=instance.id, step_id=step.id)
            # return redirect('processes:step_detail', instance_id=instance.id, step_id=next_step.id)
        return redirect('processes:request_list')
    return render(request, 'contracts/contract_step.html', {
        'instance': instance,
        'step': step,
        'contract': contract,
        'template': template_obj,
        'previous_step': previous_step,
        'next_step': next_step,
        'is_broker': is_broker,
        'can_view_contract_body': can_view_contract_body,
        'step_instance': step_instance,
    })
@login_required
def contract_print(request, instance_id):
    instance = get_scoped_instance_or_404(request, instance_id)
    contract = get_object_or_404(ContractInstance, process_instance=instance)
    return render(request, 'contracts/contract_print.html', {
        'instance': instance,
        'contract': contract,
    })