package ervu_business_metrics.service;

import java.util.List;
import java.util.UUID;
import java.util.concurrent.TimeUnit;

import ervu_business_metrics.config.KafkaEnabledCondition;
import ervu_business_metrics.dao.ActiveSessionDao;
import ervu_business_metrics.model.sso.UserSessionInfo;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Conditional;
import org.springframework.kafka.core.KafkaTemplate;
import org.springframework.stereotype.Component;

/**
 * @author Adel Kalimullin
 */
@Component
@Conditional(KafkaEnabledCondition.class)
public class SessionService {
  private final static Logger LOGGER = LoggerFactory.getLogger(SessionService.class);
  private final KafkaTemplate<String, String> kafkaTemplate;
  private final SessionResponseHolder holder;
  private final ActiveSessionDao activeSessionDao;
  @Value("${session.fetch.timeout:15}")
  private int timeout;
  @Value("${kafka.sso.sessions.state.receive}")
  private String sessionTopic;

  public SessionService(
      KafkaTemplate<String, String> kafkaTemplate,
      SessionResponseHolder holder, ActiveSessionDao activeSessionDao) {
    this.kafkaTemplate = kafkaTemplate;
    this.holder = holder;
    this.activeSessionDao = activeSessionDao;
  }

  public void syncSessions() {
    activeSessionDao.clear();

    List<UserSessionInfo> sessions = fetchSessions();
    if (!sessions.isEmpty()) {
      activeSessionDao.saveAll(sessions);
      LOGGER.info("Синхронизировано {} сессий", sessions.size());
    }
    else {
      LOGGER.info("Нет сессий для синхронизации");
    }
  }

  private List<UserSessionInfo> fetchSessions() {
    String requestKey = UUID.randomUUID().toString();
    LOGGER.info("Отправка запроса с requestKey = {}", requestKey);
    kafkaTemplate.send(sessionTopic, requestKey, "{}");

    try {
      return holder.awaitSessions(requestKey, timeout, TimeUnit.SECONDS);
    }
    catch (Exception e) {
      LOGGER.error("Ошибка при получении сессий по ключу {}", requestKey, e);
      return List.of();
    }
    finally {
      holder.remove(requestKey);
    }
  }
}
