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

import com.banesco.common.application.helper.MessageResponseHelper;
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.legal_customer_product_directory.application.usecase.DomainUseCase;
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.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 LegalCustomerProductDirectoryService implements LegalCustomerProductDirectoryUseCase {

    private final MessageResponseHelper messageResponseHelper;
    private final ServiceStatusUseCase serviceStatusUseCase;
    private final SecurityTraceUseCase securityTraceUseCase;
    private final DomainUseCase domainUseCase;

    @Inject
    public LegalCustomerProductDirectoryService(
        MessageResponseHelper messageResponseHelper,
        ServiceStatusUseCase serviceStatusUseCase,
        SecurityTraceUseCase securityTraceUseCase,
        DomainUseCase domainUseCase
    ) {
        this.messageResponseHelper = messageResponseHelper;
        this.serviceStatusUseCase = serviceStatusUseCase;
        this.securityTraceUseCase = securityTraceUseCase;
        this.domainUseCase = domainUseCase;
    }

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

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

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

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

            throw HttpStatusCodeException.serviceUnavailable("503");
        } catch (HttpStatusCodeException e) {
            log.error("Excepción HTTP del api de dominio: {} - {}", e.getStatusCode(), e.getMessage());
            throw e;
        } catch (Exception e) {
            log.error("Excepción genérica del api de dominio: {}", e.getMessage());
            throw e;
        } finally {
            securityTrace();
        }
    }

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

    private boolean serviceStatus(
        LegalCustomerProductDirectoryRequest 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 estadus del servicio: {} -> {}",
                e.getStatusCode(),
                e.getMessage()
            );
        } catch (Exception e) {
            log.info(
                "Error al ejecutar la consulta del estadus del servicio: {}",
                e.getMessage()
            );
        }

        return isServiceActive;
    }

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