package com.ruoyi.web.service;

import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
import com.ruoyi.common.utils.bean.BeanUtils;
import com.ruoyi.system.domain.SysConfig;
import com.ruoyi.system.service.ISysConfigService;
import com.ruoyi.syzy.domain.BBusiWishScoreGroups;
import com.ruoyi.syzy.domain.BBusiWishUniversitySubmitMarjorsUpdate;
import com.ruoyi.syzy.mapper.BBusiWishScoreGroupsMapper;
import com.ruoyi.syzy.mapper.BBusiWishUniversitySubmitMarjorsUpdateMapper;
import com.ruoyi.voluntary.mapper.PdMarjorMatchDataMapper;
import com.ruoyi.web.domain.ChangesDto;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import java.util.*;

@Service
@Slf4j
public class BackChangesService {
    private final BBusiWishScoreGroupsMapper busiWishScoreGroupsMapper;
    private final BBusiWishUniversitySubmitMarjorsUpdateMapper busiWishUniversitySubmitMarjorsUpdateMapper;
    private final PdMarjorMatchDataMapper pdMarjorMatchDataMapper;

    private final ISysConfigService sysConfigService;

    public BackChangesService(BBusiWishScoreGroupsMapper busiWishScoreGroupsMapper, BBusiWishUniversitySubmitMarjorsUpdateMapper busiWishUniversitySubmitMarjorsUpdateMapper, PdMarjorMatchDataMapper pdMarjorMatchDataMapper, ISysConfigService sysConfigService) {
        this.busiWishScoreGroupsMapper = busiWishScoreGroupsMapper;
        this.busiWishUniversitySubmitMarjorsUpdateMapper = busiWishUniversitySubmitMarjorsUpdateMapper;
        this.pdMarjorMatchDataMapper = pdMarjorMatchDataMapper;
        this.sysConfigService = sysConfigService;
    }

    public void deleteUpdateVersion(String version, String location) {
        busiWishUniversitySubmitMarjorsUpdateMapper.deleteUpdateVersion(version, location);
    }

    public String postScoreRank(ChangesDto.PageData<ChangesDto.ScoreRank> pageData) {
        List<BBusiWishUniversitySubmitMarjorsUpdate> records = Lists.newArrayList();
        for (ChangesDto.ScoreRank rank : pageData.getRows()) {
            BBusiWishUniversitySubmitMarjorsUpdate u = new BBusiWishUniversitySubmitMarjorsUpdate();
            BeanUtils.copyProperties(rank, u);
            u.setUdid(rank.getUdid2());
            records.add(u);
        }
        busiWishUniversitySubmitMarjorsUpdateMapper.insertUpdateBatch(records);
        if(pageData.getTotalPage() == pageData.getPageNum()) {
            SysConfig config = new SysConfig();
            config.setConfigKey("ChangesUpdateVersion");
            List<SysConfig> configList = sysConfigService.selectConfigList(config);
            config.setConfigValue(records.get(0).getVersion());
            if (configList.size() == 0) {
                config.setConfigType("Y");
                config.setConfigName("变更保存版本");
                sysConfigService.insertConfig(config);
            } else {
                config.setConfigId(configList.get(0).getConfigId());
                sysConfigService.updateConfig(config);
            }
            return "completed";
        }
        return "continue";
    }

    public void processUpdateStats(Boolean newGaoKao, Integer planYear, String location, Collection<Long> planIds, Collection<Integer> collegeIdList) {
        // 基于Plan更新匹配关系表
        List<String> locations = Lists.newArrayList(location);
        if (locations.size() > 0) {
            log.info("insertCollegeStats {}", locations);
            busiWishUniversitySubmitMarjorsUpdateMapper.insertCollegeStats(newGaoKao, planYear, locations, collegeIdList);
            log.info("updateCollegeStats {}", locations);
            busiWishUniversitySubmitMarjorsUpdateMapper.updateCollegeStats(planYear, locations, collegeIdList);
            log.info("insertStats {}", locations);
            busiWishUniversitySubmitMarjorsUpdateMapper.insertStats(planYear, locations, planIds);
            log.info("updateStats {}", locations);
            busiWishUniversitySubmitMarjorsUpdateMapper.updateStats(planYear, locations, planIds);
        }
    }

    public void processScoreRankChange(String version, Integer planYear, List<String> locations) {
        SysConfig config = new SysConfig();
        config.setConfigKey("ChangesLastVersion");
        List<SysConfig> configList = sysConfigService.selectConfigList(config);
        BBusiWishUniversitySubmitMarjorsUpdate cond = new BBusiWishUniversitySubmitMarjorsUpdate();
        cond.setVersion(version);
        Integer pageSize = 10000, offset = 0, updateSize = 500;
        List<BBusiWishUniversitySubmitMarjorsUpdate> batchList;
        List<BBusiWishUniversitySubmitMarjorsUpdate> updateList = Lists.newArrayList();
        Map<String, BBusiWishScoreGroups[]> locYearModeScoreGroupMap = Maps.newHashMap();
        Set<String> locationSet = Sets.newHashSet();
        do {
            batchList = busiWishUniversitySubmitMarjorsUpdateMapper.selectUpdateLocationList(version, locations, offset, pageSize);
            log.info("updateCorrRankBatch {} {} {}", version,offset, batchList.size());
            for (BBusiWishUniversitySubmitMarjorsUpdate u : batchList) {
                locationSet.add(u.getLocation());
                String[] datas = u.getUdid().split("_");
                u.setCorrRank(getScoreRank(getSortScoreGroupList(locYearModeScoreGroupMap, u.getLocation(), Integer.parseInt(datas[0]), datas[1]), u.getMinScore()));
                updateList.add(u);
                if (updateList.size() == updateSize) {
                    busiWishUniversitySubmitMarjorsUpdateMapper.updateCorrRankBatch(updateList);
                    updateList.clear();
                }
            }
            offset += pageSize;
        } while (batchList.size() == pageSize);
        if (updateList.size() > 0) {
            busiWishUniversitySubmitMarjorsUpdateMapper.updateCorrRankBatch(batchList);
        }
        log.info("updateSubmitMarjors {}", version);
        busiWishUniversitySubmitMarjorsUpdateMapper.updateSubmitMarjors(version, locationSet);
        for(String location : locationSet) {
            Boolean newGaokao = pdMarjorMatchDataMapper.selectNewGaokao(location, planYear) > 0;
            processUpdateStats(newGaokao, planYear, location, null, null);
        }

        config.setConfigValue(version);
        if (configList.size() == 0) {
            config.setConfigType("Y");
            config.setConfigName("变更最新版本");
            sysConfigService.insertConfig(config);
        } else {
            config.setConfigId(configList.get(0).getConfigId());
            sysConfigService.updateConfig(config);
        }
    }

    private BBusiWishScoreGroups[] getSortScoreGroupList(Map<String, BBusiWishScoreGroups[]> locYearModeScoreGroupMap, String loc, Integer year, String mode) {
        String key = loc + year + mode;
        BBusiWishScoreGroups[] list = locYearModeScoreGroupMap.get(key);
        if (null != list) {
            return list;
        }
        BBusiWishScoreGroups cond = new BBusiWishScoreGroups();
        cond.setLocation(loc);
        cond.setYear(year);
        cond.setMode(mode);
        List<BBusiWishScoreGroups> scoreGroupList = busiWishScoreGroupsMapper.selectBBusiWishScoreGroupsList(cond);
        Collections.sort(scoreGroupList, new Comparator<BBusiWishScoreGroups>() {
            @Override
            public int compare(BBusiWishScoreGroups o1, BBusiWishScoreGroups o2) {
                int iRet;
                if((iRet = o1.getScore().compareTo(o2.getScore())) != 0)
                    return iRet;
                return o1.getId().compareTo(o2.getId());
            }
        });
        list = scoreGroupList.toArray(new BBusiWishScoreGroups[scoreGroupList.size()]);
        locYearModeScoreGroupMap.put(key, list);
        return list;
    }

    private Integer getScoreRank(BBusiWishScoreGroups[] sortScoreGroups, Integer score) {
        if (null == sortScoreGroups || sortScoreGroups.length == 0)
            return 0;
        int l = 0, r = sortScoreGroups.length - 1;
        while (l <= r) {
            int mid = l + (r - l) / 2;
            BBusiWishScoreGroups sg = sortScoreGroups[mid];
            if (score >= sg.getScore() && score <= sg.getMaxScore()) {
                return sg.getLowestRank();
            } else if (sg.getScore() < score) {
                l = mid + 1;
            } else {
                r = mid - 1;
            }
        }
        return 0;
    }

    public void processStats(Integer planYear, List<String> locations) {
        for(String location : locations) {
            Boolean newGaokao = pdMarjorMatchDataMapper.selectNewGaokao(location, planYear) > 0;
            processUpdateStats(newGaokao, planYear, location, null, null);
        }
    }
}
