package com.banesco.module.payment_instruction_request.infrastructure.mapper;

import com.banesco.common.domain.model.Identifier;
import com.banesco.module.arrangement.domain.model.Arrangement;
import com.banesco.module.arrangement.domain.model.ArrangementInvolvement;
import com.banesco.module.arrangement.domain.model.ArrangementInvolvementType;
import com.banesco.module.banking_product.domain.model.BankingProduct;
import com.banesco.module.party.domain.model.Party;
import com.banesco.module.party.domain.model.PartyIdentification;
import com.banesco.module.party.domain.model.PartyIdentificationType;
import com.banesco.module.payment_instruction_request.domain.dto.request.PaymentInstructionRequestRequest;
import com.banesco.module.payment_instruction_request.domain.model.PaymentArrangement;
import com.banesco.module.payment_instruction_request.domain.model.PaymentDateTime;
import com.banesco.module.payment_instruction_request.domain.model.PaymentDateTimeType;
import com.banesco.module.payment_instruction_request.domain.model.PaymentInstructionTransaction;
import com.banesco.module.payment_request.domain.dto.request.PaymentRequestRequest;
import com.banesco.module.payment_request.domain.model.Global;
import com.banesco.module.payment_request.domain.model.PaymentRequest;
import com.banesco.module.payment_request.domain.model.Solicitud;
import io.netty.util.internal.StringUtil;

import java.math.BigDecimal;
import java.util.List;
import java.util.Objects;

public class ServicingIssueMapper {

    private ServicingIssueMapper() {}

    public static PaymentRequestRequest toPaymentRequest(
        PaymentInstructionRequestRequest request
    ) {
        return PaymentRequestRequest.builder()
            .fintechId(request.getCustomerReferenceFintechId())
            .global(
                Global.builder()
                    .telefonoDestino(request.getRecipientPhone())
                    .identificacionDestino(request.getRecipientId())
                    .codigoBancoDestino(request.getBankCode())
                    .montoTransaccion((!Objects.isNull(request.getAmount()))
                        ? request.getAmount().toPlainString()
                        : null
                    )
                    .concepto(request.getPurpose())
                    .fechaHoraEfectiva(request.getEffectiveDate())
                    .build()
            )
            .solicitudes(
                request
                    .getPaymentInstructionTransaction()
                    .getPaymentArrangement()
                    .stream().map(item ->
                        Solicitud.builder()
                            .telefonoOrigen(item.getApplicantPhone())
                            .identificacionOrigen(item.getApplicantId())
                            .telefonoDestino(item.getRecipientPhone())
                            .identificacionDestino(item.getRecipientId())
                            .codigoBancoDestino(item.getBankCode())
                            .montoTransaccion((!Objects.isNull(item.getAmount()))
                                ? item.getAmount().toPlainString()
                                : null
                            )
                            .concepto(item.getPurpose())
                            .fechaHoraEfectiva(item.getEffectiveDate())
                            .build()
                    )
                    .toList()
            )
            .canalOrigen(request.getChannelCode())
            .build();
    }

    public static PaymentInstructionTransaction toModel(List<PaymentRequest> response) {
        return PaymentInstructionTransaction.builder()
            .paymentArrangement(response.stream().map(item ->
                PaymentArrangement.builder()
                    .arrangement(List.of(
                        Arrangement.builder()
                            .arrangementInvolvement(List.of(
                                ArrangementInvolvement.builder()
                                    .arrangementInvolvementType(ArrangementInvolvementType.PARTY_IS_OBLIGEE_IN_ARRANGEMENT)
                                    .partyReference(
                                        Party.builder()
                                            .partyIdentification(List.of(
                                                PartyIdentification.builder()
                                                    .partyIdentificationType(PartyIdentificationType.IDENTITY_CARD_NUMBER)
                                                    .partyIdentification(
                                                        Identifier.builder()
                                                            .identifierValue(item.getIdentificacionDestino())
                                                            .build()
                                                    )
                                                    .build(),
                                                PartyIdentification.builder()
                                                    .partyIdentificationType(PartyIdentificationType.TELEPHONE_NUMBER)
                                                    .partyIdentification(
                                                        Identifier.builder()
                                                            .identifierValue(item.getTelefonoDestino())
                                                            .build()
                                                    )
                                                    .build()
                                            ))
                                            .build()
                                    )
                                    .build(),
                                ArrangementInvolvement.builder()
                                    .arrangementInvolvementType(ArrangementInvolvementType.PARTY_IS_OBLIGOR_IN_ARRANGEMENT)
                                    .partyReference(
                                        Party.builder()
                                            .partyIdentification(List.of(
                                                PartyIdentification.builder()
                                                    .partyIdentificationType(PartyIdentificationType.IDENTITY_CARD_NUMBER)
                                                    .partyIdentification(
                                                        Identifier.builder()
                                                            .identifierValue(item.getIdentificacionOrigen())
                                                            .build()
                                                    )
                                                    .build(),
                                                PartyIdentification.builder()
                                                    .partyIdentificationType(PartyIdentificationType.TELEPHONE_NUMBER)
                                                    .partyIdentification(
                                                        Identifier.builder()
                                                            .identifierValue(item.getTelefonoOrigen())
                                                            .build()
                                                    )
                                                    .build()
                                            ))
                                            .build()
                                    )
                                    .build()
                            ))
                            .build()
                    ))
                    .bankingProduct(
                        BankingProduct.builder()
                            .productName(item.getCodigoBancoDestino())
                            .build()
                    )
                    .paymentAmount((!StringUtil.isNullOrEmpty(item.getMontoTransaccion()))
                        ? new BigDecimal(item.getMontoTransaccion())
                        : null
                    )
                    .paymentPurpose(item.getConcepto())
                    .paymentDate(List.of(
                        PaymentDateTime.builder()
                            .dateType(PaymentDateTimeType.EFFECTIVITY_DATE)
                            .date(item.getFechaHoraEfectiva())
                            .build()
                    ))
                    .build()
            ).toList())
            .build();
    }
}