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

import com.banesco.common.application.helper.MessageHelper;
import com.banesco.common.domain.exception.HttpStatusCodeException;
import com.banesco.common.domain.model.ApiResponse;
import com.banesco.common.infrastructure.context.RequestContext;
import com.banesco.module.service_order_payment_search.application.usecase.DomainUseCase;
import com.banesco.module.service_order_payment_search.application.usecase.ServiceOrderPaymentSearchUseCase;
import com.banesco.module.service_order_payment_search.domain.dto.request.ServiceOrderPaymentSearchRequest;
import com.banesco.module.service_order_payment_search.domain.dto.response.ServiceOrderPaymentSearchResponse;
import com.banesco.module.security_trace.application.usecase.SecurityTraceUseCase;
import com.banesco.module.security_trace.domain.dto.response.SecurityTraceResponse;
import com.banesco.module.service_status.application.usecase.ServiceStatusUseCase;
import com.banesco.module.service_status.domain.dto.request.ServiceStatusRequest;
import com.banesco.module.service_status.domain.dto.response.ServiceStatusResponse;
import jakarta.enterprise.context.ApplicationScoped;
import jakarta.inject.Inject;
import lombok.extern.slf4j.Slf4j;

import java.util.Objects;

@Slf4j
@ApplicationScoped
public class ServiceOrderPaymentSearchService implements ServiceOrderPaymentSearchUseCase {

    private final MessageHelper messageHelper;
    private final ServiceStatusUseCase serviceStatusUseCase;
    private final SecurityTraceUseCase securityTraceUseCase;
    private final DomainUseCase domainUseCase;

    @Inject
    public ServiceOrderPaymentSearchService(
        MessageHelper messageHelper,
        ServiceStatusUseCase serviceStatusUseCase,
        SecurityTraceUseCase securityTraceUseCase,
        DomainUseCase domainUseCase
    ) {
        this.messageHelper = messageHelper;
        this.serviceStatusUseCase = serviceStatusUseCase;
        this.securityTraceUseCase = securityTraceUseCase;
        this.domainUseCase = domainUseCase;
    }

    @Override
    public ApiResponse<ServiceOrderPaymentSearchResponse> execute(
        ServiceOrderPaymentSearchRequest request
    ) {
        log.info("Iniciando ejecucion para la transaccion: {}", request.getId());

        if(!isServiceStatusActive(request)) {
            log.info("Estatus del servicio no disponible: {}", request.getId());
            throw HttpStatusCodeException.serviceUnavailable("VRN04");
        }

        try {
            ApiResponse<ServiceOrderPaymentSearchResponse> response = domain(request);

            if (
                !Objects.isNull(response.getData()) &&
                messageHelper.isSuccessStatusCode(response.getStatusResponse())
            ) {
                return new ApiResponse<>(response.getData(), messageHelper.createStatusResponse(
                    response.getStatusResponse().getStatusCode()
                ));
            }

            throw HttpStatusCodeException.serviceUnavailable("503");
        } catch (HttpStatusCodeException e) {
            log.error("Excepcion HTTP del api de dominio: {} - {}", e.getStatusCode(), e.getErrorCode());
            throw e;
        } catch (Exception e) {
            log.error("Excepcion generica del api de dominio: {}", e.getMessage());
            throw e;
        } finally {
            securityTrace();
        }
    }

    private ApiResponse<ServiceOrderPaymentSearchResponse> domain(
        ServiceOrderPaymentSearchRequest request
    ) {
        log.info("Ejecutando llamada al api de dominio: {}", request.getId());
        return domainUseCase.execute(request, ServiceOrderPaymentSearchResponse.class);
    }

    private boolean isServiceStatusActive(
        ServiceOrderPaymentSearchRequest request
    ) {
        log.info("Ejecutando llamada al api de la consulta del estatus del servicio");

        boolean isServiceActive = false;

        try {
            ServiceStatusResponse response = serviceStatusUseCase.execute(
                ServiceStatusRequest.builder()
                    .applicationId(request.getAppId())
                    .transactionId(RequestContext.getRequestId())
                    .build(),
                ServiceStatusResponse.class
            );

            isServiceActive = Objects.equals(response.getStatus(), "A");
        } catch (HttpStatusCodeException e) {
            log.info(
                "Error HTTP al ejecutar la consulta del estatus del servicio: {} -> {}",
                e.getStatusCode(),
                e.getMessage()
            );
        } catch (Exception e) {
            log.info(
                "Error al ejecutar la consulta del estatus del servicio: {}",
                e.getMessage()
            );
        }

        return isServiceActive;
    }

    private void securityTrace() {
        log.info("Ejecutando llamada al api de la traza de seguridad");
        securityTraceUseCase.execute(SecurityTraceResponse.class);
    }
}