package infrastructure.client.registersecurity.adapter;

import application.port.input.command.RegisterSecurityCommand;
import com.banesco.common.infraestructure.helpers.LoggerHelper;
import domain.repository.IRegisterSecurityPort;
import infrastructure.client.registersecurity.api.RegisterSecurityClient;
import infrastructure.mapper.RegisterSecurityMapper;
import jakarta.enterprise.context.ApplicationScoped;
import jakarta.inject.Inject;
import jakarta.ws.rs.WebApplicationException;
import lombok.extern.slf4j.Slf4j;
import org.eclipse.microprofile.rest.client.inject.RestClient;

@Slf4j
@ApplicationScoped
public class RegisterSecurityAdapter implements IRegisterSecurityPort {

    private final RegisterSecurityClient client;
    private final RegisterSecurityMapper mapper;

    @Inject
    public RegisterSecurityAdapter(
            @RestClient RegisterSecurityClient client,
            RegisterSecurityMapper mapper
    ) {
        this.client = client;
        this.mapper = mapper;
    }

    @Override
    public void writeTrace(RegisterSecurityCommand command, String requestId) {
        try {
            log.debug(LoggerHelper.buildInfoPrivateRequest(requestId, "Adaptador: Mapeando Command a DTO para register security"));
            var requestDto = mapper.toRequestDto(command);
            log.info(LoggerHelper.buildInfoPrivateRequest(requestId, "Llamando al servicio de register security (asincrono)", requestDto));

            client.registerSecurity(requestId, requestDto)
                    .subscribe().with(
                            // 1. Callback de ÉXITO (sin cambios)
                            response -> log.info(LoggerHelper.buildInfoPrivateResponse(
                                    requestId,
                                    String.format("Traza de seguridad registrada. Status: %s", response.getStatus())
                            )),

                            // 2. Callback de FALLO (con la nueva lógica detallada)
                            failure -> handleFailure(failure, requestId)
                    );

        } catch (Exception e) {
            // Este bloque captura errores síncronos (ej. en el mapeo)
            log.error(LoggerHelper.buildError(
                    requestId,
                    String.format("Error al preparar la llamada para registrar la traza de seguridad: %s", e.getMessage())
            ), e);
        }
    }

    /**
     * Centralizar y detallar el manejo de errores asíncronos.
     *
     * @param failure   La excepción ocurrida.
     * @param requestId El ID de la traza.
     */
    private void handleFailure(Throwable failure, String requestId) {
        if (failure instanceof WebApplicationException ex) {
            // Lógica para errores HTTP (4xx, 5xx) - Equivalente al primer catch
            var errorResponse = ex.getResponse();
            var status = errorResponse.getStatus();
            String errorDetails;

            if (errorResponse.getMediaType() != null && errorResponse.getMediaType().toString().contains("text/html")) {
                errorDetails = "Se recibio una respuesta HTML no esperada del servicio.";
                log.error(LoggerHelper.buildError(requestId,
                        String.format("Error HTTP %s del servicio de register security. %s", status, errorDetails)));
            } else {
                var errorBody = errorResponse.readEntity(String.class);
                errorDetails = errorBody.substring(0, Math.min(errorBody.length(), 1000));
                log.error(LoggerHelper.buildError(requestId,
                        String.format("Error HTTP no manejado del servicio de register security. Status: %s. Body: %s", status, errorDetails)));
            }
        } else {
            // Lógica para otros errores (red, timeout, etc.) - Equivalente al segundo catch
            log.error(LoggerHelper.buildError(
                    requestId,
                    String.format("Error de comunicacion con el servicio de register security: %s", failure.getMessage())
            ), failure);
        }
    }
}