package com.yeejoin.amos.boot.module.tcm.biz.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.yeejoin.amos.boot.biz.common.entity.BaseEntity;
import com.yeejoin.amos.boot.module.common.api.constant.TZSCommonConstant;
import com.yeejoin.amos.boot.module.common.api.entity.TzsUserPermission;
import com.yeejoin.amos.boot.module.tcm.api.entity.TzBaseEnterpriseInfo;
import com.yeejoin.amos.boot.module.tcm.api.entity.TzsUserInfo;
import com.yeejoin.amos.boot.module.tcm.api.enums.UnitTypeEnum;
import com.yeejoin.amos.boot.module.tcm.flc.api.entity.RegUnitInfo;
import com.yeejoin.amos.boot.module.tcm.flc.biz.service.impl.RegUnitInfoServiceImpl;
import com.yeejoin.amos.feign.privilege.Privilege;
import com.yeejoin.amos.feign.privilege.model.AgencyUserModel;
import com.yeejoin.amos.feign.privilege.model.CompanyModel;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StopWatch;
import org.typroject.tyboot.core.foundation.utils.ValidationUtil;

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

/**
 * @author Administrator
 */
@Service
@Slf4j
public class HistoryDataDealServiceImpl {

    private TzsUserInfoServiceImpl userInfoService;

    private TzsUserPermissionServiceImpl userPermissionService;

    private TzBaseEnterpriseInfoServiceImpl baseEnterpriseInfoService;

    private RegUnitInfoServiceImpl regUnitInfoService;

    public HistoryDataDealServiceImpl(TzsUserInfoServiceImpl userInfoService, TzsUserPermissionServiceImpl userPermissionService, TzBaseEnterpriseInfoServiceImpl baseEnterpriseInfoService, RegUnitInfoServiceImpl regUnitInfoService) {
        this.userInfoService = userInfoService;
        this.userPermissionService = userPermissionService;
        this.baseEnterpriseInfoService = baseEnterpriseInfoService;
        this.regUnitInfoService = regUnitInfoService;
    }

    @Transactional(rollbackFor = Exception.class)
    public int userPermissionUpdate() {
        log.info("刷存量人员资质开始");
        StopWatch stopWatch = new StopWatch();
        stopWatch.start();
        List<TzsUserInfo> usersOfHavingPermission = userInfoService.list(new LambdaQueryWrapper<TzsUserInfo>().isNotNull(TzsUserInfo::getPermissionData));
        List<TzsUserPermission> allWaitFlushData = new ArrayList<>();
        usersOfHavingPermission.forEach(u -> {
            JSON.parseObject(u.getPermissionData()).forEach((k, v) -> {
                List<TzsUserPermission> userPermissions = JSONArray.parseArray(v.toString(), TzsUserPermission.class);
                userPermissions.forEach(p -> {
                    p.setUserSeq(u.getSequenceNbr());
                    p.setPermissionPost(k);
                    p.setRecDate(new Date());
                    p.setRecUserName(u.getRecUserName());
                    p.setRecUserId(u.getRecUserId());
                    p.setRemark("存量数据刷入");
                });
                allWaitFlushData.addAll(userPermissions);
            });
        });
        if (allWaitFlushData.size() > 0) {
            userPermissionService.saveBatch(allWaitFlushData);
        }
        stopWatch.stop();
        log.info("刷存量人员资质结束,有资质的人员数量:{}, 插入的资质条数：{}，耗时：{}秒", usersOfHavingPermission.size(), allWaitFlushData.size(), stopWatch.getTotalTimeSeconds());
        return allWaitFlushData.size();
    }

    @Transactional(rollbackFor = Exception.class)
    public Integer userPersonTypeUpdate() {
        log.info("刷存量人员类型开始");
        StopWatch stopWatch = new StopWatch();
        stopWatch.start();
        LambdaQueryWrapper<TzsUserInfo> wrapper = new LambdaQueryWrapper<>();
        wrapper.select(BaseEntity::getSequenceNbr,TzsUserInfo::getPost,TzsUserInfo::getPostName);
        wrapper.isNotNull(TzsUserInfo::getPost);
        List<TzsUserInfo> users = userInfoService.list(wrapper);
        users.parallelStream().forEach(u->{
            LambdaUpdateWrapper<TzsUserInfo> updateWrapper = new LambdaUpdateWrapper<>();
            // 维保人员人员类型去掉，数据归并到作业人员-枚举处理
            updateWrapper.set(TzsUserInfo::getNewPost, u.getPost().replace("6618","6552"));
            // 由于目前系统作业人员为新增的资质，还没维护资质信息，故与测试沟通去掉post里面的6618维保人员，人员维护后程序会把6618重新冗余到post字段
            updateWrapper.set(TzsUserInfo::getPost, u.getPost().replace("6618",""));
            // 维保人员人员类型去掉，数据归并到作业人员-名称处理保持与new_post一致
            if (u.getPostName() != null) {
                updateWrapper.set(TzsUserInfo::getPostName, u.getPostName().replace("维保人员", "作业人员"));
            }
            updateWrapper.eq(BaseEntity::getSequenceNbr, u.getSequenceNbr());
            userInfoService.update(updateWrapper);
        });

        stopWatch.stop();
        log.info("刷存量人员类型结束，人员数量:{}，耗时：{}秒", users.size(), stopWatch.getTotalTimeSeconds());
        return users.size();
    }

    /**
     * 用企业新orgCode替换各个表缓存orgCode
     * 企业信息
     * 	tz_base_enterprise_info：org_code、
     * 人员信息
     * 	cb_org_usr：amos_org_code
     * 两个规定
     * 	p_static_day、p_static_week、p_static_month：org_code
     * 	p_check、p_check_input、p_check_shot：org_code
     * 	p_plan：user_dept
     * 	p_plan_task：org_code、user_dept
     * 监管业务
     * 	tzs_feedback_suggestions：supervise_org_code
     *
     * @param oldOrgCode 单位旧orgCode
     * @param newOrgCode 单位新orgCode
     * @return
     */
    @Transactional(rollbackFor = Exception.class)
    public Boolean unitOrgCodeUpdate(String oldOrgCode, String newOrgCode) {
        log.info("用企业新orgCode替换各个表缓存orgCode开始");
        String newSuperviseOrgCode = newOrgCode.substring(0, newOrgCode.lastIndexOf("*"));
        HashMap<String, Object> platformCompanyInfo = (HashMap<String, Object>) Privilege.companyClient.queryByOrgcode(newSuperviseOrgCode).getResult();
        // 目前平台返回key为compnay(存在拼写错误)
        CompanyModel parentModel = JSON.parseObject(JSON.toJSONString(platformCompanyInfo.get("compnay")), CompanyModel.class);
        TzBaseEnterpriseInfo baseCompanyInfo = baseEnterpriseInfoService.getBaseMapper().selectOne(new LambdaQueryWrapper<TzBaseEnterpriseInfo>().eq(TzBaseEnterpriseInfo::getOrgCode, oldOrgCode));
        baseEnterpriseInfoService.updateUnitOrgCode(baseCompanyInfo, parentModel, baseCompanyInfo.getSuperviseOrgCode(), newSuperviseOrgCode, oldOrgCode, newOrgCode);
        log.info("用企业新orgCode替换各个表缓存orgCode结束");
        return true;
    }

    /**
     * 监管单位层级调整后，业务表（企业、设备、统计等）冗余的所有旧orgCode替换为新orgCode
     *
     * @param newOrgCode 新orgCode
     * @param oldOrgCode 旧orgCode
     * @return
     */
    @Transactional(rollbackFor = Exception.class)
    public String handleCompanyHisOrgCode(List<Map<String, Object>> orgCodeMap) {
        log.info("用企业新orgCode替换各个表缓存orgCode开始");
        if (ValidationUtil.isEmpty(orgCodeMap)) {
            return "error";
        }
        orgCodeMap.forEach(map -> {
            String newOrgCode = map.get("newOrgCode").toString();
            String oldOrgCode = map.get("oldOrgCode").toString();
            //1. 查询新orgCode对应的监管单位信息
            @SuppressWarnings("unchecked")
            HashMap<String, Object> platformCompanyInfo = (HashMap<String, Object>) Privilege.companyClient.queryByOrgcode(newOrgCode).getResult();
            CompanyModel parentModel = JSON.parseObject(JSON.toJSONString(platformCompanyInfo.get(TZSCommonConstant.PLATFORM_FEIGN_RESULT_KEY_COMPANY)), CompanyModel.class);
            JSONObject modelMap = new JSONObject();
            modelMap.put("newModel", JSON.toJSON(parentModel));
            //2. 处理业务表旧orgCode错误数据
            baseEnterpriseInfoService.refreshSupervisionOrgCode(modelMap, newOrgCode, oldOrgCode);
        });
        return "success";
    }

    public String handleCompanyAppId(List<String> useUnitCodes) {
        log.info("为没有appId的企业生成appId开始");
        List<TzBaseEnterpriseInfo> unitListWithOutAppId;
        if (!ValidationUtil.isEmpty(useUnitCodes)) {
            unitListWithOutAppId = baseEnterpriseInfoService.getBaseMapper().selectList(new LambdaQueryWrapper<TzBaseEnterpriseInfo>().in(TzBaseEnterpriseInfo::getUseUnitCode, useUnitCodes).isNull(TzBaseEnterpriseInfo::getAppId));
        } else {
            unitListWithOutAppId = baseEnterpriseInfoService.getBaseMapper().selectList(new LambdaQueryWrapper<TzBaseEnterpriseInfo>().isNull(TzBaseEnterpriseInfo::getAppId));
        }
        if (!ValidationUtil.isEmpty(unitListWithOutAppId)) {
            // 处理企业未生成appId
            List<TzBaseEnterpriseInfo> companyListWithOutAppId;
            companyListWithOutAppId = unitListWithOutAppId.stream().filter(unit -> !UnitTypeEnum.grzt.getName().equals(unit.getUnitType())).collect(Collectors.toList());

            if (!ValidationUtil.isEmpty(companyListWithOutAppId)) {
                List<RegUnitInfo> regUnitInfoList = regUnitInfoService.list(new LambdaQueryWrapper<RegUnitInfo>().in(RegUnitInfo::getUnitCode, companyListWithOutAppId.stream().map(TzBaseEnterpriseInfo::getUseUnitCode).collect(Collectors.toList())));
                if (!ValidationUtil.isEmpty(regUnitInfoList)) {
                    regUnitInfoList.forEach(regUnitInfo -> {
                        if (ValidationUtil.isEmpty(regUnitInfo.getAppId())) {
                            AgencyUserModel user = new AgencyUserModel();
                            user.setUserId(regUnitInfo.getAdminUserId());
                            try {
                                regUnitInfo.setAppId(regUnitInfoService.createAppId(user));
                            } catch (Exception e) {
                                log.error("为没有appId的企业生成appId异常", e);
                                throw new RuntimeException(e);
                            }
                        }
                        companyListWithOutAppId.stream().filter(company -> company.getUseUnitCode().equals(regUnitInfo.getUnitCode())).forEach(company -> company.setAppId(regUnitInfo.getAppId()));
                    });
                    baseEnterpriseInfoService.updateBatchById(companyListWithOutAppId);
                    regUnitInfoService.updateBatchById(regUnitInfoList);
                }
            }

            List<TzBaseEnterpriseInfo> individualListWithOutAppId = unitListWithOutAppId.stream().filter(unit -> UnitTypeEnum.grzt.getName().equals(unit.getUnitType())).collect(Collectors.toList());;
            // 处理个人主体未生成appId
            List<Map<String, String>> individualUserId = baseEnterpriseInfoService.getBaseMapper().getIndividualUserId();
            if (!ValidationUtil.isEmpty(individualUserId)) {
                individualUserId.forEach(map -> {
                    AgencyUserModel user = new AgencyUserModel();
                    user.setUserId(map.get("adminUserId"));
                    try {
                        map.put("appId", regUnitInfoService.createAppId(user));
                    } catch (Exception e) {
                        log.error("为没有appId的企业生成appId异常", e);
                        throw new RuntimeException(e);
                    }
                });
            }
            if (!ValidationUtil.isEmpty(individualListWithOutAppId)) {
                individualListWithOutAppId.forEach(individual -> {
                    Optional<Map<String, String>> firstMap = individualUserId.stream().filter(map -> map.get("companyCode").equals(individual.getUseCode())).findFirst();
                    firstMap.ifPresent(stringMap -> individual.setAppId(stringMap.get("appId")));
                });
                baseEnterpriseInfoService.updateBatchById(individualListWithOutAppId);
            }
        }
        // 处理baseInfo表有appId，但是regUnitInfo表没有appId的
        List<Map<String, String>> onlyHasBaseInfoAppId = baseEnterpriseInfoService.getBaseMapper().selectOnlyHasBaseInfoAppId();
        if (!ValidationUtil.isEmpty(onlyHasBaseInfoAppId)) {
            List<RegUnitInfo> regUnitInfoList = regUnitInfoService.list(new LambdaQueryWrapper<RegUnitInfo>().isNull(RegUnitInfo::getAppId).in(RegUnitInfo::getUnitCode, onlyHasBaseInfoAppId.stream().map(e -> e.get("useUnitCode")).collect(Collectors.toList())));
            if (!ValidationUtil.isEmpty(regUnitInfoList)) {
                regUnitInfoList.forEach(regUnitInfo -> {
                    Optional<Map<String, String>> firstMap = onlyHasBaseInfoAppId.stream().filter(map -> map.get("useUnitCode").equals(regUnitInfo.getUnitCode())).findFirst();
                    firstMap.ifPresent(stringMap -> regUnitInfo.setAppId(stringMap.get("appId")));
                });
                regUnitInfoService.updateBatchById(regUnitInfoList);
            }
        }
        log.info("为没有appId的企业生成appId结束");
        return "success";
    }
}
