package com.banesco.common.infraestructure.service;

import com.banesco.common.domain.model.BackResponse;
import com.banesco.common.domain.dto.bian.response.StatusResponse;
import com.banesco.common.infraestructure.repository.MessageRepository;

import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;

public class MessageService {

    private static final Logger logger = Logger.getLogger(MessageService.class.getName());
    private final MessageRepository messageRepository;

    private final String CONFLICT = "CONFLICT";
    private final BackResponse DEFAULT_ERROR = new BackResponse(
            CONFLICT,
            409,
            CONFLICT,
            CONFLICT
    );

    private boolean messagesInsideProperties = false;

    /**
     * Constructor de MessageService.
     *
     * @param messageRepository El repositorio de mensajes que se utilizará para
     *                          cargar y obtener mensajes de error.
     */
    public MessageService(MessageRepository messageRepository) {
        this.messageRepository = messageRepository;
    }


    /**
     * Carga mensajes desde una cadena JSON en el repositorio de mensajes.
     *
     * @param responseFileName El nombre del archivo de respuesta asociado con
     *                         los mensajes.
     * @param jsonResponse     La cadena JSON que contiene los mensajes.
     */
    public void loadMessageFromJson(String responseFileName, String jsonResponse) {
        messagesInsideProperties = true;
        try {
            messageRepository.loadMessagesFromString(responseFileName, jsonResponse);
        } catch (Exception ex) {
            logger.log(Level.SEVERE, "Error loading messages from JSON: %s".formatted(ex.getMessage()), ex);
        }
    }

    /**
     * Obtiene una respuesta de estado (BackResponse) basada en el código de
     * backend y el nombre del archivo de respuesta.
     *
     * @param responseFileName El nombre del archivo de respuesta.
     * @param backendCode      El código de backend para buscar la respuesta.
     * @return La respuesta de estado (BackResponse) correspondiente al código
     * de backend, la respuesta por defecto si no se encuentra, o null si hay un
     * error.
     */
    public BackResponse geStatusResponse(String responseFileName, String backendCode) {
        logger.log(Level.INFO, "Finding backendCode: \"%s\" in File: \"%s\"".formatted(backendCode, responseFileName));
        Map<String, BackResponse> errors = messageRepository.getErrorMap(responseFileName, messagesInsideProperties);

        if (errors == null || errors.isEmpty()) {
            logger.log(Level.WARNING, "Error map for %s is empty or null.".formatted(responseFileName));
            return DEFAULT_ERROR;
        }

        BackResponse backResponse = null;
        try {
            backResponse = errors.get(backendCode);
            if (backResponse == null) {
                backResponse = errors.get("default");
            }
        } catch (Exception e) {
            logger.log(Level.WARNING, "Error code: %s not found in %s. Using default.".formatted(backendCode, responseFileName), e);
            try {
                backResponse = errors.get("default");
            } catch (Exception e2) {
                logger.log(Level.SEVERE, "Error getting default code.", e2);
            }
        }

        if (backResponse == null) {
            logger.log(Level.WARNING, "Error code: %s and default not found in %s.".formatted(backendCode, responseFileName));
            return DEFAULT_ERROR;
        }
        return backResponse;
    }

    public StatusResponse backToStatusResponse(String traceId, BackResponse backResponse, String target) {
        return new StatusResponse(
                backResponse.getHttpCode()>=200 && backResponse.getHttpCode()<300?"ok":"error",
                backResponse.getStatusCode(),
                target == null ? backResponse.getDescription() :
                        backResponse.getDescription().formatted(target),
                traceId

        );
    }
}
