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

import com.banesco.common.application.helper.ErrorResponseHelper;
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.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.Objects;

@Slf4j
@ApplicationScoped
public class LegalCustomerProductDirectoryService implements LegalCustomerProductDirectoryUseCase {

    private final RequestValidatorHelper requestValidatorHelper;
    private final BusinessUseCase businessUseCase;

    @Inject
    public LegalCustomerProductDirectoryService(
        ErrorResponseHelper errorResponseHelper,
        RequestValidatorHelper requestValidatorHelper,
        BusinessUseCase businessUseCase
    ) {
        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(), e);
            throw new ServiceUnavailableException("503", e.getMessage(), null);
        }
    }

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

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

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

    private ApiResponse<LegalCustomerProductDirectoryResponse> createSuccessMock() {
        StatusResponse statusResponse = StatusResponse.builder()
                .statusCode("200")
                .message("Operación exitosa")
                .build();

        return new ApiResponse<>(
                LegalCustomerProductDirectoryResponse.builder()
                        .customerProductAndServiceDirectory(CustomerProductAndServiceDirectory.builder()
                                .party(Party.builder()
                                        .partyName(List.of(
                                                Name.builder()
                                                        .fullName("TASCA RESTAURANT GOOD WORLD CEN, C.A.")
                                                        .build()
                                        ))
                                        .partyType(PartyType.ORGANISATION)
                                        .partyDateTime(List.of())
                                        .partyIdentification(List.of(
                                                PartyIdentification.builder()
                                                        .partyIdentificationType(PartyIdentificationType.TAX_IDENTIFICATION_NUMBER)
                                                        .partyIdentification(Identifier.builder()
                                                                .identifierValue("J000000001")
                                                                .issuingAuthority("")
                                                                .build())
                                                        .build()
                                        ))
                                        .partyLegalStructureType("")
                                        .build())
                                .accounts(List.of(
                                        Account.builder()
                                                .accountStatus(AccountStatus.builder()
                                                        .status("D")
                                                        .build())
                                                .accountIdentification(List.of(
                                                        AccountIdentification.builder()
                                                                .accountIdentificationType("NUMERO_CUENTA")
                                                                .accountIdentification(Identifier.builder()
                                                                        .identifierValue("01340025330253093528")
                                                                        .issuingAuthority("")
                                                                        .build())
                                                                .build(),
                                                        AccountIdentification.builder()
                                                                .accountIdentificationType("NUMERO_BANCO")
                                                                .accountIdentification(Identifier.builder()
                                                                        .identifierValue("01")
                                                                        .issuingAuthority("")
                                                                        .build())
                                                                .build(),
                                                        AccountIdentification.builder()
                                                                .accountIdentificationType("CODIGO_PRODUCTO")
                                                                .accountIdentification(Identifier.builder()
                                                                        .identifierValue("3980")
                                                                        .issuingAuthority("")
                                                                        .build())
                                                                .build(),
                                                        AccountIdentification.builder()
                                                                .accountIdentificationType("CLASE_CUENTA")
                                                                .accountIdentification(Identifier.builder()
                                                                        .identifierValue("80")
                                                                        .issuingAuthority("")
                                                                        .build())
                                                                .build(),
                                                        AccountIdentification.builder()
                                                                .accountIdentificationType("TIPO_CUENTA")
                                                                .accountIdentification(Identifier.builder()
                                                                        .identifierValue("MMK")
                                                                        .issuingAuthority("")
                                                                        .build())
                                                                .build()
                                                ))
                                                .accountDate(List.of())
                                                .accountBalance(List.of(
                                                        AccountBalance.builder()
                                                                .balanceAmount(BigDecimal.valueOf(390417.36))
                                                                .balanceType("SALDO_DISPONIBLE")
                                                                .build(),
                                                        AccountBalance.builder()
                                                                .balanceAmount(BigDecimal.valueOf(100000.00))
                                                                .balanceType("MAXIMO_DIARIO")
                                                                .build(),
                                                        AccountBalance.builder()
                                                                .balanceAmount(BigDecimal.valueOf(100000.00))
                                                                .balanceType("MAXIMO_TRANSACCION")
                                                                .build(),
                                                        AccountBalance.builder()
                                                                .balanceAmount(BigDecimal.valueOf(3000000.00))
                                                                .balanceType("MAXIMO_MENSUAL")
                                                                .build(),
                                                        AccountBalance.builder()
                                                                .balanceAmount(BigDecimal.valueOf(0.01))
                                                                .balanceType("MINIMO_TRANSACCION")
                                                                .build()
                                                ))
                                                .accountCurrency(List.of(
                                                        AccountCurrency.builder()
                                                                .currencyCode("BS")
                                                                .currencyType(CurrencyType.BASE)
                                                                .build()
                                                ))
                                                .accountDescription("TASCA RESTAURANT GOOD WORLD CEN, C.A.")
                                                .accountName("")
                                                .accountInvolvement(List.of(
                                                        AccountInvolvement.builder()
                                                                .accountInvolvementType("CONTACTO_TELEFONICO")
                                                                .partyReference(Party.builder()
                                                                        .partyIdentification(List.of(
                                                                                PartyIdentification.builder()
                                                                                        .partyIdentificationType(PartyIdentificationType.TELEPHONE_NUMBER)
                                                                                        .partyIdentification(Identifier.builder()
                                                                                                .identifierValue("04122710660")
                                                                                                .issuingAuthority("")
                                                                                                .build())
                                                                                        .build()
                                                                        ))
                                                                        .build())
                                                                .build()
                                                ))
                                                .build()
                                ))
                                .build())
                        .build(),
                statusResponse
        );
    }
}