package com.banesco.module.get_affiliation.infrastructure.client;

import com.banesco.common.application.usecase.HttpClientUseCase;
import com.banesco.common.domain.exception.HttpStatusCodeException;
import com.banesco.common.domain.model.Either;
import com.banesco.common.domain.model.HttpRequest;
import com.banesco.common.infrastructure.config.RestClientConfig;
import com.banesco.module.get_affiliation.application.usecase.GetAffiliationUseCase;
import com.banesco.module.get_affiliation.domain.dto.request.GetAffiliationRequest;
import com.banesco.module.get_affiliation.domain.model.GetAffiliationConfig;
import com.banesco.module.msg_request_header.domain.model.MsgRqHdr;
import com.banesco.module.payment_initiation_request.domain.dto.request.PaymentInitiationRequestRequest;
import jakarta.enterprise.context.ApplicationScoped;
import jakarta.inject.Inject;
import lombok.extern.slf4j.Slf4j;

@Slf4j
@ApplicationScoped
public class GetAffiliationClient implements GetAffiliationUseCase {
    private final HttpClientUseCase httpClientUseCase;
    private final GetAffiliationConfig getAffiliationConfig;

    @Inject
    public GetAffiliationClient(
        HttpClientUseCase httpClientUseCase,
        RestClientConfig restClientConfig
    ) {
        this.httpClientUseCase = httpClientUseCase;
        this.getAffiliationConfig = restClientConfig.getGetAffiliationConfig();
        log.info("Configuracion cargada para security-trace: {}", getAffiliationConfig);
    }

    @Override
    public <T, R> Either<T, R> execute(
        PaymentInitiationRequestRequest apiRequest,
        Class<T> responseType,
        Class<R> errorType
    ) {
        GetAffiliationRequest body = getRequest(apiRequest);
        HttpRequest request = HttpRequest.forDirectResponse(
                getAffiliationConfig.getUrl(),
                HttpRequest.HttpMethod.POST,
                responseType,
                errorType
            )
            .withBody(body)
            .withTimeout(
                getAffiliationConfig.getTimeout().getConnect(),
                getAffiliationConfig.getTimeout().getResponse()
            );

        try {
            Either<T, R> response = httpClientUseCase.executeEither(request);

            log.info(
                "Solicitud de consulta de afiliacion exitosa: {}",
                response.isLeft() && response.getLeft().toString().contains("msgRsHdr=")
            );

            return response;
        } catch (HttpStatusCodeException e) {
            log.error(
                "Error HTTP ejecutando consulta de afiliacion: {} - {}",
                e.getStatusCode(),
                e.getMessage()
            );

            throw e;
        } catch (Exception e) {
            log.error("Error ejecutando consulta de afiliacion: {}", e.getMessage());
            throw HttpStatusCodeException.serviceUnavailable("503");
        }
    }

    private GetAffiliationRequest getRequest(
        PaymentInitiationRequestRequest apiRequest
    ) {
        String payeeId = apiRequest.getPayeeId();
        MsgRqHdr msgRqHdr = getAffiliationConfig
            .getRequest()
            .getMsgRqHdr()
            .withOptions(apiRequest.getDevice());

        return GetAffiliationRequest.builder()
            .msgRqHdr(msgRqHdr)
            .type(payeeId.substring(0, 1).toUpperCase())
            .identSerialNum(getPartyIdNumber(payeeId.substring(1)))
            .phone(getAffiliationConfig.getRequest().getPhone())
            .svcType(getAffiliationConfig.getRequest().getSvcType())
            .affilType(getAffiliationConfig.getRequest().getAffilType())
            .sourceChannelCode(getAffiliationConfig.getRequest().getSourceChannelCode())
            .domain(getAffiliationConfig.getRequest().getDomain())
            .build();
    }

    private String getPartyIdNumber(String partyId) {
        if (partyId == null || partyId.trim().isEmpty()) {
            return null;
        }

        String digits = partyId.replaceAll("\\D", "");

        if (digits.isEmpty()) {
            return null;
        }

        return digits;
    }
}