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

import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;

import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.client.RestTemplate;
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 com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
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.TreeParser;
import com.yeejoin.amos.boot.module.common.api.entity.OrgUsr;
import com.yeejoin.amos.boot.module.common.biz.service.impl.OrgUsrServiceImpl;
import com.yeejoin.amos.boot.module.tzs.api.dto.BaseUnitLicenceDto;
import com.yeejoin.amos.boot.module.tzs.api.entity.BaseUnitLicence;
import com.yeejoin.amos.boot.module.tzs.api.entity.TzBaseEnterpriseInfo;
import com.yeejoin.amos.boot.module.tzs.biz.service.impl.BaseUnitLicenceServiceImpl;
import com.yeejoin.amos.boot.module.tzs.biz.service.impl.TzBaseEnterpriseInfoServiceImpl;
import com.yeejoin.amos.boot.module.tzs.biz.service.impl.TzsAuthServiceImpl;
import com.yeejoin.amos.boot.module.tzs.flc.api.dto.RegUnitIcDto;
import com.yeejoin.amos.boot.module.tzs.flc.api.dto.RegUnitInfoDto;
import com.yeejoin.amos.boot.module.tzs.flc.api.entity.RegUnitIc;
import com.yeejoin.amos.boot.module.tzs.flc.api.entity.RegUnitInfo;
import com.yeejoin.amos.boot.module.tzs.flc.api.enums.UnitReviewStateEnum;
import com.yeejoin.amos.boot.module.tzs.flc.api.mapper.RegUnitInfoMapper;
import com.yeejoin.amos.boot.module.tzs.flc.api.service.IRegUnitInfoService;
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;

/**
 * 单位注册信息表服务实现类
 *
 * @author system_generator
 * @date 2022-08-09
 */
@Service
public class RegUnitInfoServiceImpl extends BaseService<RegUnitInfoDto, RegUnitInfo, RegUnitInfoMapper> implements IRegUnitInfoService {

    @Autowired
    BaseUnitLicenceServiceImpl baseUnitLicenceService;

    @Autowired
    DataDictionaryServiceImpl iDataDictionaryService;

    @Autowired
    OrgUsrServiceImpl iOrgUsrService;

    @Autowired
    RegUnitIcServiceImpl regUnitIcService;

    @Autowired
    private TzsAuthServiceImpl tzsAuthServiceImpl;

    @Autowired
    TzBaseEnterpriseInfoServiceImpl tzBaseEnterpriseInfoService;

    @Autowired
    RestTemplate restTemplate;

    /**
     * 使用单位的类型，数据来源：cb_data_dictionary code = 1232
     */
    private static String USE_UNIT_TYPE_CODE = "1232";

    /**
     * 单位类型，数据来源：cb_data_dictionary type = UNIT_TYPE
     */
    private static String DICT_TYPE_UNIT_TYPE = "UNIT_TYPE_NEW";


    @Override
    @Transactional(rollbackFor = Exception.class)
    public RegUnitInfoDto registerUnit(RegUnitInfoDto model) {
        RegUnitInfo regUnitInfo = new RegUnitInfo();
        try {
            tzsAuthServiceImpl.setRequestContext();
            // 注册用统一信用码注册，默认证件类型为营业执照，数据来源：cb_data_dictionary code = 1060
            model.setUnitCodeType("1060");
            model.setUnitCodeTypeName("营业执照");
            Bean.copyExistPropertis(model, regUnitInfo);
            // 1.插入单位注册许可信息表：tz_base_unit_licence
            List<BaseUnitLicenceDto> unitLicenceDtos = model.getUnitLicences();
            List<BaseUnitLicence> baseUnitLicences = unitLicenceDtos.stream().map(s -> {
                s.setUnitCode(model.getUnitCode());
                s.setUnitName(model.getName());
                BaseUnitLicence target = new BaseUnitLicence();
                Bean.copyExistPropertis(s, target);
                return target;
            }).collect(Collectors.toList());
            if(!baseUnitLicences.isEmpty()){
                baseUnitLicenceService.saveOrUpdateBatch(baseUnitLicences);
            }
            // 2.插入工商单位信息表：tz_flc_reg_unit_ic
            RegUnitIc regUnitIc = new RegUnitIc();
            model.getRegUnitIc().setUnitCode(model.getUnitCode());
            model.getRegUnitIc().setUnitName(model.getName());
            Bean.copyExistPropertis(model.getRegUnitIc(), regUnitIc);
            regUnitIcService.saveOrUpdate(regUnitIc);
            // 3.调用平台进行创建单位、用户信息,同步用户信息
//            if (UnitReviewStateEnum.NO_NEED_REVIEW.getCode().equals(model.getState())) {
                // 3.1 创建企业信息
                this.createBaseEnterpriseInfo(model);
                // 3.2 自动创建：调用平台进行创建单位、用户信息
                this.createCompanyAndUser(regUnitInfo);
//            }
            // 4.插入注册单位基本信息表：tz_flc_reg_unit_info
            this.save(regUnitInfo);
            // 5.组织返回数据
            // 5.1企业基本信息
            Bean.copyExistPropertis(regUnitInfo, model);
            // 5.2行政许可数据
            model.setUnitLicences(Bean.toModels(baseUnitLicences, BaseUnitLicenceDto.class));
            // 5.3工商信息
            model.setRegUnitIc(Bean.toModel(regUnitIc, new RegUnitIcDto()));
        } catch (Exception e) {
            log.error(e.getMessage(),e);
            // 失败后回滚：删除已经创建的企业信息
            if (StringUtils.isNotEmpty(regUnitInfo.getAmosCompanySeq())) {
                FeignClientResult<CompanyModel> feignClientResult = Privilege.companyClient.seleteOne(Long.parseLong(regUnitInfo.getAmosCompanySeq()));
                if (feignClientResult != null) {
                    Privilege.companyClient.deleteCompany(regUnitInfo.getAmosCompanySeq());
                }
            }
            // 失败后回滚：删除已经创建的管理员账号
            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;
    }

    public void createBaseEnterpriseInfo(RegUnitInfoDto regUnitInfo) {
        // 1.查询管辖公司的信息
        FeignClientResult<CompanyModel> feignClientResult = Privilege.companyClient.seleteOne(Long.parseLong(regUnitInfo.getManagementUnitId()));
        CompanyModel managementCompany = feignClientResult.getResult();
        // 2.填充数据
        TzBaseEnterpriseInfo baseEnterpriseInfo = new TzBaseEnterpriseInfo();
        baseEnterpriseInfo.setUseUnitCertificate(regUnitInfo.getUnitCodeTypeName());
        baseEnterpriseInfo.setUnitType(regUnitInfo.getUnitType());
        baseEnterpriseInfo.setUseCode(regUnitInfo.getUnitCode());
        baseEnterpriseInfo.setUseUnit(regUnitInfo.getName());
        baseEnterpriseInfo.setProvince(regUnitInfo.getProvince());
        baseEnterpriseInfo.setCity(regUnitInfo.getCity());
        baseEnterpriseInfo.setDistrict(regUnitInfo.getDistrict());
        baseEnterpriseInfo.setStreet(regUnitInfo.getStree());
        baseEnterpriseInfo.setCommunity(regUnitInfo.getCommunity());
        baseEnterpriseInfo.setAddress(regUnitInfo.getAddress());
        baseEnterpriseInfo.setLegalPerson(regUnitInfo.getLegalPerson());
        baseEnterpriseInfo.setLegalPhone(regUnitInfo.getLegalPersonTel());
        baseEnterpriseInfo.setUseContact(regUnitInfo.getContactPerson());
        baseEnterpriseInfo.setContactPhone(regUnitInfo.getContactPersonTel());
        baseEnterpriseInfo.setLongitude(regUnitInfo.getLongitude());
        baseEnterpriseInfo.setLatitude(regUnitInfo.getLatitude());
        // 管辖机构信息
        baseEnterpriseInfo.setSuperviseCode(managementCompany.getCompanyCode());
        baseEnterpriseInfo.setSuperviseOrgCode(managementCompany.getOrgCode());
        // 这个表有两个字段所以赋值两字段
        baseEnterpriseInfo.setSuperviseOrgName(regUnitInfo.getManagementUnit());
        baseEnterpriseInfo.setGoverningBody(regUnitInfo.getManagementUnit());
        baseEnterpriseInfo.setDataSources("企业注册");
        baseEnterpriseInfo.setIndustry(regUnitInfo.getRegUnitIc().getIndustryName());
        baseEnterpriseInfo.setRegistrationAuthority(regUnitInfo.getRegUnitIc().getRegisteredOrgan());
        baseEnterpriseInfo.setApprovalTime(regUnitInfo.getRegUnitIc().getApprovedDate());
        baseEnterpriseInfo.setOperatingStatus(regUnitInfo.getRegUnitIc().getBusinessState());
        baseEnterpriseInfo.setSyncDate(new Date());
        baseEnterpriseInfo.setSyncState(0);
        tzBaseEnterpriseInfoService.save(baseEnterpriseInfo);
    }

    @Override
    public RegUnitInfoDto unitCheck(String unitCode, String unitType) {
        // 1.校验重复性
        RegUnitInfo regUnitInfo = this.getOne(new LambdaQueryWrapper<RegUnitInfo>().eq(RegUnitInfo::getUnitCode, unitCode));
        if (regUnitInfo != null) {
            throw new RuntimeException("该单位已注册，请联系企业管理员！");
        }
        // 2.组织返回数据
        RegUnitInfoDto regUnitInfoDto = new RegUnitInfoDto();
        if (USE_UNIT_TYPE_CODE.equals(unitType)) {
            // 本地库有的化 就不去其他系统查询
            RegUnitIc regUnitIc = regUnitIcService.getOne(new LambdaQueryWrapper<RegUnitIc>().eq(RegUnitIc::getUnitCode, unitCode));
            regUnitInfoDto.setRegUnitIc(Bean.toModel(regUnitIc, new RegUnitIcDto()));
            if(regUnitIc == null){
                // 2.1 使用单位调用行政许可系统接口进行查询工商信息
//            MultiValueMap<String, String> headers = new HttpHeaders();
//            headers.add("header-1","v1");
//            headers.add("header-2","v2");
//            RequestEntity requestEntity = new RequestEntity(
//                    null, //body部分数据
//                    headers, //头
//                    HttpMethod.GET,//请求方法
//                    URI.create("url"));
//            ResponseEntity<JSONObject> responseEntity = restTemplate.exchange(requestEntity,JSONObject.class);
//            JSONObject result = responseEntity.getBody();
                // 2.2 工商信息组装
//            regUnitInfoDto.setRegUnitIc();
            }

        } else {
            RegUnitIc regUnitIc = regUnitIcService.getOne(new LambdaQueryWrapper<RegUnitIc>().eq(RegUnitIc::getUnitCode, unitCode));
            regUnitInfoDto.setRegUnitIc(Bean.toModel(regUnitIc, new RegUnitIcDto()));
        }
        // 2.3 许可信息组装
        List<BaseUnitLicence> unitLicences = baseUnitLicenceService.list(new LambdaQueryWrapper<BaseUnitLicence>().eq(BaseUnitLicence::getUnitCode, unitCode));
        regUnitInfoDto.setUnitLicences(Bean.toModels(unitLicences, BaseUnitLicenceDto.class));
        return regUnitInfoDto;
    }

    @Override
    public List<DataDictionary> getUnitTypeList() {
        return iDataDictionaryService.getByType(DICT_TYPE_UNIT_TYPE);
    }

    @Override
    public Collection getManagementUnitTree() {
        tzsAuthServiceImpl.setRequestContext();
        // 组织架构中单位级别为：省级、地市级、区县级的单位
        List<CompanyModel> companyModels = (List<CompanyModel>) Privilege.companyClient.queryAgencyTree(null).getResult();
        return companyModels.stream().filter(c -> "headquarter".equals(c.getLevel()) || "prefecture-level".equals(c.getLevel()) || "county".equals(c.getLevel())).map(this::dealChildCompany).collect(Collectors.toList());
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean unitLogOut(String unitCode) {
        RegUnitInfo regUnitInfo = this.getOne(new LambdaQueryWrapper<RegUnitInfo>().eq(RegUnitInfo::getUnitCode, unitCode));
        if (regUnitInfo == null) {
            return Boolean.FALSE;
        }
        try {
            tzsAuthServiceImpl.setRequestContext();
            // 1.删除已经创建的企业信息
            if (StringUtils.isNotEmpty(regUnitInfo.getAmosCompanySeq())) {
                CompanyModel companyModel = Privilege.companyClient.seleteOne(Long.parseLong(regUnitInfo.getAmosCompanySeq())).getResult();
                if (companyModel != null) {
                    Privilege.companyClient.deleteCompany(regUnitInfo.getAmosCompanySeq());
                }
            }
            // 2.删除已经创建的管理员账号
            FeignClientResult<AgencyUserModel> feignClientResult = Privilege.agencyUserClient.queryByUserId(regUnitInfo.getAdminUserId());
            if (feignClientResult != null) {
                Privilege.agencyUserClient.multDeleteUser(regUnitInfo.getAdminUserId());
            }
        } catch (Exception e) {
            log.error(e.getMessage(), e);
        }
        // 3.企业注册表删除
        this.remove(new LambdaQueryWrapper<RegUnitInfo>().eq(RegUnitInfo::getUnitCode, unitCode));
        // 4.工商信息表删除
        regUnitIcService.remove(new LambdaQueryWrapper<RegUnitIc>().eq(RegUnitIc::getUnitCode, unitCode));
        // 5.许可信息删除
        baseUnitLicenceService.remove(new LambdaQueryWrapper<BaseUnitLicence>().eq(BaseUnitLicence::getUnitCode, unitCode));
        // 6.企业数据信息删除
        tzBaseEnterpriseInfoService.remove(new LambdaQueryWrapper<TzBaseEnterpriseInfo>().eq(TzBaseEnterpriseInfo::getUseCode, unitCode));
        // 7.机场单位表信息删除
        iOrgUsrService.remove(new LambdaQueryWrapper<OrgUsr>().eq(OrgUsr::getAmosOrgId, regUnitInfo.getAmosCompanySeq()));
        return Boolean.TRUE;
    }

    @Override
    public Boolean checkRepeatAccount(String userName) {
        return this.count(new LambdaQueryWrapper<RegUnitInfo>().eq(RegUnitInfo::getAdminLoginName,userName)) > 0;
    }

    @Override
    public Boolean checkRepeatPhone(String phoneNo) {
        return this.count(new LambdaQueryWrapper<RegUnitInfo>().eq(RegUnitInfo::getAdminTel,phoneNo)) > 0;
    }

    private CompanyModel dealChildCompany(CompanyModel cm) {
        cm.setChildren(this.getFilterChild(cm.getChildren() != null ? cm.getChildren() : new ArrayList()));
        cm.getChildren().stream().filter(n -> {
            CompanyModel c = JSONObject.parseObject(JSON.toJSONString(n), CompanyModel.class);
            return "headquarter".equals(c.getLevel()) || "prefecture-level".equals(c.getLevel()) || "county".equals(c.getLevel());
        }).map(n -> {
            CompanyModel c = JSONObject.parseObject(JSON.toJSONString(n), CompanyModel.class);
            return dealChildCompany(c);
        }).collect(Collectors.toList());
        return cm;
    }

    private List getFilterChild(Collection children) {
        return (List) children.stream().filter(n -> {
            CompanyModel c = JSONObject.parseObject(JSON.toJSONString(n), CompanyModel.class);
            return "headquarter".equals(c.getLevel()) || "prefecture-level".equals(c.getLevel()) || "county".equals(c.getLevel());
        }).map(s -> {
            CompanyModel c = JSONObject.parseObject(JSON.toJSONString(s), CompanyModel.class);
            c.setChildren(this.getFilterChild(c.getChildren() != null ? c.getChildren() : new ArrayList()));
            return c;
        }).collect(Collectors.toList());
    }

    private void createCompanyAndUser(RegUnitInfo 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;
            List<Long> roleIds = new ArrayList<>();
            Set<String> roleNameSet = new HashSet<>();
            // 3.1创建公司
            companyInfo.setAddress(dealNull2EmptyString(regUnitInfo.getProvince()) + dealNull2EmptyString(regUnitInfo.getCity()) + dealNull2EmptyString(regUnitInfo.getDistrict()) + dealNull2EmptyString(regUnitInfo.getStree()) + dealNull2EmptyString(regUnitInfo.getCommunity()) + dealNull2EmptyString(regUnitInfo.getAddress()));
            companyInfo.setAgencyCode("tzs");
            companyInfo.setParentId(Long.parseLong(regUnitInfo.getManagementUnitId()));
            companyInfo.setLevel("company");
            companyInfo.setCompanyName(regUnitInfo.getName());
            companyInfo.setCompanyCode(regUnitInfo.getUnitCode());
            companyInfo.setContact(regUnitInfo.getLegalPerson());
            companyInfo.setLandlinePhone(regUnitInfo.getLegalPersonTel());
            FeignClientResult<CompanyModel> companyResult = Privilege.companyClient.create(companyInfo);
            if (companyResult == null || companyResult.getResult() == null) {
                throw new BadRequest("单位注册失败");
            }
            String adminUserName = regUnitInfo.getAdminName();
            String loginName = regUnitInfo.getAdminLoginName();
            String pwd = regUnitInfo.getAdminLoginPwd();
            String adminTel = regUnitInfo.getAdminTel();
            // 3.2 创建平台用户
            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);
            String unitTypeCode = regUnitInfo.getUnitTypeCode();
            // 根据unitTypeCode 获取应用和角色 数据字典配置
            DataDictionary unitType = iDataDictionaryService.getOne(new LambdaQueryWrapper<DataDictionary>().eq(DataDictionary::getCode, unitTypeCode));
            String appCode = unitType.getTypeDesc() != null ? unitType.getTypeDesc() : "";
            String[] appCodes = appCode.split(",");
            Set<String> appCodesSet = new HashSet<>();
            Collections.addAll(appCodesSet, appCodes);
            Map<Long, List<Long>> roleSeqMap = new HashMap<>();
            roleNameSet.add(unitType.getName());
            userRoleList = allRoleList.stream().filter(r -> r.getRoleName().equals(unitType.getName())).collect(Collectors.toList());
            userRoleList.forEach(r -> roleIds.add(r.getSequenceNbr()));
            roleSeqMap.put(companyInfo.getSequenceNbr(), roleIds);
            Map<Long, List<RoleModel>> orgRoles = new HashMap<>();
            orgRoles.put(companyInfo.getSequenceNbr(), userRoleList);
            agencyUserModel.setAppCodes(new ArrayList<>(appCodesSet));
            agencyUserModel.setOrgRoles(orgRoles);
            agencyUserModel.setOrgRoleSeqs(roleSeqMap);
            userResult = Privilege.agencyUserClient.create(agencyUserModel);
            if (userResult == null || userResult.getResult() == null) {
                throw new BadRequest("单位注册失败");
            }
            regUnitInfo.setAdminUserId(userResult.getResult().getUserId());
            regUnitInfo.setAmosCompanySeq(companyInfo.getSequenceNbr().toString());
            // 3.3 org_user 创建组织机构
            OrgUsr org = new OrgUsr();
            org.setBizOrgCode(TreeParser.genTreeCode());
            org.setBizOrgType(CommonConstant.BIZ_ORG_TYPE_COMPANY);
            org.setBizOrgName(regUnitInfo.getName());
            org.setRecDate(new Date());
            org.setRecUserId(userResult.getResult().getUserId());
            org.setRecUserName(userResult.getResult().getUserName());
            org.setAmosOrgId(companyInfo.getSequenceNbr() + "");
            org.setAmosOrgCode(companyInfo.getOrgCode());
            iOrgUsrService.save(org);
        } 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());
        }
    }

    private String dealNull2EmptyString( String t){
        return StringUtils.isEmpty(t) ? "" : t;
    }
}