package cn.lihongjie.coal.submitToken.service;

import cn.lihongjie.coal.base.dto.CommonQuery;
import cn.lihongjie.coal.base.dto.IdRequest;
import cn.lihongjie.coal.base.service.BaseService;
import cn.lihongjie.coal.exception.BizException;
import cn.lihongjie.coal.submitToken.dto.CreateSubmitTokenDto;
import cn.lihongjie.coal.submitToken.dto.SubmitTokenDto;
import cn.lihongjie.coal.submitToken.dto.UpdateSubmitTokenDto;
import cn.lihongjie.coal.submitToken.entity.SubmitTokenEntity;
import cn.lihongjie.coal.submitToken.mapper.SubmitTokenMapper;
import cn.lihongjie.coal.submitToken.repository.SubmitTokenRepository;

import lombok.extern.slf4j.Slf4j;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.convert.ConversionService;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Sort;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;

@Service
@Slf4j
@Transactional
public class SubmitTokenService extends BaseService<SubmitTokenEntity, SubmitTokenRepository> {
    @Autowired private SubmitTokenRepository repository;

    @Autowired private SubmitTokenMapper mapper;

    @Autowired private ConversionService conversionService;

    public SubmitTokenDto create(CreateSubmitTokenDto request) {
        SubmitTokenEntity entity = mapper.toEntity(request);

        this.repository.save(entity);
        return getById(entity.getId());
    }

    public SubmitTokenDto update(UpdateSubmitTokenDto request) {
        SubmitTokenEntity entity = this.repository.get(request.getId());
        this.mapper.updateEntity(entity, request);

        this.repository.save(entity);

        return getById(entity.getId());
    }

    public void delete(IdRequest request) {
        this.repository.deleteAllById(request.getIds());
    }

    public SubmitTokenDto getById(String id) {
        SubmitTokenEntity entity = repository.get(id);

        return mapper.toDto(entity);
    }

    public Page<SubmitTokenDto> list(CommonQuery query) {
        Page<SubmitTokenEntity> page =
                repository.findAll(
                        query.specification(conversionService),
                        PageRequest.of(
                                query.getPageNo(),
                                query.getPageSize(),
                                Sort.by(query.getOrders())));

        return page.map(this.mapper::toDto);
    }

    public String newToken() {
        SubmitTokenEntity entity = new SubmitTokenEntity();
        entity.setStatus(0);

        this.repository.save(entity);
        return entity.getId();
    }

    public void acquireToken(String token) {

        SubmitTokenEntity entity =
                this.repository
                        .findByIdLocked(token)
                        .orElseThrow(() -> new BizException("token不存在: " + token));

        if (entity.getStatus() != 0) {
            throw new BizException("token已过期: " + token);
        }

        entity.setStatus(1);

        this.repository.save(entity);
    }

    public void releaseToken(String token) {
        SubmitTokenEntity entity =
                this.repository
                        .findByIdLocked(token)
                        .orElseThrow(() -> new BizException("token不存在: " + token));

        if (entity.getStatus() != 1) {
            throw new BizException("token已过期: " + token);
        }

        this.repository.delete(entity);
    }

    /** 删除无效的token */
    @Scheduled(cron = "0 0/1 * * * ?")
    public void expireAll() {

        Integer count = this.repository.expireAll(LocalDateTime.now().minusMinutes(30));

        log.info("删除无效token: {}", count);

    }
}
