from django.db.models import OuterRef, Subquery, DecimalField, IntegerField

from apps.companies.models import Service, ServicePrice


class ServiceRepository:

    @staticmethod
    def create_service(**data):
        return Service.objects.create(**data)

    @staticmethod
    def update_service(pk, **data):
        Service.objects.filter(pk=pk).update(**data)
        return Service.objects.get(pk=pk)

    @staticmethod
    def service_exists(company, code, exclude_pk=None):
        qs = Service.objects.filter(company=company, code=code)
        if exclude_pk:
            qs = qs.exclude(pk=exclude_pk)
        return qs.exists()

    @staticmethod
    def get_services(company):
        return Service.objects.filter(company=company)

    @staticmethod
    def get_services_list(company):
        latest_price = ServicePrice.objects.filter(
            service=OuterRef("pk"),
            company=company,
            is_active=True,
        ).order_by("-effective_from")

        return Service.objects.filter(company=company).annotate(
            _service_price=Subquery(
                latest_price.values("base_price")[:1],
                output_field=DecimalField(),
            ),
            _labor_rate=Subquery(
                latest_price.values("labor_rate_per_hour")[:1],
                output_field=DecimalField(),
            ),
            _estimated_hours=Subquery(
                latest_price.values("estimated_hours")[:1],
                output_field=IntegerField(),
            ),
        )

class ServicePriceRepository:

    @staticmethod
    def create_price(**kwargs):
        return ServicePrice.objects.create(**kwargs)

    @staticmethod
    def update_price(pk, **data):
        ServicePrice.objects.filter(pk=pk).update(**data)
        return ServicePrice.objects.get(pk=pk)

    @staticmethod
    def price_exists(service, company, effective_from, exclude_pk=None):
        qs = ServicePrice.objects.filter(
            service=service,
            company=company,
            effective_from=effective_from
        )
        if exclude_pk:
            qs = qs.exclude(pk=exclude_pk)
        return qs.exists()

    @staticmethod
    def get_prices(company):
        return ServicePrice.objects.select_related(
            "service", "company"
        ).filter(company=company)
