from django.shortcuts import render, get_object_or_404, redirect
from django.urls import reverse

from django.contrib.auth.decorators import login_required
from django.contrib import messages
from django.http import JsonResponse, HttpResponse
from django.views.decorators.http import require_POST, require_GET
from django.utils import timezone
from django.db import transaction
from django.contrib.auth import get_user_model
import openpyxl
from openpyxl.styles import Font, Alignment, PatternFill
from openpyxl.utils import get_column_letter
from datetime import datetime
from _helpers.utils import persian_converter3
from .models import Process, ProcessInstance, StepInstance, ProcessStep
from .utils import scope_instances_queryset, get_scoped_instance_or_404
from installations.models import InstallationAssignment, InstallationReport
from wells.models import Well
from accounts.models import Profile, Broker
from locations.models import Affairs
from accounts.forms import CustomerForm
from wells.forms import WellForm
from wells.models import WaterMeterManufacturer
from common.consts import UserRoles


@login_required
def request_list(request):
    """نمایش لیست درخواست‌ها با جدول و مدال ایجاد"""
    instances = ProcessInstance.objects.select_related('well', 'representative', 'requester', 'broker', 'current_step', 'process').prefetch_related('step_instances__step').filter(is_deleted=False).order_by('-created')
    access_denied = False

    # filter by roles (scoped queryset)
    try:
        instances = scope_instances_queryset(request.user, instances)
        if not instances.exists() and not getattr(request.user, 'profile', None):
            access_denied = True
            instances = instances.none()
    except Exception:
        access_denied = True
        instances = instances.none()
        
    # Filters
    status_q = (request.GET.get('status') or '').strip()
    affairs_q = (request.GET.get('affairs') or '').strip()
    broker_q = (request.GET.get('broker') or '').strip()
    step_q = (request.GET.get('step') or '').strip()

    if status_q:
        instances = instances.filter(status=status_q)
    if affairs_q:
        try:
            instances = instances.filter(well__affairs_id=int(affairs_q))
        except Exception:
            pass
    if broker_q:
        try:
            instances = instances.filter(broker_id=int(broker_q))
        except Exception:
            pass
    if step_q:
        try:
            instances = instances.filter(current_step_id=int(step_q))
        except Exception:
            pass
    processes = Process.objects.filter(is_active=True)
    status_choices = list(ProcessInstance.STATUS_CHOICES)
    affairs_list = Affairs.objects.all().order_by('name')
    brokers_list = Broker.objects.all().order_by('name')
    steps_list = ProcessStep.objects.select_related('process').all().order_by('process__name', 'order')
    manufacturers = WaterMeterManufacturer.objects.all().order_by('name')
    
    # Prepare installation assignments map (scheduled date by instance)
    try:
        instance_ids = list(instances.values_list('id', flat=True))
    except Exception:
        instance_ids = []
    assignments_map = {}
    reports_map = {}
    if instance_ids:
        try:
            ass_qs = InstallationAssignment.objects.filter(process_instance_id__in=instance_ids).values('process_instance_id', 'scheduled_date')
            for row in ass_qs:
                assignments_map[row['process_instance_id']] = row['scheduled_date']
        except Exception:
            assignments_map = {}
        # latest report per instance (visited_date)
        try:
            rep_qs = InstallationReport.objects.filter(assignment__process_instance_id__in=instance_ids).order_by('-created').values('assignment__process_instance_id', 'visited_date')
            for row in rep_qs:
                pid = row['assignment__process_instance_id']
                if pid not in reports_map:
                    reports_map[pid] = row['visited_date']
        except Exception:
            reports_map = {}

    # Calculate progress for each instance and attach install schedule info
    instances_with_progress = []
    for instance in instances:
        total_steps = instance.process.steps.count()
        completed_steps = instance.step_instances.filter(status='completed').count()
        progress_percentage = (completed_steps / total_steps * 100) if total_steps > 0 else 0
        sched_date = assignments_map.get(instance.id)
        overdue_days = 0
        reference_date = None
        if sched_date:
            # Reference date: until installer submits a report, use today; otherwise use visited_date
            try:
                visited_date = reports_map.get(instance.id)
                if visited_date:
                    reference_date = visited_date
                else:
                    try:
                        reference_date = timezone.localdate()
                    except Exception:
                        from datetime import date as _date
                        reference_date = _date.today()
                if reference_date > sched_date:
                    overdue_days = (reference_date - sched_date).days
            except Exception:
                overdue_days = 0
                reference_date = None

        installation_scheduled_date = reference_date if reference_date and reference_date > sched_date else sched_date

        # Emergency approved flag (final settlement step forced approval)
        try:
            final_settlement_step = instance.process.steps.filter(order=8).first()
            emergency_approved = False
            if final_settlement_step:
                si = instance.step_instances.filter(step=final_settlement_step).first()
                emergency_approved = bool(si and si.status == 'approved')
        except Exception:
            emergency_approved = False

        instances_with_progress.append({
            'instance': instance,
            'progress_percentage': round(progress_percentage),
            'completed_steps': completed_steps,
            'total_steps': total_steps,
            'installation_scheduled_date': installation_scheduled_date,
            'installation_overdue_days': overdue_days,
            'emergency_approved': emergency_approved,
        })
    
    # Summary stats for header cards
    total_count = instances.count()
    completed_count = instances.filter(status='completed').count()
    in_progress_count = instances.filter(status='in_progress').count()
    pending_count = instances.filter(status='pending').count()
    
    return render(request, 'processes/request_list.html', {
        'instances_with_progress': instances_with_progress,
        'customer_form': CustomerForm(),
        'well_form': WellForm(),
        'processes': processes,
        'manufacturers': manufacturers,
        'total_count': total_count,
        'completed_count': completed_count,
        'in_progress_count': in_progress_count,
        'pending_count': pending_count,
        # filter context
        'status_choices': status_choices,
        'affairs_list': affairs_list,
        'brokers_list': brokers_list,
        'steps_list': steps_list,
        'filter_status': status_q,
        'filter_affairs': affairs_q,
        'filter_broker': broker_q,
        'filter_step': step_q,
        'access_denied': access_denied,
    })


@require_GET
@login_required
def lookup_well_by_subscription(request):
    sub = request.GET.get('water_subscription_number', '').strip()
    if not sub:
        return JsonResponse({'ok': False, 'error': 'شماره اشتراک الزامی است'}, status=400)
    try:
        well = Well.objects.select_related('representative', 'water_meter_manufacturer').get(water_subscription_number=sub)
        data = {
            'id': well.id,
            'water_subscription_number': well.water_subscription_number,
            'electricity_subscription_number': well.electricity_subscription_number,
            'water_meter_serial_number': well.water_meter_serial_number,
            'water_meter_old_serial_number': well.water_meter_old_serial_number,
            'water_meter_manufacturer': well.water_meter_manufacturer.id if well.water_meter_manufacturer else None,
            'utm_x': str(well.utm_x) if well.utm_x is not None else None,
            'utm_y': str(well.utm_y) if well.utm_y is not None else None,
            'utm_zone': well.utm_zone,
            'utm_hemisphere': well.utm_hemisphere,
            'well_power': well.well_power,
            'reference_letter_number': well.reference_letter_number,
            'reference_letter_date': well.reference_letter_date.isoformat() if well.reference_letter_date else None,
            'representative_letter_file_url': well.representative_letter_file.url if well.representative_letter_file else '',
            'representative_letter_file_name': well.representative_letter_file.name.split('/')[-1] if well.representative_letter_file else '',
            'representative_id': well.representative.id if well.representative else None,
            'representative_full_name': well.representative.get_full_name() if well.representative else None,
        }
        return JsonResponse({'ok': True, 'exists': True, 'well': data})
    except Well.DoesNotExist:
        return JsonResponse({'ok': True, 'exists': False})


@require_GET
@login_required
def lookup_representative_by_national_code(request):
    national_code = request.GET.get('national_code', '').strip()
    if not national_code:
        return JsonResponse({'ok': False, 'error': 'کد ملی الزامی است'}, status=400)
    profile = Profile.objects.select_related('user').filter(national_code=national_code).first()
    if not profile:
        return JsonResponse({'ok': True, 'exists': False})
    user = profile.user
    return JsonResponse({
        'ok': True,
        'exists': True,
        'user': {
            'id': user.id,
            'username': user.username,
            'first_name': user.first_name,
            'last_name': user.last_name,
            'full_name': user.get_full_name(),
            'profile': {
                'user_type': profile.user_type,
                'national_code': profile.national_code,
                'company_name': profile.company_name,
                'company_national_id': profile.company_national_id,
                'phone_number_1': profile.phone_number_1,
                'phone_number_2': profile.phone_number_2,
                'card_number': profile.card_number,
                'account_number': profile.account_number,
                'bank_name': profile.bank_name,
                'address': profile.address,
            }
        }
    })


@require_POST
@login_required
@transaction.atomic
def create_request_with_entities(request):
    """ایجاد/به‌روزرسانی چاه و نماینده و سپس ایجاد درخواست"""
    User = get_user_model()
    # Only BROKER can create requests
    try:
        if not (hasattr(request.user, 'profile') and request.user.profile.has_role(UserRoles.BROKER)):
            return JsonResponse({'ok': False, 'error': 'فقط کارگزار مجاز به ایجاد درخواست است'}, status=403)
    except Exception:
        return JsonResponse({'ok': False, 'error': 'فقط کارگزار مجاز به ایجاد درخواست است'}, status=403)
        
    process_id = request.POST.get('process')
    process = Process.objects.get(id=process_id)
    description = request.POST.get('description', '')
    # Well fields
    water_subscription_number = request.POST.get('water_subscription_number')
    well_id = request.POST.get('well_id')  # optional if existing
    # Representative fields
    representative_id = request.POST.get('representative_id')

    if not process_id:
        return JsonResponse({'ok': False, 'errors': {'request': {'process': ['فرآیند الزامی است']}}}, status=400)
    if not water_subscription_number:
        return JsonResponse({'ok': False, 'errors': {'well': {'water_subscription_number': ['شماره اشتراک آب الزامی است']}}}, status=400)
    if not representative_id and not request.POST.get('national_code'):
        return JsonResponse({'ok': False, 'errors': {'customer': {'national_code': ['کد ملی نماینده را وارد کنید یا دکمه بررسی/افزودن نماینده را بزنید']}}}, status=400)

    representative_user = None
    representative_profile = None
    if representative_id:
        representative_profile = Profile.objects.select_related('user').filter(user_id=representative_id).first()
        if not representative_profile:
            return JsonResponse({'ok': False, 'errors': {'customer': {'__all__': ['نماینده انتخاب‌شده یافت نشد']}}}, status=400)
        # Use CustomerForm with request.POST data, merging with existing values
        customer_form = CustomerForm(request.POST, instance=representative_profile)
        customer_form.request = request
        if not customer_form.is_valid():
            return JsonResponse({'ok': False, 'errors': {'customer': customer_form.errors}}, status=400)
        representative_profile = customer_form.save()
        representative_user = representative_profile.user
    else:
        # Use CustomerForm to validate/create/update representative profile by national code
        profile_instance = None
        national_code = request.POST.get('national_code')
        if national_code:
            profile_instance = Profile.objects.filter(national_code=national_code).first()
        customer_form = CustomerForm(request.POST, instance=profile_instance)
        customer_form.request = request
        if not customer_form.is_valid():
            return JsonResponse({'ok': False, 'errors': {'customer': customer_form.errors}}, status=400)
        representative_profile = customer_form.save()
        representative_user = representative_profile.user

    # Resolve/create/update well
    # Build WellForm data from POST
    well = None
    if well_id:
        well = Well.objects.filter(id=well_id).first()
        if not well:
            return JsonResponse({'ok': False, 'error': 'شناسه چاه نامعتبر است'}, status=400)
    else:
        existing = Well.objects.filter(water_subscription_number=water_subscription_number).first()
        if existing:
            well = existing

    well_data = request.POST.copy()
    print(well_data)
    # Ensure representative set from created/selected user if not provided
    if representative_user and not well_data.get('representative'):
        well_data['representative'] = str(representative_user.id)
    if not well_data.get('water_subscription_number'):
        well_data['water_subscription_number'] = water_subscription_number

    # Preserve existing values on partial updates
    if well:
        for field_name in WellForm.Meta.fields:
            if field_name in ('representative_letter_file',):
                # File field handled via request.FILES; skip if not provided
                continue
            incoming = well_data.get(field_name, None)
            if incoming is None or incoming == '':
                current_value = getattr(well, field_name, None)
                if current_value is None:
                    continue
                # Convert FK to id
                if hasattr(current_value, 'pk'):
                    well_data[field_name] = str(current_value.pk)
                else:
                    # Convert dates/decimals/others to string
                    try:
                        well_data[field_name] = current_value.isoformat()  # dates
                    except AttributeError:
                        well_data[field_name] = str(current_value)

    well_form = WellForm(well_data, request.FILES, instance=well)
    if not well_form.is_valid():
        return JsonResponse({'ok': False, 'errors': {'well': well_form.errors}}, status=400)
    # Save with ability to remove existing file
    well = well_form.save(commit=False)
    try:
        if request.POST.get('remove_file') == 'true' and getattr(well, 'representative_letter_file', None):
            well.representative_letter_file.delete(save=False)
            well.representative_letter_file = None
    except Exception:
        pass
    well.save()
    # Auto fill geo ownership from current user profile if available
    current_profile = getattr(request.user, 'profile', None)
    if current_profile:
        if hasattr(well, 'affairs'):
            well.affairs = current_profile.affairs
        if hasattr(well, 'county'):
            well.county = current_profile.county
        if hasattr(well, 'broker'):
            well.broker = current_profile.broker
        well.save()

    # Ensure no active (non-deleted, non-completed) request exists for this well
    try:
        active_exists = ProcessInstance.objects.filter(well=well, is_deleted=False).exclude(status='completed').exists()
        if active_exists:
            return JsonResponse({'ok': False, 'error': 'برای این چاه یک درخواست جاری وجود دارد. ابتدا آن را تکمیل یا حذف کنید.'}, status=400)
    except Exception:
        return JsonResponse({'ok': False, 'error': 'خطا در بررسی وضعیت درخواست‌های قبلی این چاه'}, status=400)

    # Create request instance
    instance = ProcessInstance.objects.create(
        process=process,
        description=description,
        well=well,
        representative=representative_user,
        requester=request.user,
        broker=request.user.profile.broker if request.user.profile else None,
        status='pending',
        priority='medium',
    )
    # ایجاد نمونه‌های مرحله بر اساس مراحل فرآیند و تنظیم مرحله فعلی
    for step in process.steps.all().order_by('order'):
        StepInstance.objects.create(
            process_instance=instance,
            step=step
        )
    first_step = process.steps.all().order_by('order').first()
    if first_step:
        instance.current_step = first_step
        instance.status = 'in_progress'
        instance.save()

    redirect_url = reverse('processes:instance_steps', args=[instance.id])
    return JsonResponse({'ok': True, 'instance_id': instance.id, 'redirect': redirect_url})


@require_POST
@login_required
def delete_request(request, instance_id):
    """حذف درخواست"""
    instance = get_scoped_instance_or_404(request, instance_id)
    # Only BROKER can delete requests and only within their scope
    try:
        profile = getattr(request.user, 'profile', None)
        if not (profile and profile.has_role(UserRoles.BROKER)):
            return JsonResponse({'success': False, 'message': 'فقط کارگزار مجاز به حذف درخواست است'}, status=403)
        # Enforce ownership by broker (prevent deleting others' requests)
        if instance.broker_id and profile.broker and instance.broker_id != profile.broker.id:
            return JsonResponse({'success': False, 'message': 'شما مجاز به حذف این درخواست نیستید'}, status=403)
    except Exception:
        return JsonResponse({'success': False, 'message': 'فقط کارگزار مجاز به حذف درخواست است'}, status=403)
    code = instance.code
    if instance.status == 'completed':
        return JsonResponse({
            'success': False,
            'message': 'درخواست تکمیل شده نمی‌تواند حذف شود'
        })
    instance.delete()
    return JsonResponse({
        'success': True,
        'message': f'درخواست {code} با موفقیت حذف شد'
    })


@login_required
def step_detail(request, instance_id, step_id):
    """نمایش جزئیات مرحله خاص"""
    # Enforce scoped access to prevent URL tampering
    instance = get_scoped_instance_or_404(request, instance_id)
    # Prefetch for performance
    instance = ProcessInstance.objects.select_related('process', 'well', 'requester', 'representative', 'representative__profile').get(id=instance.id)
    step = get_object_or_404(instance.process.steps, id=step_id)
    # If the request is already completed, redirect to read-only summary page
    if instance.status == 'completed':
        return redirect('processes:instance_summary', instance_id=instance.id)
    
    # جلوگیری از پرش به مراحل آینده: فقط اجازه نمایش مرحله جاری یا مراحل تکمیل‌شده
    # try:
    #     if instance.current_step and step.order > instance.current_step.order:
    #         messages.error(request, 'ابتدا مراحل قبلی را تکمیل کنید.')
    #         return redirect('processes:step_detail', instance_id=instance.id, step_id=instance.current_step.id)
    # except Exception:
    #     pass

    # بررسی دسترسی به مرحله
    if not instance.can_access_step(step):
        messages.error(request, 'شما به این مرحله دسترسی ندارید. ابتدا مراحل قبلی را تکمیل کنید.')
        return redirect('processes:request_list')
    
    # هدایت به view مناسب بر اساس نوع مرحله
    if step.order == 1:  # مرحله اول - انتخاب اقلام
        return redirect('invoices:quote_step', instance_id=instance.id, step_id=step.id)
    elif step.order == 2:  # مرحله دوم - صدور پیش‌فاکتور
        return redirect('invoices:quote_preview_step', instance_id=instance.id, step_id=step.id)
    elif step.order == 3:  # مرحله سوم - ثبت فیش‌های واریزی
        return redirect('invoices:quote_payment_step', instance_id=instance.id, step_id=step.id)
    elif step.order == 4:  # مرحله چهارم - قرارداد
        return redirect('contracts:contract_step', instance_id=instance.id, step_id=step.id)
    elif step.order == 5:  # مرحله پنجم - انتخاب نصاب
        return redirect('installations:installation_assign_step', instance_id=instance.id, step_id=step.id)
    elif step.order == 6:  # مرحله ششم - گزارش نصب
        return redirect('installations:installation_report_step', instance_id=instance.id, step_id=step.id)
    elif step.order == 7:  # مرحله هفتم - فاکتور نهایی
        return redirect('invoices:final_invoice_step', instance_id=instance.id, step_id=step.id)
    elif step.order == 8:  # مرحله هشتم - تسویه حساب نهایی
        return redirect('invoices:final_settlement_step', instance_id=instance.id, step_id=step.id)
    elif step.order == 9:  # مرحله نهم - گواهی نهایی
        return redirect('certificates:certificate_step', instance_id=instance.id, step_id=step.id)
    
    # برای سایر مراحل، template عمومی نمایش داده می‌شود
    step_instance = instance.step_instances.filter(step=step).first()
    
    # Navigation logic
    previous_step = instance.process.steps.filter(order__lt=step.order).last()
    next_step = instance.process.steps.filter(order__gt=step.order).first()
    
    return render(request, 'processes/step_detail.html', {
        'instance': instance,
        'step': step,
        'step_instance': step_instance,
        'previous_step': previous_step,
        'next_step': next_step,
    })


@login_required 
def instance_steps(request, instance_id):
    """هدایت به مرحله فعلی instance"""
    # Enforce scoped access to prevent URL tampering
    instance = get_scoped_instance_or_404(request, instance_id)
    
    if not instance.current_step:
        # اگر مرحله فعلی تعریف نشده، به اولین مرحله برو
        first_step = instance.process.steps.first()
        if first_step:
            instance.current_step = first_step
            instance.save()
            return redirect('processes:step_detail', instance_id=instance.id, step_id=first_step.id)
        else:
            messages.error(request, 'هیچ مرحله‌ای برای این فرآیند تعریف نشده است.')
            return redirect('processes:request_list')
    
    # If completed, go to summary instead of steps
    if instance.status == 'completed':
        return redirect('processes:instance_summary', instance_id=instance.id)
    return redirect('processes:step_detail', instance_id=instance.id, step_id=instance.current_step.id)


@login_required
def instance_summary(request, instance_id):
    """نمای خلاصهٔ فقط‌خواندنی برای درخواست‌های تکمیل‌شده."""
    # Enforce scoped access to prevent URL tampering
    instance = get_scoped_instance_or_404(request, instance_id)

    instance = get_object_or_404(ProcessInstance.objects.select_related('well', 'representative'), id=instance_id)
    # Only show for completed requests; otherwise route to steps
    if instance.status != 'completed':
        return redirect('processes:instance_steps', instance_id=instance.id)

    # Collect final invoice, payments, and certificate if any
    from invoices.models import Invoice
    from installations.models import InstallationReport, InstallationAssignment
    from certificates.models import CertificateInstance
    invoice = Invoice.objects.filter(process_instance=instance).first()
    payments = invoice.payments.filter(is_deleted=False).all() if invoice else []
    latest_report = InstallationReport.objects.filter(assignment__process_instance=instance).order_by('-created').first()
    certificate = CertificateInstance.objects.filter(process_instance=instance).order_by('-created').first()

    # Calculate installation delay
    installation_assignment = InstallationAssignment.objects.filter(process_instance=instance).first()
    installation_delay_days = 0
    if installation_assignment and latest_report:
        scheduled_date = installation_assignment.scheduled_date
        visited_date = latest_report.visited_date
        if scheduled_date and visited_date and visited_date > scheduled_date:
            installation_delay_days = (visited_date - scheduled_date).days

    # Build rows like final invoice step
    rows = []
    if invoice:
        items_qs = invoice.items.select_related('item').filter(is_deleted=False).all()
        rows = list(items_qs)

    return render(request, 'processes/instance_summary.html', {
        'instance': instance,
        'invoice': invoice,
        'payments': payments,
        'rows': rows,
        'latest_report': latest_report,
        'certificate': certificate,
        'installation_assignment': installation_assignment,
        'installation_delay_days': installation_delay_days,
    })


def format_date_jalali(date_obj):
    """Convert date to Jalali format without time"""
    if not date_obj:
        return ""
    try:
        # If it's a datetime, get just the date part
        if hasattr(date_obj, 'date'):
            date_obj = date_obj.date()
        return persian_converter3(date_obj)
    except Exception:
        return ""

def format_datetime_jalali(datetime_obj):
    """Convert datetime to Jalali format without time"""
    if not datetime_obj:
        return ""
    try:
        # Get just the date part
        date_part = datetime_obj.date() if hasattr(datetime_obj, 'date') else datetime_obj
        return persian_converter3(date_part)
    except Exception:
        return ""

@login_required
def export_requests_excel(request):
    """Export filtered requests to Excel"""
    
    # Get the same queryset as request_list view (with filters)
    instances = ProcessInstance.objects.select_related(
        'process', 'current_step', 'representative', 'well', 'well__county', 'well__affairs'
    ).prefetch_related('step_instances')
    
    # Apply scoping
    instances = scope_instances_queryset(request.user, instances)
    
    # Apply filters (same logic as request_list view)
    filter_status = request.GET.get('status', '').strip()
    if filter_status:
        instances = instances.filter(status=filter_status)
    
    filter_affairs = request.GET.get('affairs', '').strip()
    if filter_affairs and filter_affairs.isdigit():
        instances = instances.filter(well__affairs_id=filter_affairs)
    
    filter_broker = request.GET.get('broker', '').strip()
    if filter_broker and filter_broker.isdigit():
        instances = instances.filter(well__broker_id=filter_broker)
    
    filter_step = request.GET.get('step', '').strip()
    if filter_step and filter_step.isdigit():
        instances = instances.filter(current_step_id=filter_step)
    
    # Get installation data
    assignment_ids = list(instances.values_list('id', flat=True))
    assignments_map = {}
    reports_map = {}
    installers_map = {}
    
    if assignment_ids:
        assignments = InstallationAssignment.objects.filter(
            process_instance_id__in=assignment_ids
        ).select_related('process_instance', 'installer')
        assignments_map = {a.process_instance_id: a.scheduled_date for a in assignments}
        installers_map = {a.process_instance_id: a.installer for a in assignments}
        
        reports = InstallationReport.objects.filter(
            assignment__process_instance_id__in=assignment_ids
        ).select_related('assignment')
        reports_map = {r.assignment.process_instance_id: r for r in reports}
    
    # Get quotes and payments data
    from invoices.models import Quote, Payment, Invoice
    quotes_map = {}
    payments_map = {}
    settlement_dates_map = {}
    approval_dates_map = {}
    approval_users_map = {}
    
    if assignment_ids:
        # Get quotes
        quotes = Quote.objects.filter(
            process_instance_id__in=assignment_ids
        ).select_related('process_instance')
        quotes_map = {q.process_instance_id: q for q in quotes}
        
        # Get payments with reference numbers
        payments = Payment.objects.filter(
            invoice__process_instance_id__in=assignment_ids, 
            is_deleted=False
        ).select_related('invoice__process_instance').order_by('created')
        
        for payment in payments:
            if payment.invoice.process_instance_id not in payments_map:
                payments_map[payment.invoice.process_instance_id] = []
            payments_map[payment.invoice.process_instance_id].append(payment)
        
        # Get final invoices to check settlement dates
        invoices = Invoice.objects.filter(
            process_instance_id__in=assignment_ids
        ).select_related('process_instance')
        
        for invoice in invoices:
            if invoice.get_remaining_amount() == 0:  # Fully settled
                # Find the last payment date for this invoice
                last_payment = Payment.objects.filter(
                    invoice__process_instance=invoice.process_instance,
                    is_deleted=False
                ).order_by('-created').first()
                if last_payment:
                    settlement_dates_map[invoice.process_instance_id] = last_payment.created
        
        # Get installation approval data by Water Resource Manager role
        from processes.models import StepInstance, StepApproval
        from accounts.models import Role
        from common.consts import UserRoles
        
        # Get the Water Resource Manager role
        water_manager_role = Role.objects.filter(slug=UserRoles.WATER_RESOURCE_MANAGER.value).first()
        
        installation_steps = StepInstance.objects.filter(
            process_instance_id__in=assignment_ids,
            step__order=6,  # Installation report step is order 6
            status='completed'
        ).select_related('process_instance')
        
        for step_instance in installation_steps:
            # Get the approval by Water Resource Manager role that completed this step
            approval = StepApproval.objects.filter(
                step_instance=step_instance,
                role=water_manager_role,
                is_deleted=False
            ).select_related('approved_by').order_by('-created_at').first()
            
            if approval:
                approval_dates_map[step_instance.process_instance_id] = approval.created_at
                approval_users_map[step_instance.process_instance_id] = approval.approved_by
    
    # Calculate progress and installation data
    instances_with_progress = []
    for instance in instances:
        total_steps = instance.process.steps.count()
        completed_steps = instance.step_instances.filter(status='completed').count()
        progress_percentage = (completed_steps / total_steps * 100) if total_steps > 0 else 0
        
        sched_date = assignments_map.get(instance.id)
        overdue_days = 0
        reference_date = None
        
        if sched_date:
            try:
                report = reports_map.get(instance.id)
                if report and report.visited_date:
                    reference_date = report.visited_date
                else:
                    try:
                        reference_date = timezone.localdate()
                    except Exception:
                        from datetime import date as _date
                        reference_date = _date.today()
                if reference_date > sched_date:
                    overdue_days = (reference_date - sched_date).days
            except Exception:
                overdue_days = 0
        
        installation_scheduled_date = reference_date if reference_date and reference_date > sched_date else sched_date
        
        instances_with_progress.append({
            'instance': instance,
            'progress_percentage': round(progress_percentage),
            'completed_steps': completed_steps,
            'total_steps': total_steps,
            'installation_scheduled_date': installation_scheduled_date,
            'installation_overdue_days': overdue_days,
        })
    
    # Create Excel workbook
    wb = openpyxl.Workbook()
    ws = wb.active
    ws.title = "لیست درخواست‌ها"
    
    # Set RTL (Right-to-Left) direction
    ws.sheet_view.rightToLeft = True
    
    # Define column headers
    headers = [
        'شناسه',
        'تاریخ ایجاد درخواست',
        'نام نماینده',
        'نام خانوادگی نماینده',
        'کد ملی نماینده',
        'نام شرکت',
        'شناسه شرکت',
        'سریال کنتور',
        'سریال کنتور جدید',
        'شماره اشتراک آب',
        'شماره اشتراک برق',
        'قدرت چاه',
        'شماره تماس ۱',
        'شماره تماس ۲',
        'آدرس',
        'مبلغ پیش‌فاکتور',
        'تاریخ واریزی‌ها و کدهای رهگیری',
        'تاریخ مراجعه نصاب',
        'تاخیر نصاب',
        'نام نصاب',
        'تاریخ تایید نصب توسط مدیر',
        'نام تایید کننده نصب',
        'تاریخ تسویه'
    ]
    
    # Write headers
    for col, header in enumerate(headers, 1):
        cell = ws.cell(row=1, column=col, value=header)
        cell.font = Font(bold=True)
        cell.alignment = Alignment(horizontal='center')
        cell.fill = PatternFill(start_color="CCCCCC", end_color="CCCCCC", fill_type="solid")
    
    # Write data rows
    for row_num, item in enumerate(instances_with_progress, 2):
        instance = item['instance']
        
        # Get representative info
        rep_first_name = ""
        rep_last_name = ""
        rep_national_code = ""
        rep_phone_1 = ""
        rep_phone_2 = ""
        rep_address = ""
        company_name = ""
        company_national_id = ""
        
        if instance.representative:
            rep_first_name = instance.representative.first_name or ""
            rep_last_name = instance.representative.last_name or ""
            if hasattr(instance.representative, 'profile') and instance.representative.profile:
                profile = instance.representative.profile
                rep_national_code = profile.national_code or ""
                rep_phone_1 = profile.phone_number_1 or ""
                rep_phone_2 = profile.phone_number_2 or ""
                rep_address = profile.address or ""
                if profile.user_type == 'legal':
                    company_name = profile.company_name or ""
                    company_national_id = profile.company_national_id or ""
        
        # Get well info
        water_subscription = ""
        electricity_subscription = ""
        well_power = ""
        old_meter_serial = ""
        if instance.well:
            water_subscription = instance.well.water_subscription_number or ""
            electricity_subscription = instance.well.electricity_subscription_number or ""
            well_power = str(instance.well.well_power) if instance.well.well_power else ""
            old_meter_serial = instance.well.water_meter_serial_number or ""
        
        # Get new meter serial from installation report
        new_meter_serial = ""
        installer_visit_date = ""
        report = reports_map.get(instance.id)
        if report:
            new_meter_serial = report.new_water_meter_serial or ""
            installer_visit_date = format_date_jalali(report.visited_date)
        
        # Get quote amount
        quote_amount = ""
        quote = quotes_map.get(instance.id)
        if quote:
            quote_amount = str(quote.final_amount) if quote.final_amount else ""
        
        # Get payments info
        payments_info = ""
        payments = payments_map.get(instance.id, [])
        if payments:
            payment_strings = []
            for payment in payments:
                date_str = format_datetime_jalali(payment.created)
                reference_number = payment.reference_number or "بدون کد"
                payment_strings.append(f"{date_str} - {reference_number}")
            payments_info = " | ".join(payment_strings)
        
        # Get installer name
        installer_name = ""
        installer = installers_map.get(instance.id)
        if installer:
            installer_name = installer.get_full_name() or str(installer)
        
        # Get overdue days
        overdue_days = ""
        if item['installation_overdue_days'] and item['installation_overdue_days'] > 0:
            overdue_days = str(item['installation_overdue_days'])
        
        # Get approval info
        approval_date = ""
        approval_user = ""
        approval_date_obj = approval_dates_map.get(instance.id)
        approval_user_obj = approval_users_map.get(instance.id)
        if approval_date_obj:
            approval_date = format_datetime_jalali(approval_date_obj)
        if approval_user_obj:
            approval_user = approval_user_obj.get_full_name() or str(approval_user_obj)
        
        # Get settlement date
        settlement_date = ""
        settlement_date_obj = settlement_dates_map.get(instance.id)
        if settlement_date_obj:
            settlement_date = format_datetime_jalali(settlement_date_obj)
        
        row_data = [
            instance.code,                    # شناسه
            format_datetime_jalali(instance.created),  # تاریخ ایجاد درخواست
            rep_first_name,                   # نام نماینده
            rep_last_name,                    # نام خانوادگی نماینده
            rep_national_code,                # کد ملی نماینده
            company_name,                     # نام شرکت
            company_national_id,              # شناسه شرکت
            old_meter_serial,                 # سریال کنتور
            new_meter_serial,                 # سریال کنتور جدید
            water_subscription,               # شماره اشتراک آب
            electricity_subscription,         # شماره اشتراک برق
            well_power,                       # قدرت چاه
            rep_phone_1,                      # شماره تماس ۱
            rep_phone_2,                      # شماره تماس ۲
            rep_address,                      # آدرس
            quote_amount,                     # مبلغ پیش‌فاکتور
            payments_info,                    # تاریخ واریزی‌ها و کدهای رهگیری
            installer_visit_date,             # تاریخ مراجعه نصاب
            overdue_days,                     # تاخیر نصاب
            installer_name,                   # نام نصاب
            approval_date,                    # تاریخ تایید نصب توسط مدیر
            approval_user,                    # نام تایید کننده نصب
            settlement_date                   # تاریخ تسویه
        ]
        
        for col, value in enumerate(row_data, 1):
            cell = ws.cell(row=row_num, column=col, value=value)
            # Set right alignment for Persian text
            cell.alignment = Alignment(horizontal='right')
    
    # Auto-adjust column widths
    for col in range(1, len(headers) + 1):
        column_letter = get_column_letter(col)
        max_length = 0
        for row in ws[column_letter]:
            try:
                if len(str(row.value)) > max_length:
                    max_length = len(str(row.value))
            except:
                pass
        adjusted_width = min(max_length + 2, 50)
        ws.column_dimensions[column_letter].width = adjusted_width
    
    # Prepare response
    response = HttpResponse(
        content_type='application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'
    )
    
    # Generate filename with current date
    current_date = datetime.now().strftime('%Y%m%d_%H%M')
    filename = f'requests_export_{current_date}.xlsx'
    response['Content-Disposition'] = f'attachment; filename="{filename}"'
    
    # Save workbook to response
    wb.save(response)
    
    return response
    