package ru.ulstu.user.service;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Sort;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import ru.ulstu.core.model.response.PageableItems;
import ru.ulstu.core.jpa.OffsetablePageRequest;
import ru.ulstu.user.error.UserNotFoundException;
import ru.ulstu.user.model.User;
import ru.ulstu.user.model.UserSession;
import ru.ulstu.user.model.UserSessionListDto;
import ru.ulstu.user.repository.UserSessionRepository;

import static ru.ulstu.core.util.StreamApiUtils.convert;

@Service
@Transactional
public class UserSessionService {
    private final Logger log = LoggerFactory.getLogger(UserSessionService.class);
    private final UserSessionRepository userSessionRepository;
    private final UserService userService;

    public UserSessionService(UserSessionRepository userSessionRepository, UserService userService) {
        this.userSessionRepository = userSessionRepository;
        this.userService = userService;
    }

    @Transactional(readOnly = true)
    public PageableItems<UserSessionListDto> getSessions(int offset, int count) {
        final Page<UserSession> page = userSessionRepository.findAll(
                new OffsetablePageRequest(offset, count, new Sort(Sort.Direction.DESC, "loginTime")));
        return new PageableItems<>(page.getTotalElements(),
                convert(page.getContent(), UserSessionListDto::new));
    }

    public void createUserSession(String sessionId, String login, String ipAddress, String host) {
        final User user = userService.getUserByLogin(login);
        if (user == null) {
            throw new UserNotFoundException(login);
        }
        userSessionRepository.save(new UserSession(sessionId, ipAddress, host, user));
        log.debug("User session {} created for user {}@{} ({})", sessionId, login, ipAddress, host);
    }

    public void closeUserSession(String sessionId) {
        final UserSession userSession = userSessionRepository.findOneBySessionId(sessionId);
        if (userSession == null) {
            throw new IllegalArgumentException(String.format("User session %s not found", sessionId));
        }
        userSession.close();
        userSessionRepository.save(userSession);
        log.debug("User session {} closed", sessionId);
    }
}
