package com.qmth.paper.library.business.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.qmth.paper.library.business.entity.PaperScanTask;
import com.qmth.paper.library.business.service.BusinessCacheService;
import com.qmth.paper.library.business.service.PaperLibraryService;
import com.qmth.paper.library.business.service.PaperScanTaskService;
import com.qmth.paper.library.common.bean.dto.SchoolDto;
import com.qmth.paper.library.common.contant.SystemConstant;
import com.qmth.paper.library.common.enums.ExceptionResultEnum;
import com.qmth.paper.library.common.lock.LockService;
import com.qmth.paper.library.common.lock.LockType;
import com.qmth.paper.library.common.service.BasicSchoolService;
import com.qmth.paper.library.common.service.SysUserService;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.StringJoiner;

@Service
public class BusinessCacheServiceImpl implements BusinessCacheService {

    Map<String, Integer> scanTaskSequenceMap = new HashMap<>();
    Map<Long, Integer> scanTaskCodeMap = new HashMap<>();
    @Resource
    private PaperScanTaskService paperScanTaskService;
    @Resource
    private PaperLibraryService paperLibraryService;
    @Resource
    private BasicSchoolService basicSchoolService;
    @Resource
    private LockService lockService;

    @Override
    @Cacheable(value = SystemConstant.CACHE_NAME, key = "'paperScanTask' + #scanTaskId")
    public PaperScanTask getPaperScanTask(Long scanTaskId) {
        return paperScanTaskService.getById(scanTaskId);
    }

    @Override
    public int getSequence(Long paperScanTaskId, String studentCode) {
        String key = getKey(String.valueOf(paperScanTaskId), studentCode);
        try {
            lockService.waitlock(LockType.GET_SEQUENCE, key);
            if (!scanTaskSequenceMap.containsKey(key)) {
                scanTaskSequenceMap.put(key, 1);
                return 1;
            }
            Integer integer = scanTaskSequenceMap.get(key);
            int value = integer + 1;
            scanTaskSequenceMap.put(key, value);
            return value;
        } catch (Exception e) {
            throw ExceptionResultEnum.ERROR.exception("获取自增数失败：" + e.getMessage());
        } finally {
            lockService.unlock(LockType.GET_SEQUENCE, key);
        }
    }

    private String getKey(String... strings) {
        StringJoiner sj = new StringJoiner("-");
        for (String string : strings) {
            sj.add(string);
        }
        return sj.toString();
    }

    @Override
    public void initCacheData() {
        QueryWrapper<PaperScanTask> queryWrapper = new QueryWrapper<>();
        List<PaperScanTask> paperScanTaskList = paperScanTaskService.list(queryWrapper);
        for (PaperScanTask paperScanTask : paperScanTaskList) {
            String paperScanTaskIdStr = String.valueOf(paperScanTask.getId());
            List<Map> mapList = paperLibraryService.listMaxSequenceByPaperScanTaskId(paperScanTask.getId());
            for (Map map : mapList) {
                String studentCode = String.valueOf(map.get("studentCode"));
                int value = map.get("maxSequence") == null ? 0 : Integer.valueOf(String.valueOf(map.get("maxSequence")));
                scanTaskSequenceMap.put(getKey(paperScanTaskIdStr, studentCode), value);
            }
        }

        List<SchoolDto> basicSchoolList = basicSchoolService.listSchool();
        for (SchoolDto schoolDto : basicSchoolList) {
            Long schoolId = Long.valueOf(schoolDto.getId());
            // 扫描任务编号序号
            QueryWrapper<PaperScanTask> scanTaskQueryWrapper = new QueryWrapper<>();
            scanTaskQueryWrapper.lambda().eq(PaperScanTask::getSchoolId, schoolId)
                    .likeRight(PaperScanTask::getScanTaskCode, SystemConstant.SCAN_TASK_CODE_PREFIX)
                    .orderByDesc(PaperScanTask::getScanTaskCode);
            List<PaperScanTask> scanTaskList = paperScanTaskService.list(scanTaskQueryWrapper);
            if (!CollectionUtils.isEmpty(scanTaskList)) {
                String scanTaskCode = scanTaskList.get(0).getScanTaskCode();
                String codeTemp = scanTaskCode.substring(SystemConstant.SCAN_TASK_CODE_PREFIX.length());
                int codeInt = Integer.parseInt(codeTemp);
                scanTaskCodeMap.put(schoolId, codeInt);
            }
        }
    }

    @Override
    public int getScanTaskCodeSequence(Long schoolId) {
        try {
            lockService.waitlock(LockType.SCAN_TASK_SEQUENCE, schoolId);
            if (!scanTaskCodeMap.containsKey(schoolId)) {
                scanTaskCodeMap.put(schoolId, 1);
                return 1;
            }
            Integer integer = scanTaskCodeMap.get(schoolId);
            int value = integer + 1;
            scanTaskCodeMap.put(schoolId, value);
            return value;
        } catch (Exception e) {
            throw ExceptionResultEnum.ERROR.exception("获取扫描任务编号自增数失败：" + e.getMessage());
        } finally {
            lockService.unlock(LockType.SCAN_TASK_SEQUENCE, schoolId);
        }
    }
}
