package com.xunmei.core.resumption.service.impl;

import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.xunmei.common.core.constant.SecurityConstants;
import com.xunmei.common.security.utils.SecurityUtils;
import com.xunmei.core.resumption.domain.*;
import com.xunmei.core.resumption.mapper.*;
import com.xunmei.core.resumption.service.AppPlanService;
import com.xunmei.core.resumption.vo.appPlan.AppPlanVo;
import com.xunmei.core.resumption.vo.appPlan.RuleItemVo;
import com.xunmei.core.resumption.vo.appPlan.RuleRequestVo;
import com.xunmei.system.api.RemoteOrgService;
import com.xunmei.system.api.domain.SysOrg;
import com.xunmei.system.api.model.LoginUser;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;
import java.util.stream.Collectors;

/**
 * @author : 高雄
 * @date :2022/4/27 17:44
 * @description :
 * @modyified By:
 */
@Service
public class AppPlanServiceImpl extends ServiceImpl<AppPlanMapper, AppPlan> implements AppPlanService {

    @Autowired
    private AppRuleMapper appRuleMapper;

    @Autowired
    private RemoteOrgService orgService;

    @Autowired
    private AppPlanToRoleMapper appPlanToRoleMapper;

    @Autowired
    private AppPlanToItemMapper appPlanToItemMapper;


    @Autowired
    private AppPlanToCheckOrgMapper appPlanToCheckOrgMapper;

    @Autowired
    private AppPlanToExecOrgMapper appPlanToExecOrgMapper;
    @Autowired
    private SysResumptionMapper sysResumptionMapper;

    @Override
    public List<Long> selectItemIdsByPlanId(Long id) {
        return appPlanToItemMapper.selectItemIdsByPlanId(id);
    }
//    @Autowired
//    private ResumptionService resumptionService;


    @Autowired
    RedisTemplate redisTemplate;

    @Override
    public Page<AppPlan> selectPage(AppPlanVo info) {
        Page<AppPlan> page = new Page<>();
        long current = info.getPage() + 1;
        long size = info.getSize();
        page.setCurrent(current);
        page.setSize(size);
        Page<AppPlan> result = baseMapper.selectPage(page, info);
        return result;
    }

    @Override
    public List<Long> findExecOrgByPlan(Long plan_id) {
        return baseMapper.findExecOrgByPlan(plan_id);
    }

    @Override
    public List<Long> findRoleByPlan(Long plan_id) {
        return baseMapper.findRoleByPlan(plan_id);
    }

    /**
     * 获取检查要点分页
     *
     * @param info
     * @return
     */
    @Override
    public Page<RuleItemVo> selectItemPage(RuleItemVo info) {
        Page<RuleItemVo> page = new Page<>();
        long current = info.getPage() + 1;
        long size = info.getSize();
        page.setCurrent(current);
        page.setSize(size);
        if (info.getRuleId() == null) {
            page.setRecords(null);
            return page;
        }
        Page<RuleItemVo> result = baseMapper.selectItemPage(page, info);
        List<RuleItemVo> content = result.getRecords();
        for (RuleItemVo ruleItemVo : content) {
            String key = "dict_config_check_type_" + ruleItemVo.getSafeType();
            String name = (String) redisTemplate.opsForValue().get(key);
            ruleItemVo.setSafeTypeText(name);

            if (ObjectUtil.isNotNull(ruleItemVo.getBusinessType())) {
                key = "dict_config_point_business_type_" + ruleItemVo.getBusinessType();
                name = (String) redisTemplate.opsForValue().get(key);
                ruleItemVo.setBusinessTypeText(name);
            }

        }
        result.setRecords(content);
        return result;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void saveOrUpdatePlan(AppPlanVo app) throws Exception {
        AppPlan plan = convertToAppPlan(app);
        if (app.getId() == null) {
            //新增
            plan.setPlanOfOrgId(app.getPlanCreateOrgId());
            plan.setPlanOfOrgName(app.getPlanCreateOrgName());
            //验证名称是否重复
            QueryWrapper<AppPlan> qw = new QueryWrapper<>();
            qw.lambda().eq(AppPlan::getPlanName, app.getPlanName());

            Long size = baseMapper.selectCount(qw);

            if (size > 0) {
                throw new RuntimeException("计划名称重复，请确认！");
            }


            baseMapper.insert(plan);
            Long id = plan.getId();


            List<Long> roleList = app.getRoleList();
            AppPlanToRole atr = null;
            for (Long roleId : roleList) {
                atr = new AppPlanToRole();
                atr.setRoleId(roleId);
                atr.setPlanId(id);
                appPlanToRoleMapper.insert(atr);
            }

            List<RuleItemVo> itemList = app.getItemList();
            if (itemList.size() == 0) {
                throw new RuntimeException("请选择履职要点");
            }

            AppPlanToItem item = null;
            for (RuleItemVo ruleItemVo : itemList) {
                item = new AppPlanToItem();
                item.setItemId(ruleItemVo.getItemId());
                item.setPlanId(id);
                item.setPointScan(ruleItemVo.isPointScan());
                item.setRequired(ruleItemVo.isRequired());
                appPlanToItemMapper.insert(item);
            }

//            Integer orgId = app.getExecOrgType();
//            if (orgId != null) {
//                AppPlanToCheckOrg checkOrg = new AppPlanToCheckOrg();
//                AppPlanToExecOrg execOrg = new AppPlanToExecOrg();
//                List<SysOrg> sysOrgs = orgService.selectByOrgType(orgId, SecurityConstants.INNER);
//                List<Long> orgids = sysOrgs.stream().map(SysOrg::getId).collect(Collectors.toList());
//                for (Long i :
//                        orgids) {
//                    checkOrg.setOrgId(i);
//                    checkOrg.setPlanId(id);
//                    execOrg.setOrgId(i);
//                    execOrg.setPlanId(id);
//                    appPlanToCheckOrgMapper.insert(checkOrg);
//                    appPlanToExecOrgMapper.insert(execOrg);
//                }
//
//
//
//            }
        } else {
            //修改
            QueryWrapper<AppPlan> qw = new QueryWrapper<>();
            qw.lambda().eq(AppPlan::getPlanName, app.getPlanName())
                    .ne(AppPlan::getId, plan.getId());

            Long size = baseMapper.selectCount(qw);

            if (size > 0) {
                throw new RuntimeException("计划名称重复，请确认！");
            }


            baseMapper.updateById(plan);

            Long id = plan.getId();
            QueryWrapper<AppPlanToRole> apr = new QueryWrapper<>();
            apr.lambda().eq(AppPlanToRole::getPlanId, id);
            appPlanToRoleMapper.delete(apr);

            QueryWrapper<AppPlanToItem> api = new QueryWrapper<>();
            api.lambda().eq(AppPlanToItem::getPlanId, id);
            appPlanToItemMapper.delete(api);


            QueryWrapper<AppPlanToCheckOrg> apc = new QueryWrapper<>();
            apc.lambda().eq(AppPlanToCheckOrg::getPlanId, id);
            appPlanToCheckOrgMapper.delete(apc);

            QueryWrapper<AppPlanToExecOrg> ape = new QueryWrapper<>();
            ape.lambda().eq(AppPlanToExecOrg::getPlanId, id);
            appPlanToExecOrgMapper.delete(ape);

            List<Long> roleList = app.getRoleList();
            AppPlanToRole atr = null;
            for (Long roleId : roleList) {
                atr = new AppPlanToRole();
                atr.setRoleId(roleId);
                atr.setPlanId(id);
                appPlanToRoleMapper.insert(atr);
            }

            List<RuleItemVo> itemList = app.getItemList();
            if (itemList.size() == 0) {
                throw new RuntimeException("请选择履职要点");
            }
            AppPlanToItem item = null;
            for (RuleItemVo ruleItemVo : itemList) {
                item = new AppPlanToItem();
                item.setItemId(ruleItemVo.getItemId());
                item.setPlanId(id);
                item.setPointScan(ruleItemVo.isPointScan());
                item.setRequired(ruleItemVo.isRequired());
                appPlanToItemMapper.insert(item);
            }

            Long orgId = app.getOrgId();
            if (orgId != null) {
                AppPlanToCheckOrg checkOrg = new AppPlanToCheckOrg();
                AppPlanToExecOrg execOrg = new AppPlanToExecOrg();

                checkOrg.setOrgId(orgId);
                checkOrg.setPlanId(id);

                execOrg.setOrgId(orgId);
                execOrg.setPlanId(id);

                appPlanToCheckOrgMapper.insert(checkOrg);
                appPlanToExecOrgMapper.insert(execOrg);
            }

        }

    }

    @Override
    public AppPlanVo findById(Long id) {

        AppPlan appPlan = baseMapper.selectById(id);

        AppPlanVo appPlanVo = convertToAppPlanVo(appPlan);

        QueryWrapper<AppPlanToRole> apr = new QueryWrapper<>();
        apr.lambda().eq(AppPlanToRole::getPlanId, id);
        List<AppPlanToRole> appPlanToRoles = appPlanToRoleMapper.selectList(apr);

        List<Long> roleIds = new ArrayList<>();
        for (AppPlanToRole appPlanToRole : appPlanToRoles) {
            roleIds.add(appPlanToRole.getRoleId());
        }
        appPlanVo.setRoleList(roleIds);

        QueryWrapper<AppPlanToItem> api = new QueryWrapper<>();
        api.lambda().eq(AppPlanToItem::getPlanId, id);
        List<AppPlanToItem> appPlanToItems = appPlanToItemMapper.selectList(api);

        List<RuleItemVo> ruleItemVos = baseMapper.selectByPlanId(id);


        for (RuleItemVo ruleItemVo : ruleItemVos) {
            String key = "dict_config_check_type_" + ruleItemVo.getSafeType();
            String name = (String) redisTemplate.opsForValue().get(key);
            ruleItemVo.setSafeTypeText(name);
            if (ObjectUtil.isNotNull(ruleItemVo.getBusinessType())) {
                key = "dict_config_point_business_type_" + ruleItemVo.getBusinessType();
                name = (String) redisTemplate.opsForValue().get(key);
                ruleItemVo.setBusinessTypeText(name);
            }
        }
        appPlanVo.setItemList(ruleItemVos);


        QueryWrapper<AppPlanToExecOrg> ape = new QueryWrapper<>();
        ape.lambda().eq(AppPlanToExecOrg::getPlanId, id);
        List<AppPlanToExecOrg> orgs = appPlanToExecOrgMapper.selectList(ape);
        if (orgs.size() > 0) {
            appPlanVo.setOrgId(orgs.get(0).getOrgId());
        }


        return appPlanVo;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void deleted(Long id) throws Exception {
        /**
         * 验证计划是否被应用
         */
        Long num = sysResumptionMapper.selectCount(new QueryWrapper<SysResumption>().eq("plan_id", id));
        if (num > 0) {
            throw new RuntimeException("计划已生成任务，不能删除！");
        }

        //删除对应的角色关系
        QueryWrapper<AppPlanToRole> qw = new QueryWrapper<>();
        qw.lambda().eq(AppPlanToRole::getPlanId, id);
        appPlanToRoleMapper.delete(qw);

        //删除对应的要点关系
        QueryWrapper<AppPlanToItem> aw = new QueryWrapper<>();
        aw.lambda().eq(AppPlanToItem::getPlanId, id);
        appPlanToItemMapper.delete(aw);

        //删除机构关系
        QueryWrapper<AppPlanToExecOrg> apo = new QueryWrapper<>();
        apo.lambda().eq(AppPlanToExecOrg::getPlanId, id);
        appPlanToExecOrgMapper.delete(apo);

        QueryWrapper<AppPlanToCheckOrg> aco = new QueryWrapper<>();
        aco.lambda().eq(AppPlanToCheckOrg::getPlanId, id);
        appPlanToCheckOrgMapper.delete(aco);


        //删除本尊
        baseMapper.deleteById(id);


    }


    private AppPlanVo convertToAppPlanVo(AppPlan app) {
        AppPlanVo plan = new AppPlanVo();
        plan.setExecType(app.getExecType());
        plan.setNote(app.getDescription());
        plan.setPlanCycle(app.getPlanCycle());
        plan.setPlanExec(app.getPlanExec());
        plan.setPlanName(app.getPlanName());
        plan.setPlanStatus(app.getPlanStatus());
        plan.setOrgType(app.getExecOrgType());
        plan.setId(app.getId());
        plan.setPlanType(app.getPlanType());
        plan.setNotResumptionOnRest(app.getNotResumptionOnRest());
        plan.setExecOrgType(app.getExecOrgType());

        return plan;
    }

    private AppPlan convertToAppPlan(AppPlanVo app) {
//        LoginUser loginUser = SecurityUtils.getLoginUser();
        AppPlan plan = new AppPlan();
        plan.setCheckType(app.getExecType());
//        plan.setCheckOrgType(app.getOrgType());
        plan.setPlanCreateOrgId(app.getPlanCreateOrgId());
        plan.setPlanCreateOrgName(app.getPlanCreateOrgName());
        Date time = new Date();
        if (app.getId() == null) {
            plan.setCreateTime(time);
        }
        plan.setUpdateTime(time);
        plan.setModifiedName(SecurityUtils.getUsername());
        plan.setModifiedBy(SecurityUtils.getUserId());
        plan.setExecOrgType(app.getExecOrgType());
        plan.setExecType(app.getExecType());
        plan.setPlanType(app.getPlanType());
        plan.setCount(app.getCount());

        plan.setDescription(app.getNote());
        plan.setPlanCycle(app.getPlanCycle());
        plan.setPlanExec(app.getPlanExec());
        plan.setPlanName(app.getPlanName());

        plan.setPlanStatus(app.getPlanStatus());
        plan.setDescription(app.getNote());

        plan.setId(app.getId());
        plan.setNotResumptionOnRest(app.getNotResumptionOnRest());
        return plan;
    }

    @Override
    public List<Map<String, Object>> findByOrg(RuleRequestVo info) {

        List<Map<String, Object>> list = new ArrayList<>();

        if (info.getOrgType() == null && info.getOrgId() == null) {
            return null;
        }
        QueryWrapper<AppRule> qw = new QueryWrapper<>();

        if (info.getOrgType() != null) {
            qw.lambda().eq(AppRule::getOrgType, info.getOrgType()).eq(AppRule::getStatus, 0);
        }

        if (info.getOrgId() != null) {
            SysOrg org = orgService.selectSysOrgById(info.getOrgId(), SecurityConstants.INNER);
            qw.lambda().eq(AppRule::getOrgType, org.getType()).eq(AppRule::getStatus, 0);
        }

        List<AppRule> appRules = appRuleMapper.selectList(qw);

        Map<String, Object> map = null;
        for (AppRule appRule : appRules) {
            map = new HashMap<>();
            map.put("id", appRule.getId());
            map.put("name", appRule.getName());
            list.add(map);
        }
        return list;
    }
}