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

import com.banesco.common.application.usecase.HttpClientUseCase;
import com.banesco.common.domain.exception.HttpApiResponseException;
import com.banesco.common.domain.exception.HttpStatusCodeException;
import com.banesco.common.domain.model.ApiResponse;
import com.banesco.common.domain.model.DomainConfig;
import com.banesco.common.domain.model.HttpRequest;
import com.banesco.common.infrastructure.config.RestClientConfig;
import com.banesco.module.service_order_payment_search.application.usecase.DomainUseCase;
import com.banesco.module.service_order_payment_search.domain.dto.request.ServiceOrderPaymentSearchRequest;
import jakarta.enterprise.context.ApplicationScoped;
import jakarta.inject.Inject;
import lombok.extern.slf4j.Slf4j;

import java.util.Map;

@Slf4j
@ApplicationScoped
public class DomServiceOrderPaymentSearchClient implements DomainUseCase {
    private final HttpClientUseCase httpClientUseCase;
    private final DomainConfig domainConfig;

    @Inject
    public DomServiceOrderPaymentSearchClient(
        HttpClientUseCase httpClientUseCase,
        RestClientConfig restClientConfig
    ) {
        this.httpClientUseCase = httpClientUseCase;
        this.domainConfig = restClientConfig.getDomServiceIssueConfig();
        log.info("Configuracion cargada para bus-service-order-payment-search: {}", domainConfig);
    }

    @Override
    public <T> ApiResponse<T> execute(
        ServiceOrderPaymentSearchRequest params,
        Class<T> responseType
    ) {
        String partyReferenceId = params.getId();
        String channelCode = params.getChannelCode();
        String signatureIdentifier = params.getSignatureIdentifier();
        HttpRequest request = HttpRequest.forApiResponse(
                domainConfig.getUrl(),
                HttpRequest.HttpMethod.GET,
                responseType
            )
            .withPathParams(Map.of(
                "partyReferenceId", partyReferenceId,
                "channelCode", channelCode,
                "signatureIdentifier", signatureIdentifier
            ))
            .withQueryParams(params.toQueryString())
            .withTimeout(
                domainConfig.getTimeout().getConnect(),
                domainConfig.getTimeout().getResponse()
            );

        log.debug("Request configurado: {}", request);

        try {
            ApiResponse<T> response = httpClientUseCase.executeApiResponse(request);

            log.info(
                "Solicitud del api de dominio exitoso: {}",
                response.getStatusResponse()
            );

            return response;
        } catch (HttpApiResponseException e) {
            log.error(
                "Error HTTP con ApiResponse consultando transaccion {}: {}",
                partyReferenceId,
                e.getApiResponse()
            );

            throw new HttpStatusCodeException(
                e.getStatusCode(),
                e.getApiResponse().getStatusResponse().getStatusCode()
            );
        } catch (HttpStatusCodeException e) {
            log.error(
                "Error HTTP consultando transaccion {}: {} - {}",
                partyReferenceId,
                e.getStatusCode(),
                e.getMessage()
            );

            throw e;
        } catch (Exception e) {
            log.error("Error consultando transaccion {}: {}", partyReferenceId, e.getMessage());
            throw HttpStatusCodeException.serviceUnavailable("503");
        }
    }
}