package com.eactive.eai.rms.onl.manage.authserver.tokenissuance;

import com.eactive.eai.data.entity.onl.authserver.TokenIssuanceLog;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.eactive.eai.data.entity.onl.authserver.ClientEntity;
import com.eactive.eai.rms.common.base.OnlBaseService;
import com.eactive.eai.rms.data.entity.onl.authserver.ClientEntityService;
import com.eactive.eai.rms.data.entity.onl.authserver.ClientSearch;
import com.eactive.eai.rms.data.entity.onl.authserver.TokenIssuanceLogService;

import java.time.LocalDateTime;
import java.util.List;
import java.util.stream.Collectors;

@Service
@Transactional
public class TokenIssuanceStatusService extends OnlBaseService {

    private ClientEntityService clientEntityService;
    private TokenIssuanceLogService tokenIssuanceLogService;
    private TokenIssuanceLogUIMapper tokenIssuanceLogUIMapper;
    private TokenIssuanceStatusUIMapper tokenIssuanceStatusUIMapper;

    @Autowired
    public TokenIssuanceStatusService(ClientEntityService clientEntityService,
                                      TokenIssuanceLogService tokenIssuanceLogService,
                                      TokenIssuanceStatusUIMapper tokenIssuanceStatusUIMapper,
                                      TokenIssuanceLogUIMapper tokenIssuanceLogUIMapper) {
        this.clientEntityService = clientEntityService;
        this.tokenIssuanceLogService = tokenIssuanceLogService;
        this.tokenIssuanceStatusUIMapper = tokenIssuanceStatusUIMapper;
        this.tokenIssuanceLogUIMapper = tokenIssuanceLogUIMapper;
    }

    public Page<TokenIssuanceStatusUI> selectList(Pageable pageable, ClientSearch clientSearch) {
        Page<ClientEntity> page = clientEntityService.findAll(pageable, clientSearch);
        return page.map(this::createTokenIssuanceStatusUI);
    }

    private TokenIssuanceStatusUI createTokenIssuanceStatusUI(ClientEntity clientEntity) {
        TokenIssuanceStatusUI ui = tokenIssuanceStatusUIMapper.toVo(clientEntity);

        LocalDateTime startDateTime = LocalDateTime.now().minusHours(24);
        long requestCount = tokenIssuanceLogService.countRecentLogsForRestriction(clientEntity.getClientid(), startDateTime);
        long failedCount = tokenIssuanceLogService.countRecentFailedLogs(clientEntity.getClientid(), startDateTime);
        long successCount = requestCount - failedCount;

        ui.setRequestCount(requestCount);
        ui.setSuccessCount(successCount);
        ui.setFailedCount(failedCount);
        ui.setRestricted(isRestricted(clientEntity, requestCount));

        return ui;
    }

    private boolean isRestricted(ClientEntity clientEntity, long requestCount) {
        long dailyTokenLimit = (long) clientEntity.getDailytokenlimit();
        return dailyTokenLimit > 0 && requestCount >= dailyTokenLimit;
    }

    public TokenIssuanceStatusDetailUI selectDetail(String clientId) {
        TokenIssuanceStatusDetailUI detailUI = new TokenIssuanceStatusDetailUI();

        ClientEntity clientEntity = clientEntityService.getById(clientId);
        TokenIssuanceStatusUI statusUI = createTokenIssuanceStatusUI(clientEntity);
        detailUI.setStatusUI(statusUI);

        LocalDateTime startDateTime = LocalDateTime.now().minusHours(24);
        List<TokenIssuanceLog> logs = tokenIssuanceLogService.findRecentLogsForRestriction(clientId, startDateTime);
        List<TokenIssuanceLogUI> logUIs = logs.stream()
                .map(tokenIssuanceLogUIMapper::toVo)
                .collect(Collectors.toList());
        detailUI.setLogs(logUIs);
        return detailUI;
    }

    public void exemptRestrictionForClient(String clientId) {
        LocalDateTime startDateTime = LocalDateTime.now().minusHours(24);
        tokenIssuanceLogService.exemptRestrictionForClient(clientId, startDateTime);
    }
}