package com.banesco.module.correspondence.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.correspondence.application.usecase.DomainUseCase;
import com.banesco.module.correspondence.application.usecase.CorrespondenceUseCase;
import com.banesco.module.correspondence.domain.dto.request.CorrespondenceRequest;
import com.banesco.module.correspondence.domain.dto.response.CorrespondenceResponse;
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 jakarta.ws.rs.core.Response;
import lombok.extern.slf4j.Slf4j;

import java.util.Objects;

@Slf4j
@ApplicationScoped
public class CorrespondenceService implements CorrespondenceUseCase {

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

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

    @Override
    public Response execute(
        CorrespondenceRequest request
    ) {
        log.info("Iniciando ejecucion para la transaccion: {}", request.getId());

        Response response = null;
        long startTime = System.currentTimeMillis();

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

            ApiResponse<CorrespondenceResponse> apiResponse = domain(request);

            response = messageHelper.handleSuccess(
                apiResponse.getData(),
                apiResponse.getStatusResponse().getStatusCode()
            );
        } catch (HttpStatusCodeException e) {
            log.error("Excepcion HTTP del api de dominio: {} - {}", e.getStatusCode(), e.getErrorCode());
            response = messageHelper.handleException(e);
        } catch (Exception e) {
            log.error("Excepcion generica del api de dominio: {}", e.getMessage());
            response = messageHelper.handleGenericException(e);
        } finally {
            long endTime = System.currentTimeMillis();
            securityTrace(request, response, startTime, endTime);
        }

        return response;
    }

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

    private boolean isServiceStatusActive(
        CorrespondenceRequest 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(
        CorrespondenceRequest request,
        Response response,
        long startTime,
        long endTime
    ) {
        log.info("Ejecutando llamada al api de la traza de seguridad");

        try {
            securityTraceUseCase.execute(
                request, response,
                startTime, endTime,
                SecurityTraceResponse.class
            );
        } catch (HttpStatusCodeException e) {
            log.info(
                "Error HTTP al ejecutar la traza de seguridad: {} -> {}",
                e.getStatusCode(),
                e.getMessage()
            );
        } catch (Exception e) {
            log.info("Error al ejecutar la traza de seguridad: {}", e.getMessage());
        }
    }
}