from typing import TYPE_CHECKING, Optional

from litestar import Controller, get, post
from litestar.di import Provide
from sqlalchemy.ext.asyncio import AsyncSession

from app.domain.fiscal_payment_mapping import (
    FiscalPaymentMapping,
    FiscalPaymentMappingReadDTO,
    FiscalPaymentMappingWriteDTO,
    Repository,
    Service,
)
from app.lib.filters import ExactFilter
from app.lib.responses import ObjectListResponse, ObjectResponse

if TYPE_CHECKING:
    from sqlalchemy.ext.asyncio import AsyncSession


DETAIL_ROUTE = "/{id:int}"


def provides_service(db_session: AsyncSession) -> Service:
    """Constructs repository and service objects for the request."""
    return Service(Repository(session=db_session))


class FiscalPaymentMappingController(Controller):
    dto = FiscalPaymentMappingWriteDTO
    return_dto = FiscalPaymentMappingReadDTO
    path = "/fiscal-payment-mappings"
    dependencies = {
        "service": Provide(provides_service, sync_to_thread=False),
    }
    tags = ["FiscalPaymentMappings"]

    @post()
    async def create_fiscal_payment_mappings(
        self, data: FiscalPaymentMapping, service: Service
    ) -> FiscalPaymentMapping:
        return await service.create(data)

    @get()
    async def get_fiscal_payment_mappings(
        self, service: Service, payment_device_code: Optional[int] = None
    ) -> ObjectListResponse[FiscalPaymentMapping]:
        filters = []

        if payment_device_code is not None:
            filters.append(
                ExactFilter[int](
                    field_name="payment_device_code",
                    value=payment_device_code,
                ),
            )

        content = await service.list(*filters)
        return ObjectListResponse(content=content)

    @get(DETAIL_ROUTE)
    async def get_fiscal_payment_mapping(
        self, service: Service, id: int
    ) -> ObjectResponse[FiscalPaymentMapping]:
        content = await service.get(id)
        return ObjectResponse(content=content)
