Необходимо сделать рефакторинг suspend fut GetLatestCommentsList и написать его через toEntity на основе референса остальных функций в коде. package ru.maxi.mobile.repositories.delivery.remote.order

import io.reactivex.Completable
import io.reactivex.Single
import ru.maxi.mobile.core.data.Money
import ru.maxi.mobile.core.network.utils.commonRest
import ru.maxi.mobile.core.network.utils.makeApiRequest
import ru.maxi.mobile.entity.delivery.order.EditOrder
import ru.maxi.mobile.entity.delivery.order.FreeDeliveryProgressEntity
import ru.maxi.mobile.entity.delivery.order.InitDataOrder
import ru.maxi.mobile.entity.delivery.order.Order
import ru.maxi.mobile.entity.delivery.order.OrderAddress
import ru.maxi.mobile.entity.delivery.order.OrderAddressParameters
import ru.maxi.mobile.entity.delivery.order.OrderOverWeightData
import ru.maxi.mobile.entity.delivery.order.OrderParameters
import ru.maxi.mobile.entity.delivery.order.OrderPaymentType
import ru.maxi.mobile.entity.delivery.order.OrderStateItem
import ru.maxi.mobile.entity.delivery.order.OrderWeightData
import ru.maxi.mobile.entity.delivery.order.StateType
import ru.maxi.mobile.entity.delivery.order.detail.OrderDeliveryInfo
import ru.maxi.mobile.entity.delivery.order.onlinepayment.OnlinePaymentCard
import ru.maxi.mobile.entity.delivery.order.onlinepayment.OnlinePaymentData
import ru.maxi.mobile.feature.delivery.config.entity.PaymentType
import ru.maxi.mobile.feature.delivery.latestComments.RestDeleteLastCommentRequest
import ru.maxi.mobile.feature.delivery.latestComments.model.Comment
import ru.maxi.mobile.feature.listorder.model.OrderDetailData
import ru.maxi.mobile.feature.listorder.model.OrderDetailProduct
import ru.maxi.mobile.repositories.delivery.remote.order.onlinepayment.RestOnlinePaymentCard
import ru.maxi.mobile.repositories.delivery.remote.order.onlinepayment.RestOnlinePaymentData
import ru.maxi.mobile.repositories.delivery.remote.order.onlinepayment.RestOnlinePaymentRequest
import java.util.UUID

/**
 * Репозиторий для работы с заказами доставки
 */
class OrderRepository(private val apiService: OrderApiService) {

    /**
     * Получить данные для оформления заказа
     */
    suspend fun getInitDataOrder(bonusCount: Int): InitDataOrder {
        return makeApiRequest {
            val response = apiService.getInitDataOrder(bonusCount)
            response.toEntity()
        }
    }

    /**
     * Отправить заказ с хеш суммой [hash] и параметрами [orderParameters]
     */
    suspend fun sendOrder(hash: String, orderParameters: OrderParameters): Order {
        val onlinePayment = orderParameters.paymentType as? OrderPaymentType.ByCardOnline
        val request = RestSendOrderRequest(
            orderHash = hash,
            address = orderParameters.orderAddress.toRest(),
            name = orderParameters.name,
            phone = orderParameters.phone,
            noProductAction = orderParameters.noProductAction,
            comment = orderParameters.comment,
            paymentType = orderParameters.paymentType.toPaymentType(),
            onlinePaymentCardId = onlinePayment?.card?.bindingId,
            bonusesCount = orderParameters.bonusesCount,
            email = orderParameters.email,
        )
        return makeApiRequest {
            val response = apiService.sendOrder(request)
            response.toEntity()
        }
    }

    /**
     * Получить список заказов с возможностью редактирования списка товаров
     */
    suspend fun getEditOrdersList(): List<EditOrder> {
        return makeApiRequest {
            val response = apiService.getEditOrdersList()
            response.orderList.map(RestEditOrder::toEntity)
        }
    }

    /**
     * Получить список заказов пользователя
     */
    suspend fun getOrderList(): List<Order> {
        return makeApiRequest {
            val response = apiService.getOrderList().orders
            response.map(RestOrder::toEntity)
        }
    }

    /**
     * Получить деталку заказа
     */
    fun getOrderDetailInfo(orderId: Long): Single<OrderDetailData> {
        return apiService.getOrderDetailInfo(orderId)
            .commonRest()
            .map(RestOrderDetailInfo::toEntity)
    }

    /**
     * Повторить заказ с идентификатором [orderId]
     */
    fun repeatOrder(orderId: Long): Completable {
        return apiService.repeatOrder(RestOrderIdRequest(orderId))
            .commonRest()
            .ignoreElement()
    }

    /**
     * Отправить запрос на отмену заказа
     */
    suspend fun cancelOrder(orderId: Long) {
        makeApiRequest {
            apiService.cancelOrder(RestOrderIdRequest(orderId))
        }
    }

    /**
     * Добавить корзину с хеш суммой [hash] к заказу с идентификатором [orderId]
     */
    fun addCartToOrder(orderId: Long, hash: String): Completable {
        val request = RestAddCartToOrderRequest(orderId, hash)
        return apiService.addCartToOrder(request)
            .commonRest()
            .ignoreElement()
    }

    /**
     * Получить список карт для онлайн оплаты
     */
    suspend fun getOnlinePaymentCardList(): List<OnlinePaymentCard> {
        return makeApiRequest {
            val response = apiService.getOnlinePaymentCardList()
            response.cardList.map(RestOnlinePaymentCard::toEntity)
        }
    }

    /**
     * Отправить запрос на получение данных для добавления новой карты для онлайн оплаты заказа
     *
     * @return данные для добавления новой карты
     */
    suspend fun addOnlinePaymentCard(): OnlinePaymentData {
        return makeApiRequest {
            val response = apiService.addOnlinePaymentCard()
            response.toEntity()
        }
    }

    /**
     * Удалить карту для онлайн оплаты с идентификатором привязки [bindingId]
     */
    suspend fun removeOnlinePaymentCard(bindingId: String) {
        makeApiRequest {
            apiService.removeOnlinePaymentCard(bindingId)
        }
    }

    /**
     * Отправить запрос на получение данных для онлайн оплаты заказа с идентификатором [orderId]
     */
    suspend fun startOrderOnlinePayment(orderId: Long): OnlinePaymentData {
        return makeApiRequest {
            val body = RestOnlinePaymentRequest(orderId)
            val response = apiService.startOrderOnlinePayment(body)
            response.toEntity()
        }
    }

    /**
     * Отправить запрос на получение данных для повторной онлайн оплаты заказа с идентификатором [orderId]
     */
    suspend fun repeatOrderOnlinePayment(orderId: Long): OnlinePaymentData {
        return makeApiRequest {
            val body = RestOnlinePaymentRequest(orderId)
            val response = apiService.repeatOrderOnlinePayment(body)
            response.toEntity()
        }
    }

    /**
     * Получить список последних комментариев
     */
    suspend fun getLatestCommentsList(): List<Comment> {
        return makeApiRequest {
            val response = apiService.getLatestCommentsList().comments
            response.map { text ->
                Comment(
                    id = UUID.randomUUID().hashCode().toLong(),
                    text = text,
                )
            }
        }
    }

    /**
     * Удалить последний комментарий с текстом [text]
     */
    suspend fun deleteLastComment(text: String) {
        makeApiRequest {
            val request = RestDeleteLastCommentRequest(text)
            apiService.deleteLastComment(request)
        }
    }
}

private fun RestOrderAddress.toEntity() = OrderAddress(
    street = street,
    apartment = apartment,
    entrance = entrance,
    floor = floor,
)

private fun RestOrderState.toEntity() = OrderStateItem(
    isActive = isActive,
    state = state,
    description = description,
    stateType = StateType.valueOf(stateType),
)

private fun RestOrderDetailInfo.toEntity() = OrderDetailData(
    orderId = order.id,
    orderDate = order.orderDate,
    phone = phone,
    address = address.toEntity(),
    deliveryInfo = OrderDeliveryInfo(
        deliveryInfo.date,
        Money(deliveryInfo.price),
        deliveryInfo.startDeliveryTime,
        deliveryInfo.endDeliveryTime,
    ),
    stateList = stateList.map(RestOrderState::toEntity),
    comment = comment,
    additionalInfo = additionalInfo?.trim()?.takeIf(String::isNotEmpty),
    paymentType = paymentType,
    paymentDate = paymentDate,
    waitingPayment = waitingPayment,
    paymentTypeChanged = paymentTypeChanged,
    email = email,
    productList = order.productList.map(RestOrderProduct::toEntity),
    totalAmount = Money(totalAmount),
    discount = Money(discount),
    bonuses = bonuses?.let { Money.fromWholePart(it.toLong()) },
    npsUuid = npsUuid,
    canCancel = canCancel,
    canCorrect = canCorrect,
    canRepeat = canRepeat,
    canRepeatSbpPay = canRepeatSbpPay,
    weightData = weightData?.toEntity(),
)

private fun RestOrderProduct.toEntity() = OrderDetailProduct(
    id = id,
    name = name,
    price = Money(price),
    count = count,
    imageUrl = imageUrl,
)

private fun RestInitDataOrder.toEntity() = InitDataOrder(
    clientAddress = clientAddress,
    deliveryAddress = deliveryAddress,
    intervalBegin = intervalBegin,
    intervalEnd = intervalEnd,
    deliveryDate = deliveryDate,
    deliveryPrice = Money(deliveryPrice.toLong()),
    freeDeliveryProgress = freeDeliveryProgress?.toEntity(),
    orderSum = orderSum,
    promoCodeDiscount = promoCodeDiscount,
    bonusesPointsDiscount = bonusesPointsDiscount,
    email = email,
    weightData = weightData.toEntity(),
    hasSavedComments = hasSavedComments,
)

private fun RestEditOrder.toEntity() = EditOrder(
    id = id,
    date = date,
)

private fun OrderAddressParameters.toRest() = RestOrderAddressParameters(
    apartment = apartment,
    entrance = entrance,
    floor = floor,
)

private fun RestFreeDeliveryProgress.toEntity() = FreeDeliveryProgressEntity(
    startSum = startSum,
    finishSum = finishSum,
    currentSum = currentSum,
    startSumTitle = startSumTitle,
    finishSumTitle = finishSumTitle,
    message = message,
)

private fun RestOnlinePaymentCard.toEntity() = OnlinePaymentCard(
    bindingId = bindingId,
    type = type,
    number = number,
    shortNumber = shortNumber,
    bankLogo = bankLogo,
    bankColor = bankColor,
)

private fun RestOnlinePaymentData.toEntity() = OnlinePaymentData(
    formUrl = paymentFormUrl,
    merchantName = merchantName,
)

private fun OrderPaymentType.toPaymentType(): PaymentType {
    return when (this) {
        OrderPaymentType.ByCard -> PaymentType.CARD
        is OrderPaymentType.ByCardOnline -> PaymentType.ONLINE
        OrderPaymentType.ByNewCardOnline -> PaymentType.ONLINE
        OrderPaymentType.Cash -> PaymentType.CASH
        OrderPaymentType.ViaSbp -> PaymentType.SBP
    }
}

private fun RestOrderWeightData.toEntity() = OrderWeightData(
    totalWeight = totalWeight,
    overWeightData = if (overWeight == null || overWeightAmount == null) {
        null
    } else {
        OrderOverWeightData(
            overWeight = overWeight,
            overWeightAmount = overWeightAmount,
        )
    },
)