package org.jeecg.modules.stm.common.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import org.apache.commons.lang3.StringUtils;
import org.jeecg.modules.stm.act.check.entity.StCaMainCheck;
import org.jeecg.modules.stm.act.check.service.IStCaMainCheckService;
import org.jeecg.modules.stm.act.collection.entity.StCaMainCollection;
import org.jeecg.modules.stm.act.collection.service.IStCaMainCollectionService;
import org.jeecg.modules.stm.act.main.entity.StCaMain;
import org.jeecg.modules.stm.act.main.entity.StCaMainLable;
import org.jeecg.modules.stm.act.main.service.IStCaMainLableService;
import org.jeecg.modules.stm.act.main.service.IStCaMainService;
import org.jeecg.modules.stm.act.metric.entity.StCaMainMetric;
import org.jeecg.modules.stm.act.metric.entity.StMetric;
import org.jeecg.modules.stm.act.metric.service.IStCaMainMetricService;
import org.jeecg.modules.stm.act.metric.service.IStMetricService;
import org.jeecg.modules.stm.base.classify.entity.StClassify;
import org.jeecg.modules.stm.base.classify.service.IStClassifyService;
import org.jeecg.modules.stm.base.domain.entity.StDomain;
import org.jeecg.modules.stm.base.domain.service.IStDomainService;
import org.jeecg.modules.stm.base.lable.entity.StLable;
import org.jeecg.modules.stm.base.lable.service.IStLableService;
import org.jeecg.modules.stm.best.cases.entity.StBestCase;
import org.jeecg.modules.stm.best.cases.service.IStBestCaseService;
import org.jeecg.modules.stm.best.practices.entity.StBestPractices;
import org.jeecg.modules.stm.best.practices.service.IStBestPracticesService;
import org.jeecg.modules.stm.common.mapper.StCommonMapper;
import org.jeecg.modules.stm.common.service.IStCommonService;
import org.jeecg.modules.stm.common.vo.DutyVo;
import org.jeecg.modules.stm.common.vo.QueryVo;
import org.jeecg.modules.stm.common.vo.StMenuVo;
import org.jeecg.modules.stm.compliane.info.entity.StComplianeInfo;
import org.jeecg.modules.stm.compliane.info.service.IStComplianeInfoService;
import org.jeecg.modules.stm.compliane.item.entity.StComplianeItem;
import org.jeecg.modules.stm.compliane.item.entity.StComplianeRiskRef;
import org.jeecg.modules.stm.compliane.item.service.IStComplianeItemService;
import org.jeecg.modules.stm.compliane.item.service.IStComplianeRiskRefService;
import org.jeecg.modules.stm.inner.control.entity.StInnerControl;
import org.jeecg.modules.stm.inner.control.service.IStInnerControlService;
import org.jeecg.modules.stm.inner.order.entity.StInnerControlOrder;
import org.jeecg.modules.stm.inner.order.service.IStInnerControlOrderService;
import org.jeecg.modules.stm.plan.approve.entity.StPlanApprove;
import org.jeecg.modules.stm.plan.approve.service.IStPlanApproveService;
import org.jeecg.modules.stm.plan.main.constant.PlanFlag;
import org.jeecg.modules.stm.plan.main.entity.StPlanMan;
import org.jeecg.modules.stm.plan.main.service.IStPlanManService;
import org.jeecg.modules.stm.problem.entity.StProblem;
import org.jeecg.modules.stm.problem.service.IStProblemService;
import org.jeecg.modules.stm.risk.event.entity.StRiskEvent;
import org.jeecg.modules.stm.risk.event.service.IStRiskEventService;
import org.jeecg.modules.stm.risk.scenario.entity.StRiskScenario;
import org.jeecg.modules.stm.risk.scenario.service.IStRiskScenarioService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;


import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

/**
 * @Author: yzh
 * @Date 2023/4/2 18:26
 * @Description:
 */
@Service
public class IStCommonServiceImpl implements IStCommonService {
    @Autowired
    private IStCaMainService iStCaMainService;

    @Autowired
    private IStMetricService iStMetricService;

    @Autowired
    private IStCaMainCheckService iStCaMainCheckService;

    @Autowired
    private IStCaMainCollectionService iStCaMainCollectionService;

    @Autowired
    private IStComplianeInfoService iStComplianeInfoService;

    @Autowired
    private IStInnerControlService iStInnerControlService;

    @Autowired
    private IStInnerControlOrderService iStInnerControlOrderService;

    @Autowired
    private IStRiskScenarioService iStRiskScenarioService;

    @Autowired
    private IStRiskEventService iStRiskEventService;

    @Autowired
    private IStBestPracticesService iStBestPracticesService;

    @Autowired
    private IStBestCaseService iStBestCaseService;

    @Autowired
    private IStProblemService iStProblemService;

    @Autowired
    private IStLableService iStLableService;

    @Autowired
    private IStDomainService iStDomainService;

    @Autowired
    private IStClassifyService iStClassifyService;

    @Autowired
    private IStCaMainMetricService iStCaMainMetricService;

    @Autowired
    private IStComplianeItemService iStComplianeItemService;

    @Autowired
    private IStCaMainLableService iStCaMainLableService;

    @Autowired
    private IStComplianeRiskRefService iStComplianeRiskRefService;

    @Autowired
    private StCommonMapper stCommonMapper;

    @Autowired
    private IStPlanManService iStPlanManService;

    @Autowired
    private IStPlanApproveService iStPlanApproveService;


    private void stCaMain(Map<String, StMenuVo> map){
        long count = iStCaMainService.count();
        StMenuVo stMenuVo = new StMenuVo();
        stMenuVo.setCount(count);
        StCaMain entity = iStCaMainService.getOne(new QueryWrapper<StCaMain>().orderByDesc("UPDATED_TIME").last("limit 1"));
        stMenuVo.setUpdateDate(entity!=null?entity.getUpdatedTime():new Date());
        map.put("stCaMain",stMenuVo);
    }
    private void stMetric(Map<String, StMenuVo> map){
        long count = iStMetricService.count();
        StMenuVo stMenuVo = new StMenuVo();
        stMenuVo.setCount(count);
        StMetric entity = iStMetricService.getOne(new QueryWrapper<StMetric>().orderByDesc("UPDATED_TIME").last("limit 1"));
        stMenuVo.setUpdateDate(entity!=null?entity.getUpdatedTime():new Date());
        map.put("stMetric",stMenuVo);
    }

    private void stCheck(Map<String, StMenuVo> map){
        long count = iStCaMainCheckService.count();
        StMenuVo stMenuVo = new StMenuVo();
        stMenuVo.setCount(count);
        StCaMainCheck entity = iStCaMainCheckService.getOne(new QueryWrapper<StCaMainCheck>().orderByDesc("UPDATED_TIME").last("limit 1"));
        stMenuVo.setUpdateDate(entity!=null?entity.getUpdatedTime():new Date());
        map.put("stCheck",stMenuVo);
    }

    private void stCollection(Map<String, StMenuVo> map){
        long count = iStCaMainCollectionService.count();
        StMenuVo stMenuVo = new StMenuVo();
        stMenuVo.setCount(count);
        StCaMainCollection entity = iStCaMainCollectionService.getOne(new QueryWrapper<StCaMainCollection>().orderByDesc("UPDATED_TIME").last("limit 1"));
        stMenuVo.setUpdateDate(entity!=null?entity.getUpdatedTime():new Date());
        map.put("stCollection",stMenuVo);
    }

    private void stCompliane(Map<String, StMenuVo> map){
        long count = iStComplianeInfoService.count();
        StMenuVo stMenuVo = new StMenuVo();
        stMenuVo.setCount(count);
        StComplianeInfo entity = iStComplianeInfoService.getOne(new QueryWrapper<StComplianeInfo>().orderByDesc("UPDATED_TIME").last("limit 1"));
        stMenuVo.setUpdateDate(entity!=null?entity.getUpdatedTime():new Date());
        map.put("stCompliane",stMenuVo);
        for(int i=1;i<6;i++) {
            long count1 = iStComplianeInfoService.
                    count(new QueryWrapper<StComplianeInfo>().eq("COMPLIANE_CLASS", ""+i));
            StMenuVo stMenuVoTmp = new StMenuVo();
            stMenuVoTmp.setCount(count1);
            StComplianeInfo entityTmp = iStComplianeInfoService.
                    getOne(new QueryWrapper<StComplianeInfo>()
                            .eq("COMPLIANE_CLASS", ""+i)
                            .orderByDesc("UPDATED_TIME").last("limit 1"));
            stMenuVoTmp.setUpdateDate(entityTmp!=null?entityTmp.getUpdatedTime():new Date());
            map.put("stCompliane"+i, stMenuVoTmp);
        }
    }

    private void stInnerControl(Map<String, StMenuVo> map){
        long count = iStInnerControlService.count();
        StMenuVo stMenuVo = new StMenuVo();
        stMenuVo.setCount(count);
        StInnerControl entity = iStInnerControlService.getOne(new QueryWrapper<StInnerControl>().orderByDesc("UPDATED_TIME").last("limit 1"));
        stMenuVo.setUpdateDate(entity!=null?entity.getUpdatedTime():new Date());
        map.put("stInnerControl",stMenuVo);
    }

    private void stInnerControlOrder(Map<String, StMenuVo> map){
        long count = iStInnerControlOrderService.count();
        StMenuVo stMenuVo = new StMenuVo();
        stMenuVo.setCount(count);
        StInnerControlOrder entity = iStInnerControlOrderService.getOne(new QueryWrapper<StInnerControlOrder>().orderByDesc("UPDATED_TIME").last("limit 1"));
        stMenuVo.setUpdateDate(entity!=null?entity.getUpdatedTime():new Date());
        map.put("stInnerControlOrder",stMenuVo);
    }

    private void stScenario(Map<String, StMenuVo> map){
        long count = iStRiskScenarioService.count();
        StMenuVo stMenuVo = new StMenuVo();
        stMenuVo.setCount(count);
        StRiskScenario entity = iStRiskScenarioService.getOne(new QueryWrapper<StRiskScenario>().orderByDesc("UPDATED_TIME").last("limit 1"));
        stMenuVo.setUpdateDate(entity!=null?entity.getUpdatedTime():new Date());
        map.put("stScenario",stMenuVo);
    }

    private void stEvent(Map<String, StMenuVo> map){
        long count = iStRiskEventService.count();
        StMenuVo stMenuVo = new StMenuVo();
        stMenuVo.setCount(count);
        StRiskEvent entity = iStRiskEventService.getOne(new QueryWrapper<StRiskEvent>().orderByDesc("UPDATED_TIME").last("limit 1"));
        stMenuVo.setUpdateDate(entity!=null?entity.getUpdatedTime():new Date());
        map.put("stEvent",stMenuVo);
    }

    private void stBestPractices(Map<String, StMenuVo> map){
        long count = iStBestPracticesService.count();
        StMenuVo stMenuVo = new StMenuVo();
        stMenuVo.setCount(count);
        StBestPractices entity = iStBestPracticesService.getOne(new QueryWrapper<StBestPractices>().orderByDesc("UPDATED_TIME").last("limit 1"));
        stMenuVo.setUpdateDate(entity!=null?entity.getUpdatedTime():new Date());
        map.put("stBestPractices",stMenuVo);
    }

    private void stBestCase(Map<String, StMenuVo> map){
        long count = iStBestCaseService.count();
        StMenuVo stMenuVo = new StMenuVo();
        stMenuVo.setCount(count);
        StBestCase entity = iStBestCaseService.getOne(new QueryWrapper<StBestCase>().orderByDesc("UPDATED_TIME").last("limit 1"));
        stMenuVo.setUpdateDate(entity!=null?entity.getUpdatedTime():new Date());
        map.put("stBestCase",stMenuVo);
    }

    private void stProblem(Map<String, StMenuVo> map){
        long count = iStProblemService.count();
        StMenuVo stMenuVo = new StMenuVo();
        stMenuVo.setCount(count);
        StProblem entity = iStProblemService.getOne(new QueryWrapper<StProblem>().orderByDesc("UPDATED_TIME").last("limit 1"));
        stMenuVo.setUpdateDate(entity!=null?entity.getUpdatedTime():new Date());
        map.put("stProblem",stMenuVo);
    }

    private void stLable(Map<String, StMenuVo> map){
        long count = iStLableService.count();
        StMenuVo stMenuVo = new StMenuVo();
        stMenuVo.setCount(count);
        StLable entity = iStLableService.getOne(new QueryWrapper<StLable>().orderByDesc("UPDATED_TIME").last("limit 1"));
        stMenuVo.setUpdateDate(entity!=null?entity.getUpdatedTime():new Date());
        map.put("stLable",stMenuVo);
    }

    private void stDomain(Map<String, StMenuVo> map){
        long count = iStDomainService.count();
        StMenuVo stMenuVo = new StMenuVo();
        stMenuVo.setCount(count);
        StDomain entity = iStDomainService.getOne(new QueryWrapper<StDomain>().orderByDesc("UPDATED_TIME").last("limit 1"));
        stMenuVo.setUpdateDate(entity!=null?entity.getUpdatedTime():new Date());
        map.put("stDomain",stMenuVo);
    }

    private void stClassify(Map<String, StMenuVo> map){
        long count = iStClassifyService.count();
        StMenuVo stMenuVo = new StMenuVo();
        stMenuVo.setCount(count);
        StClassify entity = iStClassifyService.getOne(new QueryWrapper<StClassify>().orderByDesc("UPDATED_TIME").last("limit 1"));
        stMenuVo.setUpdateDate(entity!=null?entity.getUpdatedTime():new Date());
        map.put("stClassify",stMenuVo);
    }

    @Override
    public Map<String, StMenuVo> statistics() {
        Map<String, StMenuVo> map = new HashMap<>();
        stCaMain(map);
        stMetric(map);
        stCheck(map);
        stCollection(map);
        stCompliane(map);
        stInnerControl(map);
        stInnerControlOrder(map);
        stScenario(map);
        stEvent(map);
        stBestPractices(map);
        stBestCase(map);
        stProblem(map);
        stLable(map);
        stDomain(map);
        stClassify(map);
        return map;
    }

    @Override
    public Map<String, Long> statisticsByCaNo(String caNo) {
        if(StringUtils.isEmpty(caNo)){
            return null;
        }
        Map<String, Long> data = new HashMap<>();
        long count = iStCaMainMetricService.count(new QueryWrapper<StCaMainMetric>().eq("CA_NO",caNo));
        data.put("metric",count);
        long count2 = iStComplianeItemService.count(new QueryWrapper<StComplianeItem>().eq("CA_NO",caNo));
        data.put("compliane",count2);
        List<StInnerControl> stInnerControlList = iStInnerControlService.list(new QueryWrapper<StInnerControl>().eq("CA_NO",caNo));
        long count3 = 0L;
        if(!CollectionUtils.isEmpty(stInnerControlList)) {
            List<String> strategyNos = stInnerControlList.stream().map(StInnerControl::getStrategyNo).collect(Collectors.toList());
            count3 = iStInnerControlOrderService.count(new QueryWrapper<StInnerControlOrder>()
                    .in("STRATEGY_NO",strategyNos));
        }
        data.put("innerControl",count3);
        long count4 = iStBestPracticesService.count(new QueryWrapper<StBestPractices>().eq("CA_NO",caNo));
        data.put("best",count4);
        long count5 = iStCaMainCheckService.count(new QueryWrapper<StCaMainCheck>().eq("CA_NO",caNo));
        data.put("check",count5);
        long count6 = iStProblemService.count(new QueryWrapper<StProblem>().eq("CA_NO",caNo));
        data.put("problem",count6);        QueryWrapper<StCaMainLable> stCaMainLableQueryWrapper = new QueryWrapper<>();
        stCaMainLableQueryWrapper.eq("CA_NO",caNo);
        List<StCaMainLable> lables =  iStCaMainLableService.list(stCaMainLableQueryWrapper);
        // todo 待重新关联风险事件
        long count7 = iStRiskEventService.countBylables(lables);
        data.put("event",count7);
        return data;
    }

    @Override
    public Map<String, Long> statisticsByComplianceNo(String complianeNo) {
        if(StringUtils.isEmpty(complianeNo)){
            return null;
        }
        Map<String, Long> map = new HashMap<>();
        long count1 = iStProblemService.count(new QueryWrapper<StProblem>().eq("COMPLIANE_NO",complianeNo));
        map.put("problem",count1);
        long count2 = iStComplianeItemService.count(new QueryWrapper<StComplianeItem>().eq("COMPLIANE_NO",complianeNo));
        map.put("item",count2);
        long count3 = 0L;
        List<StComplianeRiskRef> listRef = iStComplianeRiskRefService.list(new QueryWrapper<StComplianeRiskRef>().eq("COMPLIANE_NO",complianeNo));
        if(!CollectionUtils.isEmpty(listRef)){
            List<String> riskNos = listRef.stream().map(StComplianeRiskRef::getRiskNo).collect(Collectors.toList());
            count3 = iStRiskEventService.count(new QueryWrapper<StRiskEvent>().in("RISK_EVENT_NO",riskNos));
        }
        map.put("risk",count3);
        return map;
    }

    public static String IgnoreCaseReplace(String source, String[] patternstring) {
        StringBuffer sb = new StringBuffer();
        for(int i=0;i<patternstring.length;i++) {
            Pattern p = Pattern.compile(patternstring[i], Pattern.CASE_INSENSITIVE);
            Matcher mc = p.matcher(source);
            while (mc.find()) {
                mc.appendReplacement(sb, String.format("<span style=\"color:red\">%s</span>",mc.group()));
            }
            mc.appendTail(sb);
        }

        return sb.toString();
    }

//    @Override
//    public IPage<QueryVo> queryCommonByPage(IPage<QueryVo> page, QueryVo queryVo) {
//        IPage<QueryVo> data = stCommonMapper.queryCommonByPage(page,queryVo);
//        List<QueryVo> records = data.getRecords();
//        LableVo lableVo = new LableVo();
//        List<String> lable2 = new ArrayList<>();
//        List<String> lable4 = new ArrayList<>();
//        for(QueryVo qvo:records){
//            if(StringUtils.isNotEmpty(queryVo.getName())) {
//                String name = qvo.getName();
//                String[] qNames = queryVo.getNames();
//                qvo.setName(IgnoreCaseReplace(name,qNames));
//            }
//            if(qvo.getSctype().equals("2")) {
//                lable2.add(qvo.getBizNo());
//            }
//            if(qvo.getSctype().equals("4")) {
//                lable4.add(qvo.getBizNo());
//            }
//
//        }
//
//        if(lable2.size()>0) {
//            lableVo.setLable2(lable2);
//        }
//        if(lable4.size()>0) {
//            lableVo.setLable4(lable4);
//        }
//        if(lableVo.getLable2()!=null||lableVo.getLable4()!=null) {
//            List<LableVo> listLable = stCommonMapper.queryLables(lableVo);
//            for (QueryVo qvo : records) {
//                for (LableVo labelVo : listLable) {
//                    if (qvo.getBizNo().equals(labelVo.getBizNo())) {
//                        qvo.setLableNames(labelVo.getLableNames());
//                        if (StringUtils.isNotEmpty(qvo.getLableNames())) {
//                            qvo.buildLable(labelVo.getLableCodes(),qvo.getLableNames(), queryVo.getName());
//                            break;
//                        }
//                    }
//                }
//            }
//            data.setRecords(records);
//        }
//        return data;
//    }

    @Override
    public IPage<DutyVo> queryDutyVoByPage(Page<DutyVo> page, DutyVo queryVo) {
        IPage<DutyVo> data = stCommonMapper.queryDutyByPage(page,queryVo);
        List<DutyVo> records = data.getRecords();
        if(!CollectionUtils.isEmpty(records)){
            for(DutyVo dutyVo:records){
                dutyVo.initDutyNames();
            }
        }
        return data;
    }

    @Override
    public DutyVo queryDutyByCode(String code) {
        return stCommonMapper.queryDutyByCode(code);
    }

    @Override
    public Map<String, StMenuVo> statisticsProject() {
        Map<String, StMenuVo> map = new HashMap<>();
        stPlanMain(map);
        stPlanMainChange(map);
        stPlanMainApprove(map);
        return map;
    }

    private void stPlanMain(Map<String, StMenuVo> map) {
        long count = iStPlanManService.count();
        StMenuVo stMenuVo = new StMenuVo();
        stMenuVo.setCount(count);
        StPlanMan entity = iStPlanManService.getOne(new QueryWrapper<StPlanMan>().orderByDesc("UPDATED_TIME").last("limit 1"));
        stMenuVo.setUpdateDate(entity!=null?entity.getUpdatedTime():new Date());
        map.put("planmain",stMenuVo);
    }

    private void stPlanMainChange(Map<String, StMenuVo> map) {
        QueryWrapper<StPlanMan> queryWrapper = new QueryWrapper<>();
        queryWrapper.in("PLAN_FLAG", PlanFlag.CHANGE_LIST);
        long count = iStPlanManService.count(queryWrapper);
        StMenuVo stMenuVo = new StMenuVo();
        stMenuVo.setCount(count);
        queryWrapper.orderByDesc("UPDATED_TIME").last("limit 1");
        StPlanMan entity = iStPlanManService.getOne(queryWrapper);
        stMenuVo.setUpdateDate(entity!=null?entity.getUpdatedTime():new Date());
        map.put("planchange",stMenuVo);
    }

    private void stPlanMainApprove(Map<String, StMenuVo> map) {
        long count = iStPlanApproveService.count();
        StMenuVo stMenuVo = new StMenuVo();
        stMenuVo.setCount(count);
        StPlanApprove entity = iStPlanApproveService.getOne(new QueryWrapper<StPlanApprove>().orderByDesc("UPDATED_TIME").last("limit 1"));
        stMenuVo.setUpdateDate(entity!=null?entity.getUpdatedTime():new Date());
        map.put("planapprove",stMenuVo);
    }


    @Override
    public List<QueryVo> queryCommonAll(QueryVo queryVo) {
        List<QueryVo>  data = stCommonMapper.queryCommonByPage(queryVo);
        return data;
    }

//    @Override
//    public List<EsQueryFileVo> queryAllFile(EsQueryFileVo queryVo) {
//        List<EsQueryFileVo>  data = stCommonMapper.queryAllFile(queryVo);
//        return data;
//    }

    @Override
    public List<QueryVo> queryAllLibData(QueryVo queryVo) {
        List<QueryVo> data = stCommonMapper.queryAllLibData(queryVo);
        return data;
    }

    @Override
    public IPage<QueryVo> queryCommonByPage(IPage<QueryVo> page, QueryVo queryVo) {
        IPage<QueryVo> data = stCommonMapper.queryAllLibData(page,queryVo);
        List<QueryVo> records = data.getRecords();
        for(QueryVo qvo:records) {
            if (StringUtils.isNotEmpty(queryVo.getName())) {
                String name = qvo.getName();
                String[] qNames = queryVo.getNames();
                qvo.setName(IgnoreCaseReplace(name, qNames));
            }
        }
        return data;
    }
}
