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

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.yeejoin.amos.boot.biz.common.constants.CommonConstant;
import com.yeejoin.amos.boot.biz.common.entity.DataDictionary;
import com.yeejoin.amos.boot.biz.common.utils.RedisKey;
import com.yeejoin.amos.boot.biz.common.utils.RedisUtils;
import com.yeejoin.amos.boot.biz.common.utils.TreeParser;
import com.yeejoin.amos.boot.module.common.api.entity.OrgUsr;
import com.yeejoin.amos.boot.module.hygf.api.Enum.DealerReviewEnum;
import com.yeejoin.amos.boot.module.hygf.api.Enum.PowerStationNodeEnum;
import com.yeejoin.amos.boot.module.hygf.api.Enum.PowerStationProcessStateEnum;
import com.yeejoin.amos.boot.module.hygf.api.dto.CommerceInfoDto;
import com.yeejoin.amos.boot.module.hygf.api.dto.UnitRegisterDto;
import com.yeejoin.amos.boot.module.hygf.api.entity.*;
import com.yeejoin.amos.boot.module.hygf.api.fegin.IdxFeginService;
import com.yeejoin.amos.boot.module.hygf.api.fegin.PrivilegeFeginService;
import com.yeejoin.amos.boot.module.hygf.api.mapper.DealerReviewMapper;
import com.yeejoin.amos.boot.module.hygf.api.mapper.UnitInfoMapper;
import com.yeejoin.amos.boot.module.hygf.api.service.IDealerReviewService;
import com.yeejoin.amos.boot.module.hygf.api.service.IUnitInfoService;
import com.yeejoin.amos.boot.module.hygf.api.dto.UnitInfoDto;
import com.yeejoin.amos.component.feign.config.TokenOperation;
import com.yeejoin.amos.component.feign.model.FeignClientResult;
import com.yeejoin.amos.component.robot.AmosRequestContext;
import com.yeejoin.amos.feign.privilege.Privilege;
import com.yeejoin.amos.feign.privilege.model.AgencyUserModel;
import com.yeejoin.amos.feign.privilege.model.CompanyModel;
import com.yeejoin.amos.feign.privilege.model.RoleModel;
import com.yeejoin.amos.feign.systemctl.Systemctl;
import com.yeejoin.amos.feign.systemctl.model.SmsRecordModel;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.ObjectUtils;
import org.typroject.tyboot.core.foundation.context.RequestContext;
import org.typroject.tyboot.core.foundation.exception.BaseException;
import org.typroject.tyboot.core.foundation.utils.Bean;
import org.typroject.tyboot.core.foundation.utils.ValidationUtil;
import org.typroject.tyboot.core.rdbms.service.BaseService;
import org.springframework.stereotype.Service;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import org.typroject.tyboot.core.restful.exception.instance.BadRequest;
import org.typroject.tyboot.core.restful.utils.ResponseModel;

import java.util.*;
import java.util.concurrent.Callable;
import java.util.concurrent.FutureTask;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
 * 经销商人员信息服务实现类
 *
 * @author system_generator
 * @date 2023-07-07
 */
@Service
public class UnitInfoServiceImpl extends BaseService<UnitInfoDto,UnitInfo,UnitInfoMapper> implements IUnitInfoService {

    String COMPANY_TREE_REDIS_KEY = "REGULATOR_UNIT_TREE";

    @Value("${regulator.unit.code}")
    private String code;

    @Value("${dealer.appcode}")
    private String appCodes;

    @Autowired
    RedisUtils redisUtil;

    @Autowired
    PrivilegeFeginService privilegeFeginService;

    @Autowired
    CommerceInfoServiceImpl commerceInfoService;
    @Autowired
    IDealerReviewService dealerReviewService;
    @Value("${hygf.user.group.id}")
    private long userGroupId;

    @Autowired
    IdxFeginService idxFeginService;
    private static final String regionRedis="app_region_redis";
    private static final String OPERATION_TYPE_SUBMIT="submit";
    private static final String OPERATION_TYPE_APPLY="apply";
    private static final String IDX_REQUEST_STATE="200";
    private static final String VERIFY_RESULT_YES="0";
    private static final String VERIFY_RESULT_NO="1";
    @Autowired
    DealerReviewMapper dealerReviewMapper;

    @Value("${power.station.examine.pageId}")
    private long pageId;
    @Autowired
    AmosRequestContext requestContext;
    @Value("${unitInfo.station.examine.planId}")
    private String planId;

    @Value("${amos.system.user.product}")
    private String AMOS_STUDIO_WEB;
    @Value("${amos.system.user.app-key}")
    private String AMOS_STUDIO;

    @Value("${hygf.sms.tempCodeJXS}")
    private String smsTempCode;
    /**
     * 分页查询
     */
    public Page<UnitInfoDto> queryForUnitInfoPage(Page<UnitInfoDto> page)   {
        return this.queryForPage(page, null, false);
    }

    /**
     * 列表查询 示例
     */
    public List<UnitInfoDto> queryForUnitInfoList()   {
        return this.queryForList("" , false);
    }

    @Override
    public Collection getManagementUnitTree(String orgCode) {
        List<LinkedHashMap> companyModels = (List<LinkedHashMap>) redisUtil.get(COMPANY_TREE_REDIS_KEY);
        if (ValidationUtil.isEmpty(companyModels)) {
            companyModels = creatTree();
        }
        if (!ValidationUtil.isEmpty(orgCode)) {
            companyModels = findNodesByCondition(companyModels, "orgCode", orgCode, "children");
            companyModels = (List<LinkedHashMap>) companyModels.get(0).get("children");
        }
        return companyModels;
    }

    @Override
    @Transactional
    public UnitRegisterDto registerUnit(UnitRegisterDto model) {
        UnitInfoDto regUnitInfo = model.getUnitInfoDto();
        try {
            // 1. 调用平台进行创建单位、用户信息
            this.createCompanyAndUser(regUnitInfo);
            // 2.插入单位表
          //  regUnitInfo = this.createWithModel(regUnitInfo);
            regUnitInfo = this.createWithModelnew(regUnitInfo);
            CommerceInfoDto commerceInfo = model.getCommerceInfoDto();
            commerceInfo.setUnitSeq(regUnitInfo.getSequenceNbr());
            commerceInfo = commerceInfoService.createWithModel(commerceInfo);
            model.setCommerceInfoDto(commerceInfo);
            model.setUnitInfoDto(regUnitInfo);
        } catch (Exception e) {
            log.error(e.getMessage(), e);
            // 失败后回滚：删除已经创建的企业信息
            if (!ObjectUtils.isEmpty(regUnitInfo.getAmosCompanySeq())) {
                FeignClientResult<CompanyModel> feignClientResult = Privilege.companyClient
                        .seleteOne(regUnitInfo.getAmosCompanySeq());
                if (feignClientResult != null) {
                    Privilege.companyClient.deleteCompany(regUnitInfo.getAmosCompanySeq().toString());
                }
            }
            // 失败后回滚：删除已经创建的管理员账号
            if (StringUtils.isNotEmpty(regUnitInfo.getAdminUserId())) {
                FeignClientResult<AgencyUserModel> feignClientResult = Privilege.agencyUserClient
                        .queryByUserId(regUnitInfo.getAdminUserId());
                if (feignClientResult != null) {
                    Privilege.agencyUserClient.multDeleteUser(regUnitInfo.getAdminUserId());
                }
            }
            throw new RuntimeException(e.getMessage());
        }
        return model;
    }

    private static List<LinkedHashMap> findNodesByCondition(List<LinkedHashMap> nodes, String conditionName,
                                                           String condition, String childName) {
        return nodes.stream()
                .flatMap(node -> Stream.concat(
                        node.get(conditionName).equals(condition) ? Stream.of(node) : Stream.empty(),
                        node.get(childName) != null ? findNodesByCondition((List<LinkedHashMap>) node.get(childName),
                                conditionName, condition, condition).stream() :
                                Stream.empty()
                ))
                .collect(Collectors.toList());
    }

    private List<LinkedHashMap> creatTree() {
        FeignClientResult tree = privilegeFeginService.tree(RequestContext.getToken(),RequestContext.getAppKey(),RequestContext.getProduct());
        List<LinkedHashMap> result = (List<LinkedHashMap>) tree.getResult();
        List<LinkedHashMap> treeData = deleteRegulatorTreeData(result);
        List<LinkedHashMap> supervisionTree = treeData.stream().filter(e -> code.equals(e.get("orgCode"))).collect(Collectors.toList());
        List<LinkedHashMap> resultTree = updateNullChildren(supervisionTree);
        redisUtil.set(COMPANY_TREE_REDIS_KEY, resultTree);
        return resultTree;
    }

    /**
     * 将管辖机构树中children为[]的修改为null
     *
     * @param result
     * @return
     */
    private List<LinkedHashMap> updateNullChildren(List<LinkedHashMap> result) {
        Iterator it = result.iterator();
        while (it.hasNext()) {
            LinkedHashMap e = (LinkedHashMap) it.next();
            //将管辖机构树中children为[]的修改为null
            if (e.get("children") != null) {
                if (((List<LinkedHashMap>) e.get("children")).size() == 0) {
                    e.put("children", null);
                }
            }
            if (!ObjectUtils.isEmpty(e.get("children"))) {
                updateNullChildren((List<LinkedHashMap>) e.get("children"));
            }
        }
        return result;
    }

    /**
     * 删除管辖机构树中level为使用单位的数据
     * @param result 管辖机构树
     * @return 筛选过滤后不包含使用单位的管辖机构树
     */
    private List<LinkedHashMap> deleteRegulatorTreeData(List<LinkedHashMap> result) {
        Iterator it = result.iterator();
        while (it.hasNext()) {
            LinkedHashMap e = (LinkedHashMap) it.next();
            //删除使用单位
            if ("company".equals(e.get("level"))) {
                it.remove();
            }
            if (e.get("companyName").toString().contains("行政审批局")) {
                it.remove();
            }
            if (!ObjectUtils.isEmpty(e.get("children"))) {
                deleteRegulatorTreeData((List<LinkedHashMap>) e.get("children"));
            }
        }
        return result;
    }

    private void createCompanyAndUser(UnitInfoDto regUnitInfo) {
        CompanyModel companyInfo = new CompanyModel();
        FeignClientResult<AgencyUserModel> userResult = null;
        try {
            FeignClientResult<List<RoleModel>> roleListResult = Privilege.roleClient.queryRoleList(null, null);
            List<RoleModel> allRoleList = roleListResult.getResult();
            List<RoleModel> userRoleList = new ArrayList<>();
            List<Long> roleIds = new ArrayList<>();
            // 1创建公司
            companyInfo.setAddress(regUnitInfo.getRegisterPcd());
            companyInfo.setAgencyCode("JXIOP");
            companyInfo.setParentId(Long.parseLong(regUnitInfo.getManagementUnitId()));
            companyInfo.setLevel("station");
            companyInfo.setCompanyName(regUnitInfo.getName());
//            companyInfo.setCompanyCode(regUnitInfo.getUnitTypeCode());
            companyInfo.setContact(regUnitInfo.getHeadName());
            companyInfo.setCompanyType(regUnitInfo.getUnitType());
            companyInfo.setLandlinePhone(regUnitInfo.getHeadPhone());
            FeignClientResult<CompanyModel> companyResult = Privilege.companyClient.create(companyInfo);
            if (companyResult == null || companyResult.getResult() == null) {
                throw new BadRequest("单位注册失败");
            }
            String adminUserName = regUnitInfo.getAdminUserName();
            String loginName = regUnitInfo.getAdminLoginName();
            String pwd = regUnitInfo.getAdminLoginPwd();
            String adminTel = regUnitInfo.getAdminPhone();
            // 2 创建平台用户
            companyInfo = companyResult.getResult();
            AgencyUserModel agencyUserModel = new AgencyUserModel();
            agencyUserModel.setUserName(loginName);
            agencyUserModel.setRealName(adminUserName);
            agencyUserModel.setLockStatus("LOCK");
            agencyUserModel.setPassword(pwd);
            agencyUserModel.setRePassword(pwd);
            agencyUserModel.setAgencyCode("JXIOP");
            agencyUserModel.setMobile(adminTel);
            List<String> split = Arrays.asList(StringUtils.split(appCodes, ','));
            Map<Long, List<Long>> roleSeqMap = new HashMap<>();
            Map<Long, List<RoleModel>> orgRoles = new HashMap<>();
            userRoleList = allRoleList.stream().filter(r -> r.getRoleName().equals(regUnitInfo.getUnitTypeCode()))
                    .collect(Collectors.toList());
            userRoleList.forEach(r -> {
                if (!roleIds.contains(r.getSequenceNbr())) {
                    roleIds.add(r.getSequenceNbr());
                }
            });
            roleSeqMap.put(companyInfo.getSequenceNbr(), roleIds);
            orgRoles.put(companyInfo.getSequenceNbr(), userRoleList);
            agencyUserModel.setAppCodes(split);
            agencyUserModel.setOrgRoles(orgRoles);
            agencyUserModel.setOrgRoleSeqs(roleSeqMap);
            userResult = Privilege.agencyUserClient.create(agencyUserModel);
            if (userResult == null || userResult.getResult() == null) {
                throw new BadRequest("单位注册失败");
            }
//            String[] userIds = { userResult.getResult().getUserId() };
            regUnitInfo.setAdminUserId(userResult.getResult().getUserId());
            regUnitInfo.setAmosCompanySeq(companyInfo.getSequenceNbr());
            List<String> userId = new ArrayList<>();
            userId.add(userResult.getResult().getUserId());
            // 将创建用户加入用户组
            Privilege.groupUserClient.create(userGroupId, userId);
        } catch (Exception e) {
            // 删除已经创建的 企业信息
            if (companyInfo != null && companyInfo.getSequenceNbr() != null) {
                Privilege.companyClient.deleteCompany(companyInfo.getSequenceNbr() + "");
            }
            if (userResult != null && userResult.getResult() != null
                    && StringUtils.isNotEmpty(userResult.getResult().getUserId())) {
                Privilege.agencyUserClient.multDeleteUser(userResult.getResult().getUserId());
            }
            log.error(e.getMessage(), e);
            throw new RuntimeException(e.getMessage());
        }
    }


   public UnitInfoDto  createWithModelnew(UnitInfoDto regUnitInfo){
       regUnitInfo.setBlacklist(0);
       regUnitInfo.setAuditStatus(1);
       regUnitInfo.setManagementUnit("经销商事业部");
       regUnitInfo= this.createWithModel(regUnitInfo);
       this.submitExamine(regUnitInfo);
       return regUnitInfo;
   }


    private void submitExamine( UnitInfoDto regUnitInfo) {
        String taskId = null;
        Map<String, Object> objectMap = new HashMap<>(1);
        objectMap.put("describe", "经销商已上传信息");
        // 第一步启动工作流
        DealerReview dealerReview = new DealerReview();
        // 保存并审核
        try {
            FeignClientResult<String> submit = idxFeginService.tokenSubmit(AMOS_STUDIO, AMOS_STUDIO_WEB,requestContext.getToken(),pageId, taskId, planId, null, null, null, objectMap);

            if (IDX_REQUEST_STATE.equals(String.valueOf(submit.getStatus()))) {
                String code = submit.getResult();
                // 插入记录表
                dealerReview.setPlanInstanceId(planId);
                dealerReview.setUnitInfoId(regUnitInfo.getSequenceNbr());
                // 获取流程信息
                FeignClientResult<JSONObject> record = idxFeginService.getRecordtoken(AMOS_STUDIO, AMOS_STUDIO_WEB,requestContext.getToken(),code);
                if (IDX_REQUEST_STATE.equals(String.valueOf(record.getStatus()))) {
                    JSONObject resultObj = record.getResult();
                    String taskIdNew = String.valueOf(resultObj.get("taskId"));
                    String processInstanceId = String.valueOf(resultObj.get("processInstanceId"));
                    String flowTaskId = String.valueOf(resultObj.get("flowTaskId"));
                    dealerReview.setTaskId(taskIdNew);
                    dealerReview.setProcessInstanceId(processInstanceId);
                    dealerReview.setFlowTaskId(flowTaskId);
                    dealerReview.setNextProcessNode(DealerReviewEnum.经销商管理员审核.getCode());
                }
                dealerReviewService.saveDealerReview(dealerReview,true,false);
            }else{
                throw new BaseException("获取工作流节点失败！","400","获取工作流节点失败！");
            }
        } catch (Exception e){
            throw new BaseException("获取工作流节点失败！","400","获取工作流节点失败！");
        }
    }



    @Override
    @Transactional
    public String powerStationExamine(long pageId, String nodeCode, String stationId, String taskId, String planInstanceId, Map<String, Object> kv) {

        // 2.更新审核记录表
        try{
        DealerReview  dealerReview= dealerReviewMapper.selectOne(new QueryWrapper<DealerReview>().eq("unit_info_id", stationId));
        UnitInfo  unitInfo= this.getById(stationId);
        DealerReviewEnum nodeByCode = DealerReviewEnum.getNodeByCode(nodeCode);
        if (DealerReviewEnum.经销商管理员审核.getCode().equals(nodeCode)) {
            String result = String.valueOf(kv.get("approvalStatue"));
            if (VERIFY_RESULT_NO.equals(result)) {
                // 1. 更新经销商状态
                unitInfo.setAuditStatus(3);
                //发送断线
                Boolean flag = true;
                HashMap<String, String> params = new HashMap<>(3);
                String meg= String.valueOf(kv.get("approveInfo"));
                params.put("code","不通过");
                params.put("mobile",unitInfo.getAdminPhone());
                params.put("smsCode", smsTempCode);
                FeignClientResult<SmsRecordModel> date= Systemctl.smsClient.sendCommonSms(params);
            }else{
                // 1. 更新经销商状态
                unitInfo.setAuditStatus(2);
                Privilege.agencyUserClient.unlockUsers(unitInfo.getAdminUserId());
            }
        }
             // 2. 更新流程状态
               String code = null;
            // 3. 工作流执行
            FeignClientResult<String> submit = idxFeginService.submit(pageId, taskId, planInstanceId, null, null, null, kv);
            if (IDX_REQUEST_STATE.equals(String.valueOf(submit.getStatus()))) {
                code = submit.getResult();
                // 获取流程信息
                FeignClientResult<JSONObject> record = idxFeginService.getRecord(code);
                if (IDX_REQUEST_STATE.equals(String.valueOf(record.getStatus()))) {
                    JSONObject resultObj = record.getResult();
                    String flowTaskId = String.valueOf(resultObj.get("flowTaskId"));
                    dealerReview.setFlowTaskId(flowTaskId);
                }
                dealerReviewService.saveDealerReview(dealerReview,false,true);
            }
            this.saveOrUpdate(unitInfo);
        }catch (Exception e){
            throw new  BaseException("获取工作流节点失败！","400","获取工作流节点失败！");

        }
        return code;
    }

}