package com.yeejoin.amos.boot.module.tzs.flc.biz.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
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.service.impl.DataDictionaryServiceImpl;
import com.yeejoin.amos.boot.biz.common.utils.QRCodeUtil;
import com.yeejoin.amos.boot.biz.common.utils.TreeParser;
import com.yeejoin.amos.boot.module.common.api.dto.AttachmentDto;
import com.yeejoin.amos.boot.module.common.api.entity.OrgUsr;
import com.yeejoin.amos.boot.module.common.api.service.ISourceFileService;
import com.yeejoin.amos.boot.module.common.biz.service.impl.OrgUsrServiceImpl;
import com.yeejoin.amos.boot.module.common.biz.service.impl.SourceFileServiceImpl;
import com.yeejoin.amos.boot.module.tzs.api.enums.TzsCommonParam;
import com.yeejoin.amos.boot.module.tzs.biz.service.impl.TzsAuthServiceImpl;
import com.yeejoin.amos.boot.module.tzs.flc.api.dto.UnitInfoApproveDto;
import com.yeejoin.amos.boot.module.tzs.flc.api.dto.UnitInfoDto;
import com.yeejoin.amos.boot.module.tzs.flc.api.entity.UnitInfo;
import com.yeejoin.amos.boot.module.tzs.flc.api.entity.UnitInfoChange;
import com.yeejoin.amos.boot.module.tzs.flc.api.mapper.UnitInfoMapper;
import com.yeejoin.amos.boot.module.tzs.flc.api.service.IUnitInfoService;
import com.yeejoin.amos.component.feign.model.FeignClientResult;
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.privilege.util.DesUtil;
import com.yeejoin.amos.feign.systemctl.Systemctl;
import org.apache.commons.lang3.StringUtils;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.mock.web.MockMultipartFile;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;
import org.typroject.tyboot.core.foundation.utils.Bean;
import org.typroject.tyboot.core.rdbms.service.BaseService;
import org.typroject.tyboot.core.restful.exception.instance.BadRequest;

import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

/**
 * 企业信息表服务实现类
 *
 * @author system_generator
 * @date 2021-11-11
 */
@Service
public class UnitInfoServiceImpl extends BaseService<UnitInfoDto, UnitInfo, UnitInfoMapper> implements IUnitInfoService {

    private final Logger logger = LogManager.getLogger(UnitInfoServiceImpl.class);

    @Autowired
    private TzsAuthServiceImpl tzsAuthServiceImpl;

    @Autowired
    ISourceFileService ISourceFileService;

    @Autowired
    DataDictionaryServiceImpl iDataDictionaryService;

    @Autowired
    UnitInfoChangeServiceImpl iUnitInfoChangeServiceImpl;

    @Autowired
    UnitInfoApproveServiceImpl iUnitInfoApproveServiceImpl;

    @Autowired
    OrgUsrServiceImpl iOrgUsrService;

    @Autowired
    UnitInfoChangeServiceImpl unitInfoChangeServiceImpl;

    @Autowired
    SourceFileServiceImpl sourceFileService;


    @Transactional
    public UnitInfoDto saveUnitInfo(UnitInfoDto model) {
        tzsAuthServiceImpl.setRequestContext();
        model.setUnitStatus(0);// 设置为待审核状态
        model.setSubmitTime(new Date()); // 提交时间
        model.setIsChange(false);// 新增状态不是变更状态
        // 处理单位类型
        String unitTypeCode = model.getUnitTypeCode();
        String[] unitTypeCodes = unitTypeCode.split(",");
        String unitType = "";
        for(String t : unitTypeCodes) {
            LambdaQueryWrapper<DataDictionary> queryWrapper = new LambdaQueryWrapper<>();
            queryWrapper.eq(DataDictionary::getType, TzsCommonParam.UNIT_TYPE).eq(DataDictionary::getCode, t);
            DataDictionary temp = iDataDictionaryService.getOne(queryWrapper);
            unitType += "," + temp.getName();
        }
        if(unitType.length() > 0) {
            unitType = unitType.substring(1);
            model.setUnitType(unitType);
        }

        // 处理密码信息
        String oldPwd = model.getAdminLoginPwd();
        String newPwd = DesUtil.encode(oldPwd, "qaz");
        model.setAdminLoginPwd(newPwd);
        UnitInfo entity = this.prepareEntity(model);
        if(this.save(entity)) {
            // 处理图片信息
            Map<String, List<AttachmentDto>> resultPicMap = new HashMap<>();
            resultPicMap.put(TzsCommonParam.LICENCE_PIC,model.getLicencePic());
            resultPicMap.put(TzsCommonParam.ADMIN_LICENSE_PIC,model.getAdminLicensePic());
            ISourceFileService.saveAttachments(entity.getSequenceNbr(),resultPicMap);
        }
        return Bean.toModel(entity, model);
    }

    @Transactional
    @Override
    public UnitInfoDto approve(UnitInfoApproveDto approveDto) {
        UnitInfoDto result = null;
        // 如果不存在审批意见 则 默认 通过 / 驳回
        // 通过unitid 查找企业信息表 如果不存在则查找 变更表 都不存在返回未找到企业审核表单
        String content = approveDto.getContent(); // 审批意见
        UnitInfo sourceUnit = this.getById(approveDto.getUnitId());
        UnitInfoChange changeUnit = null;
        if(sourceUnit == null) {
            changeUnit = iUnitInfoChangeServiceImpl.getById(approveDto.getUnitId());
            if(changeUnit == null) {
                throw new BadRequest("未找到企业审核表单.");
            }
            sourceUnit = this.getById(changeUnit.getSourceId());
        }
        if(sourceUnit.getUnitStatus() != 0) { // 无论变更单还是新建单 原始单状态都应该为审核中
            throw new BadRequest("表单未处于审核状态中.请确认后操作");
        }
        Integer approveStatus = approveDto.getApproveStatus(); // 0通过 1驳回
        Boolean changeFlag = false;
        if(changeUnit != null) {
            changeFlag = true;
            approveDto.setUnitId(changeUnit.getSequenceNbr());
            approveDto.setApproveType(1); // 0 注册审批 1 变更审批
        } else {
            approveDto.setApproveType(0); // 0 注册审批 1 变更审批
        }
        approveDto.setSourceId(sourceUnit.getSequenceNbr());

        if(0 == approveStatus) {
            // 审核通过生成二维码

            this.saveUnitInfoQrCode(sourceUnit);

            if(StringUtils.isEmpty(content)) {
                content = "通过";
            }
            sourceUnit.setUnitStatus(1);
            if(changeFlag) {   // 如果是变更单 需要把 变更数据覆盖到原单子 预留（确定字段）

            } else {     // 如果是审批单 创建用户 创建组织机构 赋权等


                sourceUnit.setApprovedTime(new Date());
                // 创建用户  创建组织机构 平台组织机构及 org_user表中  赋权
                String adminUserName = sourceUnit.getAdminName();
                String loginName = sourceUnit.getAdminLoginName();
                String pwd = sourceUnit.getAdminLoginPwd();
                String adminTel = sourceUnit.getAdminTel();

                CompanyModel companyInfo = new CompanyModel();
                companyInfo.setAddress(sourceUnit.getProvince() + sourceUnit.getCity() + sourceUnit.getDistrict() + sourceUnit.getStree() + sourceUnit.getCommunity() + sourceUnit.getAddress());
                companyInfo.setAgencyCode("tzs");
                companyInfo.setParentId(sourceUnit.getManagementUnitId());
                companyInfo.setLevel("headquarter");
                companyInfo.setCompanyName(sourceUnit.getOrgName());
                companyInfo.setContact(sourceUnit.getUnitTel());
                FeignClientResult<CompanyModel> companyResult = Privilege.companyClient.create(companyInfo);
                if(companyResult == null || companyResult.getResult() == null) {
                    throw new BadRequest("单位注册失败");
                }
                companyInfo = companyResult.getResult();

                AgencyUserModel agencyUserModel = new AgencyUserModel();
                agencyUserModel.setUserName(loginName);
                agencyUserModel.setRealName(adminUserName);
                agencyUserModel.setLockStatus("UNLOCK");
                agencyUserModel.setPassword(pwd);
                agencyUserModel.setRePassword(pwd);
                agencyUserModel.setAgencyCode("tzs");
                agencyUserModel.setMobile(adminTel);

                // 根据unitTypeCode 获取应用和 角色
                String unitTypeCode = sourceUnit.getUnitTypeCode();
                String[] unitTypeCodes = unitTypeCode.split(",");
                Set<String> roleNameSet = new HashSet<>();
                Set<String> appCodesSet = new HashSet<>();
                Map<Long, List<Long>> roleSeqsMap = new HashMap<>();

                for(String code : unitTypeCodes) {
                    DataDictionary unitType = iDataDictionaryService.getOne(new LambdaQueryWrapper<DataDictionary>().eq(DataDictionary::getCode,code));
                    String appCode = unitType.getTypeDesc();
                    String[] appCodes = appCode.split(",");
                    for(String tempCode : appCodes) {
                        appCodesSet.add(tempCode);
                    }
                    roleNameSet.add(unitType.getName());
                }
                List<RoleModel> userRoleList = new ArrayList<>();
                // 全部角色筛选
                // 获取角色
                FeignClientResult<List<RoleModel>> roleListResult = Privilege.roleClient.queryRoleList(null,null);
                List<RoleModel> allRoleList = roleListResult.getResult();
                allRoleList.stream().forEach(t -> {
                    if(roleNameSet.contains(t.getRoleName())) {
                        userRoleList.add(t);
                    }
                });
                List<Long> roleIds = new ArrayList<>();
                userRoleList.stream().forEach(r -> {
                    roleIds.add(r.getSequenceNbr());
                });
                roleSeqsMap.put(companyInfo.getSequenceNbr(),roleIds);


                List<String> appCodes = new ArrayList<>(appCodesSet);
                agencyUserModel.setAppCodes(appCodes);
                Map<Long, List<RoleModel>> orgRoles = new HashMap<>();
                orgRoles.put(companyInfo.getSequenceNbr(),userRoleList);
                agencyUserModel.setOrgRoles(orgRoles);
                agencyUserModel.setOrgRoleSeqs(roleSeqsMap);
                FeignClientResult<AgencyUserModel> userResult = Privilege.agencyUserClient.create(agencyUserModel);

                if(userResult == null || userResult.getResult() == null) {
                    throw new BadRequest("注册失败");
                }
                // org_user 创建组织机构
                OrgUsr org = new OrgUsr();
                TreeParser.genTreeCode();
                org.setBizOrgCode(TreeParser.genTreeCode());
                org.setBizOrgType(CommonConstant.BIZ_ORG_TYPE_COMPANY);
                org.setBizOrgName(sourceUnit.getOrgName());
                org.setRecDate(new Date());
                org.setRecUserId(userResult.getResult().getUserId());
                org.setRecUserName(userResult.getResult().getUserName());
                if(!iOrgUsrService.save(org)) {
                    throw new BadRequest("org单位注册失败");
                }
                sourceUnit.setOrgUserId(org.getSequenceNbr());

            }

        } else if(1 == approveStatus) {
            if(StringUtils.isEmpty(content)) {
                content = "驳回";
            }
            sourceUnit.setUnitStatus(2);

        }
        approveDto.setContent(content);
        iUnitInfoApproveServiceImpl.createWithModel(approveDto);
        if(this.updateById(sourceUnit)) {
            if(changeFlag && 1 == approveStatus) { // 变更不通过返回变更表数据 其他情况返回原数据
                result = unitChangeInfoToDto(changeUnit);
            } else {
                result = unitInfoToDto(sourceUnit);
            }
        }


        return result;
    }

    @Override
    public UnitInfoDto getDtoById(Long sequenceNbr) {
        UnitInfo unitInfo = this.getById(sequenceNbr);
        UnitInfoDto result = null;
        // 如果是变更单 同时为 审批中，默认展示变更表中最新数据
        if(unitInfo.getIsChange() && unitInfo.getUnitStatus() == 0) {
            List<UnitInfoChange> changeList = unitInfoChangeServiceImpl.list(new LambdaQueryWrapper<UnitInfoChange>().eq(UnitInfoChange::getIsDelete,false).eq(UnitInfoChange::getSourceId,sequenceNbr).orderByDesc(UnitInfoChange::getRecDate));
            UnitInfoChange temp = changeList.get(0);
            result = unitChangeInfoToDto(temp);
        } else {
            result = unitInfoToDto(unitInfo);
        }
        return result;
    }


    private UnitInfoDto unitInfoToDto(UnitInfo source) {
        UnitInfoDto target = new UnitInfoDto();
        // 把原对象数据拷贝到新对象
        BeanUtils.copyProperties(source, target);
        if(source.getIsChange()) {
            target.setTypeStr("变更");
        } else {
            target.setTypeStr("注册");
        }
        if(0 == source.getUnitStatus()) {
            target.setStatusStr("审批中");
        } else if(1 == source.getUnitStatus()) {
            target.setStatusStr("审批结束");
        } else if(2 == source.getUnitStatus()) {
            target.setStatusStr("已驳回");
        }
        Map<String, List<AttachmentDto>> attachmentMap = sourceFileService.getAttachments(source.getSequenceNbr());
        // 获取企业二维码
        if(attachmentMap != null) {
            if(attachmentMap.get(TzsCommonParam.QR_CODE) != null) {
                target.setQrcode(attachmentMap.get(TzsCommonParam.QR_CODE));
            }
            if(attachmentMap.get(TzsCommonParam.LICENCE_PIC) != null) {
                target.setLicencePic(attachmentMap.get(TzsCommonParam.LICENCE_PIC));
            }
            if(attachmentMap.get(TzsCommonParam.ADMIN_LICENSE_PIC) != null) {
                target.setAdminLicensePic(attachmentMap.get(TzsCommonParam.ADMIN_LICENSE_PIC));
            }

        }
        target.setFullAddress(source.getProvince() + source.getCity() + source.getDistrict() + source.getStree() + source.getCommunity() + source.getAddress());
        return target;
    }

    private UnitInfoDto unitChangeInfoToDto(UnitInfoChange source) {
        UnitInfoDto target = new UnitInfoDto();
        // 把原对象数据拷贝到新对象
        BeanUtils.copyProperties(source, target);
        if(0 == source.getUnitStatus()) {
            target.setStatusStr("审批中");
        } else if(1 == source.getUnitStatus()) {
            target.setStatusStr("审批结束");
        } else if(2 == source.getUnitStatus()) {
            target.setStatusStr("已驳回");
        }
        Map<String, List<AttachmentDto>> attachmentMap = sourceFileService.getAttachments(source.getSourceId());
        // 获取附件信息
        if(attachmentMap != null) {
            if(attachmentMap.get(TzsCommonParam.QR_CODE) != null) {
                target.setQrcode(attachmentMap.get(TzsCommonParam.QR_CODE));
            }
            if(attachmentMap.get(TzsCommonParam.LICENCE_PIC) != null) {
                target.setLicencePic(attachmentMap.get(TzsCommonParam.LICENCE_PIC));
            }
            if(attachmentMap.get(TzsCommonParam.ADMIN_LICENSE_PIC) != null) {
                target.setAdminLicensePic(attachmentMap.get(TzsCommonParam.ADMIN_LICENSE_PIC));
            }

        }
        target.setFullAddress(source.getProvince() + source.getCity() + source.getDistrict() + source.getStree() + source.getCommunity() + source.getAddress());
        return target;
    }


    private String saveUnitInfoQrCode( UnitInfo sourceUnit) {
        // 二维码生成规则
        String qrString = "企业统一信用代码: " +sourceUnit.getOrganizationCode() +"\n\r";
        qrString += "管理人: " +sourceUnit.getAdminName() +"\n\r";
        qrString += "管理人电话: " +sourceUnit.getAdminTel() +"\n\r";
        byte[] bytes = QRCodeUtil.generateQRCodeImageByteData(qrString, 480);
        MultipartFile file = new MockMultipartFile("unitInfo_" + sourceUnit.getSequenceNbr() + ".png","unitInfo_" + sourceUnit.getSequenceNbr() + ".png","application/octet-stream" ,bytes);
        FeignClientResult<Map<String, String>> result =  Systemctl.fileStorageClient.updateCommonFile(file);
        Map<String, String> map = result.getResult();
        if(map.isEmpty()) {
            logger.error("未生成二维码文件");
            throw new BadRequest("未生成二维码文件");
        }
        String filePath = "";
        for(Map.Entry<String,String> fileResult : map.entrySet()) {
            filePath = fileResult.getKey();
        }
        // 保存qrCode
        List<AttachmentDto> qrCode = new ArrayList<>();
        AttachmentDto temp = new AttachmentDto();
        temp.setName("unitInfo_" + sourceUnit.getSequenceNbr() + ".png");
        temp.setType("image");
        temp.setUrl(filePath);
        qrCode.add(temp);
        Map<String, List<AttachmentDto>> attachmentMap = new HashMap<>();
        attachmentMap.put(TzsCommonParam.QR_CODE,qrCode);
        sourceFileService.saveAttachments(sourceUnit.getSequenceNbr(),attachmentMap);
        return filePath;
    }
}