package application.usecase;

import application.exception.GatewayServiceException;
import application.port.input.IServiceStatus;
import application.port.input.command.ServiceStatusCommand;
import application.port.output.IMaintenanceCheckPort;
import com.banesco.common.infraestructure.helpers.JsonHelper;
import com.banesco.common.infraestructure.helpers.LoggerHelper;
import domain.repository.IStatusPort;
import jakarta.enterprise.context.ApplicationScoped;
import jakarta.inject.Inject;
import lombok.extern.slf4j.Slf4j;


@Slf4j
@ApplicationScoped
public class ServiceStatusUseCase implements IServiceStatus {

    private static final String INACTIVE_STATUS = "I";

    private final IStatusPort statusApiPort;
    private final IMaintenanceCheckPort maintenancePort;

    @Inject
    public ServiceStatusUseCase(
            IStatusPort statusApiService,
            IMaintenanceCheckPort maintenancePort
    ) {
        this.statusApiPort = statusApiService;
        this.maintenancePort = maintenancePort;
    }

    /**
     * Determina el estado de disponibilidad de un servicio, devolviendo true si está activo y false si no lo está.
     *
     * @param command El objeto de comando que contiene los datos necesarios para la consulta, como el ID de aplicación y transacción.
     * @param requestId Un identificador único de la solicitud, utilizado principalmente para la trazabilidad en los logs.
     * @return {@code true} si el servicio se considera activo; {@code false} si está inactivo, en mantenimiento o si la verificación falló.
     */
    @Override
    public Boolean execute(ServiceStatusCommand command, String requestId) {
        log.debug(LoggerHelper.buildInfoPrivateRequest(requestId, "Iniciando caso de uso: Service Status"));

        // Si no estamos en ventana de mantenimiento, el servicio está activo.
        if(!maintenancePort.isUnderMaintenance(requestId)) {
            log.info(LoggerHelper.buildInfoPrivateRequest(requestId, "No estamos en ventana de mantenimiento. Servicio ACTIVO"));
            return true;
        }

        log.info(LoggerHelper.buildInfoPrivateRequest(requestId, "En ventana de mantenimiento, consultando estado remoto..."));

        try {
            // Si estamos en horario de validacion, consultamos el estado remoto.
            var remoteStatus = statusApiPort.getServiceStatus(command, requestId);

            var isActive = remoteStatus != null && !INACTIVE_STATUS.equalsIgnoreCase(remoteStatus.getStatus());

            if (isActive) {
                log.info(LoggerHelper.buildInfoPrivateRequest(requestId, "El servicio externo confirmo estado ACTIVO"));
            } else {
                log.warn(LoggerHelper.buildInfoPrivateRequest(requestId, "El servicio externo esta nulo o en estado INACTIVO"));
            }
            return isActive;
        } catch (GatewayServiceException ex) {
            log.error(LoggerHelper.buildError(requestId, "Fallo la comunicacion con el servicio de service status"));
            throw ex;
        } finally {
            log.debug(LoggerHelper.buildInfoPrivateRequest(requestId, "Finalizado caso de uso: Service Status"));
        }
    }

}