from django.db.models import Exists, OuterRef, Prefetch
from apps.access.authorization import authorized_queryset
from apps.organization.models import ServiceCenter
from apps.service.models import ServiceCase
from .models import ServiceQuotation, QuotationLine

VIEW = "commercial.view_servicequotation"


def quotation_cases(*, actor, permission=VIEW):
    centers = authorized_queryset(user=actor, permission=permission, queryset=ServiceCenter.objects.all())
    return ServiceCase.objects.filter(service_center_id__in=centers.values("pk")).select_related(
        "company", "service_center", "customer", "device").order_by("received_at", "job_number", "pk")


def service_quotations(*, actor):
    return ServiceQuotation.objects.filter(family__service_case_id__in=quotation_cases(actor=actor).values("pk")).select_related(
        "family__service_case__customer", "family__service_case__service_center", "created_by", "submitted_by", "decision__recorded_by").order_by("family__number", "revision", "pk")


def quotation_history(*, actor, service_case):
    return service_quotations(actor=actor).filter(family__service_case=service_case).order_by("revision", "pk")


def current_service_quotation(*, actor, service_case):
    return quotation_history(actor=actor, service_case=service_case).filter(is_current=True).first()


def approved_service_quotation(*, actor, service_case):
    return quotation_history(actor=actor, service_case=service_case).filter(is_current=True, status="APPROVED").first()


def quotation_lines(*, actor, quotation):
    return QuotationLine.objects.filter(quotation_id__in=service_quotations(actor=actor).filter(pk=quotation.pk).values("pk"),
        is_active=True).select_related("spare_part", "repair_action__repair_action", "finding__fault_diagnosis").order_by("position", "pk")


def quotation_detail(*, actor, quotation):
    return service_quotations(actor=actor).prefetch_related(Prefetch("lines", queryset=quotation_lines(actor=actor, quotation=quotation))).get(pk=quotation.pk)


def quotation_customer_due(*, actor, quotation):
    return service_quotations(actor=actor).values_list("customer_pay_total", flat=True).get(pk=quotation.pk)


def service_cases_awaiting_quotation(*, actor):
    return quotation_cases(actor=actor).filter(status__in=["DIAGNOSED", "REPAIRING"]).filter(
        ~Exists(ServiceQuotation.objects.filter(family__service_case_id=OuterRef("pk"))))


def service_cases_awaiting_customer_approval(*, actor):
    return quotation_cases(actor=actor).filter(status__in=["DIAGNOSED", "REPAIRING"], quotation_family__revisions__is_current=True,
        quotation_family__revisions__status="SUBMITTED").distinct()
