package com.banesco.module.legal_customer_product_directory.application.service;

import com.banesco.common.application.helper.MessageResponseHelper;
import com.banesco.common.application.helper.RequestValidatorHelper;
import com.banesco.common.domain.exception.BaseApiException;
import com.banesco.common.domain.exception.ServiceUnavailableException;
import com.banesco.common.domain.model.*;
import com.banesco.module.account.domain.model.*;
import com.banesco.common.domain.model.Agreement;
import com.banesco.common.domain.model.Arrangement;
import com.banesco.common.domain.model.ArrangementType;
import com.banesco.module.legal_customer_product_directory.application.usecase.BusinessUseCase;
import com.banesco.module.legal_customer_product_directory.application.usecase.LegalCustomerProductDirectoryUseCase;
import com.banesco.module.legal_customer_product_directory.domain.dto.request.LegalCustomerProductDirectoryRequest;
import com.banesco.module.legal_customer_product_directory.domain.dto.response.LegalCustomerProductDirectoryResponse;
import com.banesco.module.legal_customer_product_directory.domain.model.CustomerProductAndServiceDirectory;
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.party.domain.model.PartyType;
import jakarta.enterprise.context.ApplicationScoped;
import jakarta.inject.Inject;
import lombok.extern.slf4j.Slf4j;

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

@Slf4j
@ApplicationScoped
public class LegalCustomerProductDirectoryService implements LegalCustomerProductDirectoryUseCase {

    private final MessageResponseHelper messageResponseHelper;
    private final RequestValidatorHelper requestValidatorHelper;
    private final BusinessUseCase businessUseCase;

    @Inject
    public LegalCustomerProductDirectoryService(
        MessageResponseHelper messageResponseHelper,
        RequestValidatorHelper requestValidatorHelper,
        BusinessUseCase businessUseCase
    ) {
        this.messageResponseHelper = messageResponseHelper;
        this.requestValidatorHelper = requestValidatorHelper;
        this.businessUseCase = businessUseCase;
    }

    @Override
    public ApiResponse<LegalCustomerProductDirectoryResponse> execute(
        LegalCustomerProductDirectoryRequest request
    ) {
        log.info("Iniciando ejecución para el cliente: {}", request.getCustomerIbsNumber());

        validate(request);

        try {
            return business(request);
        } catch (BaseApiException e) {
            log.warn("Excepción controlada del api de negocio: {} -> {}", e.getErrorCode(), e.getMessage());

            if(Objects.equals(e.getErrorCode(), "200")) {
                return createSuccessMock();
            }

            throw e;
        } catch (Exception e) {
            log.warn("Excepción generica del api de negocio: {}", e.getMessage());
            throw new ServiceUnavailableException("503", e.getMessage(), null);
        }
    }

    private void validate(
        LegalCustomerProductDirectoryRequest request
    ) {
        requestValidatorHelper.validateRequired(request);
    }

    private ApiResponse<LegalCustomerProductDirectoryResponse> business(
        LegalCustomerProductDirectoryRequest request
    ) {
        log.info("Calling business service for client: {}", request.getCustomerIbsNumber());

        return businessUseCase.execute(
            true,
            request.getCustomerIbsNumber(),
            Map.of(),
            request.toBusinessHeaders(),
            LegalCustomerProductDirectoryResponse.class
        );
    }

    private ApiResponse<LegalCustomerProductDirectoryResponse> createSuccessMock() {
        return new ApiResponse<>(
            LegalCustomerProductDirectoryResponse.builder()
                .customerProductAndServiceDirectory(
                    CustomerProductAndServiceDirectory.builder()
                        .accounts(List.of(getAccount()))
                        .build()
                )
                .build(),
            messageResponseHelper.createSuccessResponse("200")
        );
    }

    private Account getAccount() {
        return Account.builder()
            .accountStatus(AccountStatus.builder()
                .status("A")
                .statusType(AccountStatusType.ENABLED)
                .build())
            .accountType(AccountType.CURRENT_ACCOUNT)
            .accountIdentification(List.of(
                AccountIdentification.builder()
                    .accountIdentificationType(AccountIdentificationType.ACCOUNT_NUMBER)
                    .accountIdentification(Identifier.builder()
                        .identifierValue("01340025330253093528")
                        .build())
                    .build(),
                AccountIdentification.builder()
                    .accountIdentificationType(AccountIdentificationType.BANK_NUMBER)
                    .accountIdentification(Identifier.builder()
                        .identifierValue("01")
                        .build())
                    .build(),
                AccountIdentification.builder()
                    .accountIdentificationType(AccountIdentificationType.PRODUCT_CODE)
                    .accountIdentification(Identifier.builder()
                        .identifierValue("3980")
                        .build())
                    .build(),
                AccountIdentification.builder()
                    .accountIdentificationType(AccountIdentificationType.ACCOUNT_CLASS)
                    .accountIdentification(Identifier.builder()
                        .identifierValue("80")
                        .build())
                    .build()
            ))
            .accountBalance(List.of(
                AccountBalance.builder()
                    .balanceAmount(BigDecimal.valueOf(390417.36))
                    .balanceType(BalanceType.AVAILABLE_BALANCE)
                    .build(),
                AccountBalance.builder()
                    .balanceAmount(BigDecimal.valueOf(100000.00))
                    .balanceType(BalanceType.DAILY_MAXIMUM)
                    .build(),
                AccountBalance.builder()
                    .balanceAmount(BigDecimal.valueOf(3000000.00))
                    .balanceType(BalanceType.MONTHLY_MAXIMUM)
                    .build(),
                AccountBalance.builder()
                    .balanceAmount(BigDecimal.valueOf(0.01))
                    .balanceType(BalanceType.TRANSACTION_MINIMUM)
                    .build(),
                AccountBalance.builder()
                    .balanceAmount(BigDecimal.valueOf(100000.00))
                    .balanceType(BalanceType.TRANSACTION_MAXIMUM)
                    .build()
            ))
            .accountCurrency(List.of(
                AccountCurrency.builder()
                    .currencyCode("BS")
                    .currencyType(CurrencyType.BASE)
                    .build()
            ))
            .accountInvolvement(List.of(
                AccountInvolvement.builder()
                    .accountInvolvementType(AccountInvolvementType.PARTY_IS_OWNER_OF_ACCOUNT)
                    .partyReference(
                        Party.builder()
                            .partyName(List.of(
                                Name.builder()
                                    .fullName("TASCA RESTAURANT GOOD WORLD CEN, C.A.")
                                    .build()
                            ))
                            .partyType(PartyType.ORGANISATION)
                            .partyIdentification(List.of(
                                PartyIdentification.builder()
                                    .partyIdentificationType(PartyIdentificationType.TAX_IDENTIFICATION_NUMBER)
                                    .partyIdentification(Identifier.builder()
                                        .identifierValue("J000000001")
                                        .build())
                                    .build(),
                                PartyIdentification.builder()
                                    .partyIdentificationType(PartyIdentificationType.TELEPHONE_NUMBER)
                                    .partyIdentification(Identifier.builder()
                                        .identifierValue("04122710660")
                                        .build())
                                    .build(),
                                PartyIdentification.builder()
                                    .partyIdentificationType(PartyIdentificationType.TELEPHONE_OPERATOR)
                                    .partyIdentification(Identifier.builder()
                                        .identifierValue("0412")
                                        .build())
                                    .build()
                            ))
                            .build()
                    )
                    .build()
            ))
            .accountRelationship(List.of(
                AccountRelationship.builder()
                    .accountRelationshipType(AccountRelationshipType.ACCOUNT_IS_SUB_ACCOUNT_FOR_ACCOUNT)
                    .build()
            ))
            .agreement(List.of(
                Agreement.builder()
                    .arrangement(List.of(
                        Arrangement.builder()
                            .arrangementType(ArrangementType.INTEREST_ARRANGEMENT)
                            .build()
                    ))
                    .build()
            ))
            .build();
    }
}