package com.liquidnet.service.platform.service.impl.kylin;

import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.fasterxml.jackson.core.type.TypeReference;
import com.liquidnet.common.cache.redis.util.RedisDataSourceUtil;
import com.liquidnet.commons.lang.util.*;
import com.liquidnet.service.adam.dto.vo.AdamUserInfoVo;
import com.liquidnet.service.base.ResponseDto;
import com.liquidnet.service.kylin.dto.param.PerformancePartnerVo;
import com.liquidnet.service.kylin.dto.vo.mongo.KylinPerformanceVo;
import com.liquidnet.service.kylin.entity.KylinPerformanceRelations;
import com.liquidnet.service.kylin.mapper.*;
import com.liquidnet.service.slime.constant.SlimeAuthorizationConst;
import com.liquidnet.service.slime.constant.SlimeRedisConst;
import com.liquidnet.service.slime.dto.param.SlimeAuthorizationPermissionParam;
import com.liquidnet.service.slime.dto.vo.*;
import com.liquidnet.service.slime.entity.*;
import com.liquidnet.service.slime.mapper.*;
import com.liquidnet.service.platform.utils.ObjectUtil;
import com.mongodb.BasicDBObject;
import com.mysql.cj.jdbc.result.ResultSetImpl;
import lombok.extern.slf4j.Slf4j;
import org.bson.Document;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.convert.MongoConverter;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.data.mongodb.core.query.Update;
import org.springframework.stereotype.Service;
import org.springframework.util.MultiValueMap;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;

@Service
@Slf4j
public class DataImpl {

    @Value("${liquidnet.service.adam.url}")
    private String adamUrl;

    @Autowired
    private MongoTemplate mongoTemplate;
    @Autowired
    private MongoConverter mongoConverter;
    @Autowired
    private RedisDataSourceUtil redisDataSourceUtil;
    @Autowired
    SlimeFieldsMapper slimeFieldsMapper;
    @Autowired
    SlimeFieldAppliesMapper slimeFieldAppliesMapper;
    @Autowired
    SlimeSponsorsMapper slimeSponsorsMapper;
    @Autowired
    SlimeSponsorAppliesMapper slimeSponsorAppliesMapper;
    @Autowired
    KylinPerformanceRelationsMapper kylinPerformanceRelationsMapper;
    @Autowired
    DMTAuthorizationPermissionService dmtAuthorizationPermissionService;
    @Autowired
    DMTAuthorizationRecordsService dmtAuthorizationRecordsService;


    private static final String SQL_URL = "jdbc:mysql://39.107.71.112:3308/test_ln_scene";
    private static final String SQL_USER = "testmall";
    private static final String SQL_PWD = "zhengzai!mYT";
    private static final String PHP_DB = "testmall";

    //迁移场地和场地认领关系
    public void fieldData() {
        try {
            String sql = "select mf.id                                                   AS 'field_id',\n" +
                    "       1                                                       AS 'is_online',\n" +
                    "       0                                                       AS 'is_check',\n" +
                    "       mf.`name`                                               AS 'name',\n" +
                    "       ''                                                      AS 'logo',\n" +
                    "       IF(LEFT(mf.cover_img, 4) = 'http', mf.cover_img, '')    AS 'background',\n" +
                    "       IF(ISNULL(mf.description), '', mf.description)          AS 'description',\n" +
                    "       NULL                                                    AS 'built_date',\n" +
                    "       mf.province_id                                          AS 'province_id',\n" +
                    "       mf.province_name                                        AS 'province_name',\n" +
                    "       mf.city_id                                              AS 'city_id',\n" +
                    "       mf.city_name                                            AS 'city_name',\n" +
                    "       IF(mf.ad_code > 7000, mf.ad_code, '')                   AS 'district_id',\n" +
                    "       mf.district_name                                        AS 'district_name',\n" +
                    "       mf.address                                              AS 'address',\n" +
                    "       mf.longitude                                            AS 'longitude',\n" +
                    "       mf.latitude                                             AS 'latitude',\n" +
                    "       mm.`name`                                               AS 'contact_name',\n" +
                    "       mm.mobile                                               AS 'contact_mobile',\n" +
                    "       mm.email                                                AS 'contact_email',\n" +
                    "       ''                                                      AS 'company_id',\n" +
                    "       IF(ISNULL(mf.created_at), mf.updated_at, mf.created_at) AS 'created_at',\n" +
                    "       mf.updated_at                                           AS 'updated_at',\n" +
                    "       mf.admin_id,\n" +
                    "       mm.name,\n" +
                    "       mm.email,\n" +
                    "       mmd.enterprise_name,\n" +
                    "       mmd.business_license,\n" +
                    "       mmd.business_license_img,\n" +
                    "       mmd.legal_person,\n" +
                    "       mmd.identity_card,\n" +
                    "       mmd.identity_card_img_front,\n" +
                    "       mmd.identity_card_img_back,\n" +
                    "       kpr.performance_id\n" +
                    "from kylin_performances as kp\n" +
                    "         inner join kylin_performance_relations as kpr on kpr.performance_id = kp.performances_id\n" +
                    "         inner join " + PHP_DB + ".fields as mf on mf.id = kpr.field_id\n" +
                    "         left join " + PHP_DB + ".merchants as mm on mm.id = mf.admin_id\n" +
                    "         left join " + PHP_DB + ".merchant_details as mmd on mmd.merchant_id = mf.admin_id\n" +
                    "group by field_id";
            Connection connection = DriverManager.getConnection(SQL_URL, SQL_USER, SQL_PWD);
            //查询数据
            PreparedStatement preparedStatement = connection.prepareStatement(sql);
            ResultSetImpl row = (ResultSetImpl) preparedStatement.executeQuery();
            //数据迁移
            while (row.next()) {
                SlimeFields fields = new SlimeFields();
                fields.setFieldId(row.getString("field_id"));
                fields.setIsOnline(row.getInt("is_online"));
                String contactMobile = row.getString("contact_mobile");
                //判断场地认领逻辑
                if (null != contactMobile && !contactMobile.isEmpty()) {
                    if (contactMobile.equals("15810312145")) {
                        contactMobile = "15810579150";
                    }
                    MultiValueMap<String, String> params = CollectionUtil.linkedMultiValueMapStringString();
                    params.add("mobile", contactMobile);
                    MultiValueMap<String, String> headers = CollectionUtil.linkedMultiValueMapStringString();
                    headers.add("Accept", "application/json;charset=UTF-8");
                    String returnData = HttpUtil.post(adamUrl.concat("/adam/rsc/reg/mobile"), params, headers);
                    AdamUserInfoVo adamUserInfoVo = JsonUtils.fromJson(returnData, new TypeReference<ResponseDto<AdamUserInfoVo>>() {
                    }).getData();
                    String uid = adamUserInfoVo.getUid();
                    fields.setClaimStatus(1);
                    fields.setUid(uid);
                } else {
                    fields.setClaimStatus(0);
                    fields.setUid("");
                }
                //完成
                fields.setIsCheck(row.getInt("is_check"));
                fields.setName(row.getString("name"));
                fields.setLogo(row.getString("logo"));
                fields.setBackground(row.getString("background").contains(".") ? row.getString("background") : "");
                fields.setDescription("空".equals(row.getString("description")) ? "" : row.getString("description"));
                fields.setBuiltDate(null != row.getDate("built_date") ? row.getDate("built_date").toLocalDate() : null);
                fields.setProvinceId(row.getString("province_id"));
                fields.setProvinceName(row.getString("province_name"));
                fields.setCityId(row.getString("city_id"));
                fields.setCityName(row.getString("city_name"));
                fields.setDistrictId(row.getString("district_id"));
                fields.setDistrictName(row.getString("district_name"));
                fields.setAddress(null != row.getString("address") ? row.getString("address") : "");
                fields.setLongitude(row.getString("longitude").contains(".") ? row.getString("longitude") : "");
                fields.setLatitude(row.getString("latitude").contains(".") ? row.getString("latitude") : "");
                fields.setContactName(null != row.getString("contact_name") ? row.getString("contact_name") : "");
                fields.setContactEmail(null != row.getString("contact_email") ? row.getString("contact_email") : "");
                fields.setCompanyId(row.getString("company_id"));
                fields.setCreatedAt(row.getTimestamp("created_at").toLocalDateTime());
                fields.setUpdatedAt(row.getTimestamp("updated_at").toLocalDateTime());
                SlimeFieldsVo vo = SlimeFieldsVo.getNew().copy(fields);

                SlimeFieldApplies applies = new SlimeFieldApplies();
                SlimeFieldAppliesVo appliesVo = null;
                if (fields.getClaimStatus() != 0) {
                    applies.setFieldApplyId(IDGenerator.nextSnowId());
                    applies.setApplyStatus(1);
                    applies.setUid(fields.getUid());
                    applies.setFieldId(fields.getFieldId());
                    applies.setName(fields.getName());
                    applies.setLogo(fields.getLogo());
                    applies.setBackground(fields.getBackground());
                    applies.setDescription(fields.getDescription());
                    applies.setBuiltDate(fields.getBuiltDate());
                    applies.setProvinceId(fields.getProvinceId());
                    applies.setProvinceName(fields.getProvinceName());
                    applies.setCityId(fields.getCityId());
                    applies.setCityName(fields.getCityName());
                    applies.setDistrictId(fields.getDistrictId());
                    applies.setDistrictName(fields.getDistrictName());
                    applies.setAddress(fields.getAddress());
                    applies.setLongitude(fields.getLongitude());
                    applies.setLatitude(fields.getLatitude());
                    if (row.getInt("admin_id") == 0) {
                        applies.setApplyType("create");
                    } else {
                        applies.setApplyType("claim");
                        applies.setContactName(row.getString("name"));
                        applies.setContactEmail(row.getString("email"));
                        applies.setCompanyName(row.getString("enterprise_name"));
                        applies.setLicenseCode(row.getString("business_license"));
                        applies.setLicenseImg(row.getString("business_license_img"));
                        applies.setLegalName(row.getString("legal_person"));
                        applies.setLegalIdentity(row.getString("identity_card"));
                        applies.setLegalIdentityObverse(row.getString("identity_card_img_front"));
                        applies.setLegalIdentityReverse(row.getString("identity_card_img_back"));
                    }
                    applies.setCreatedAt(LocalDateTime.now());
                    appliesVo = SlimeFieldAppliesVo.getNew().copy(applies);
                }
                //MYSQL
                slimeFieldsMapper.delete(Wrappers.lambdaQuery(SlimeFields.class).eq(SlimeFields::getFieldId, fields.getFieldId()));
                slimeFieldsMapper.insert(fields);
                if (fields.getClaimStatus() != 0) {
                    slimeFieldAppliesMapper.delete(Wrappers.lambdaQuery(SlimeFieldApplies.class).eq(SlimeFieldApplies::getFieldId, applies.getFieldId()));
                    slimeFieldAppliesMapper.insert(applies);
                }
                //OTHER
                judgeFields(fields.getFieldId(), fields.getUid(), appliesVo, vo);
                //场地权限
                if (!fields.getUid().equals("")) {
                    initPermission("field", null, row.getString("performance_id"), fields.getUid(), null, null, null);
                }
            }
            row.close();
            preparedStatement.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    //演出所属账号修改
    public void account() {
        try {
            String sql = "select merchant_id, mm.mobile,  kp.performances_id ,kps.audit_status\n" +
                    "from kylin_performances kp\n" +
                    "         inner join kylin_performance_relations kpr on kpr.performance_id = kp.performances_id\n" +
                    "         inner join kylin_performance_status kps on kps.performance_id = kp.performances_id\n"+
                    "         left join " + PHP_DB + ".merchants mm on mm.id = kpr.merchant_id";
            Connection connection = DriverManager.getConnection(SQL_URL, SQL_USER, SQL_PWD);
            //查询数据
            PreparedStatement preparedStatement = connection.prepareStatement(sql);
            ResultSetImpl row = (ResultSetImpl) preparedStatement.executeQuery();
            //数据迁移
            while (row.next()) {
                String mobile = row.getString("mobile");
                String merchantId = row.getString("merchant_id");
                String performancesId = row.getString("performances_id");
                String auditStatus = row.getString("audit_status");
                if (mobile == null) {
                    continue;
                } else {
                    if (mobile.equals("15810312145")) {
                        mobile = "15810579150";
                    }
                }
                //获取java用户id
                MultiValueMap<String, String> params = CollectionUtil.linkedMultiValueMapStringString();
                params.add("mobile", mobile);
                MultiValueMap<String, String> headers = CollectionUtil.linkedMultiValueMapStringString();
                headers.add("Accept", "application/json;charset=UTF-8");
                String returnData = HttpUtil.post(adamUrl.concat("/adam/rsc/reg/mobile"), params, headers);
                AdamUserInfoVo adamUserInfoVo = JsonUtils.fromJson(returnData, new TypeReference<ResponseDto<AdamUserInfoVo>>() {
                }).getData();
                String uid = adamUserInfoVo.getUid();
                KylinPerformanceRelations kylinPerformanceRelations = KylinPerformanceRelations.getNew();
                kylinPerformanceRelations.setMerchantId(uid);
                kylinPerformanceRelationsMapper.update(kylinPerformanceRelations,
                        Wrappers.lambdaUpdate(KylinPerformanceRelations.class).eq(KylinPerformanceRelations::getMerchantId, merchantId).eq(KylinPerformanceRelations::getPerformanceId,performancesId));

                HashMap<String, Object> map = CollectionUtil.mapStringObject();
                map.put("merchantId", uid);
                map.put("auditStatus",auditStatus);
                //修改vo
                Query voQuery = Query.query(Criteria.where("performancesId").is(performancesId));
                BasicDBObject objectVo = ObjectUtil.cloneBasicDBObject().append("$set", mongoConverter.convertToMongoType(map));
                mongoTemplate.getCollection(KylinPerformanceVo.class.getSimpleName()).updateOne(
                        voQuery.getQueryObject(),
                        objectVo
                );
                //修改partnerVo
//                Query partnerVoQuery = Query.query(Criteria.where("merchantId").is(merchantId).and("performancesId").is(performancesId));
//                BasicDBObject objectPartnerVo = ObjectUtil.cloneBasicDBObject().append("$set", mongoConverter.convertToMongoType(map));
                mongoTemplate.getCollection(PerformancePartnerVo.class.getSimpleName()).updateOne(
                        voQuery.getQueryObject(),
                        objectVo
                );
                initPermission("sponsor", uid, row.getString("performances_id"), null, null, null, null);
            }
            row.close();
            preparedStatement.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    //演出主办
    public void sponsor() {
        try {
            String sql = "select sponsor_id,sponsor_type from kylin_performances kp\n" +
                    "inner join kylin_performance_status kps on kps.performance_id = kp.performances_id\n" +
                    "where status >=3 and sponsor_id != ''\n" +
                    "group by sponsor_id,sponsor_type;";
            Connection connection = DriverManager.getConnection(SQL_URL, SQL_USER, SQL_PWD);
            //查询数据
            PreparedStatement preparedStatement = connection.prepareStatement(sql);
            ResultSetImpl row = (ResultSetImpl) preparedStatement.executeQuery();
            //数据迁移
            while (row.next()) {
                String sponsorId = row.getString("sponsor_id");
                String sponsorType = row.getString("sponsor_type");
                String sponsorSql = "";
                if (sponsorType.equals("brand")) {
                    sponsorSql = "select b.name,m.id,m.email,m.mobile,m.name as 'merchant_name',md.enterprise_name,md.business_license,md.business_license_img,md.enterprise_name,md.legal_person,md.identity_card,md.identity_card_img_front,md.identity_card_img_back\n" +
                            "from testmall.brands b inner join testmall.merchants m on m.id=b.admin_id inner join testmall.merchant_details md on md.merchant_id = m.id where b.id =" + sponsorId;
                } else if (sponsorType.equals("field")) {
                    sponsorSql = "select mu.name,m.id,m.mobile,m.name as 'merchant_name',md.enterprise_name,md.business_license,md.business_license_img,md.enterprise_name,md.legal_person,md.identity_card,md.identity_card_img_front,md.identity_card_img_back\n" +
                            "from testmall.brands b inner join testmall.merchants m on m.id=b.admin_id inner join testmall.merchant_details md on md.merchant_id = m.id where b.id =" + sponsorId;
                } else if (sponsorType.equals("musician")) {
                    sponsorSql = "select f.name,m.id,m.mobile,m.name as 'merchant_name',md.enterprise_name,md.business_license,md.business_license_img,md.enterprise_name,md.legal_person,md.identity_card,md.identity_card_img_front,md.identity_card_img_back\n" +
                            "from testmall.brands b inner join testmall.merchants m on m.id=b.admin_id inner join testmall.merchant_details md on md.merchant_id = m.id where b.id =" + sponsorId;
                }
                if (sponsorSql.equals("")) {
                    continue;
                }
                PreparedStatement preparedStatementSponsor = connection.prepareStatement(sponsorSql);
                ResultSetImpl rowSponsor = (ResultSetImpl) preparedStatementSponsor.executeQuery();
                while (rowSponsor.next()) {
                    SlimeSponsors sponsors = new SlimeSponsors();
                    sponsors.setSponsorId(IDGenerator.nextSnowId());
                    sponsors.setIsOnline(1);
                    String contactMobile = rowSponsor.getString("mobile");
                    //判断场地认领逻辑
                    if (null != contactMobile && !contactMobile.isEmpty()) {
                        if (contactMobile.equals("15810312145")) {
                            contactMobile = "15810579150";
                        }
                        MultiValueMap<String, String> params = CollectionUtil.linkedMultiValueMapStringString();
                        params.add("mobile", contactMobile);
                        MultiValueMap<String, String> headers = CollectionUtil.linkedMultiValueMapStringString();
                        headers.add("Accept", "application/json;charset=UTF-8");
                        String returnData = HttpUtil.post(adamUrl.concat("/adam/rsc/reg/mobile"), params, headers);
                        AdamUserInfoVo adamUserInfoVo = JsonUtils.fromJson(returnData, new TypeReference<ResponseDto<AdamUserInfoVo>>() {
                        }).getData();
                        String uid = adamUserInfoVo.getUid();
                        sponsors.setUid(uid);
                    } else {
                        sponsors.setUid("");
                    }
                    sponsors.setName(rowSponsor.getString("name"));
                    sponsors.setContactName(rowSponsor.getString("merchant_name"));
                    sponsors.setContactEmail(rowSponsor.getString("email"));
                    sponsors.setCreatedAt(LocalDateTime.now());
                    SlimeSponsorsVo vo = SlimeSponsorsVo.getNew().copy(sponsors);

                    SlimeSponsorApplies sponsorApplies = new SlimeSponsorApplies();
                    sponsorApplies.setSponsorApplyId(IDGenerator.nextSnowId());
                    sponsorApplies.setSponsorId(sponsors.getSponsorId());
                    sponsorApplies.setApplyStatus(1);
                    sponsorApplies.setApplyType("create");
                    sponsorApplies.setUid(sponsors.getUid());
                    sponsorApplies.setName(rowSponsor.getString("merchant_name"));
                    sponsorApplies.setContactEmail(sponsors.getContactEmail());
                    sponsorApplies.setLicenseCode(rowSponsor.getString("business_license"));
                    sponsorApplies.setLicenseImg(rowSponsor.getString("business_license_img"));
                    sponsorApplies.setCompanyName(rowSponsor.getString("enterprise_name"));
                    sponsorApplies.setLegalName(rowSponsor.getString("legal_person"));
                    sponsorApplies.setLegalIdentity(rowSponsor.getString("identity_card"));
                    sponsorApplies.setLegalIdentityObverse(rowSponsor.getString("identity_card_img_front"));
                    sponsorApplies.setLegalIdentityReverse(rowSponsor.getString("identity_card_img_back"));
                    sponsorApplies.setCreatedAt(sponsors.getCreatedAt());
                    SlimeSponsorAppliesVo sponsorAppliesVo = SlimeSponsorAppliesVo.getNew().copy(sponsorApplies);

                    //MYSQL
                    slimeSponsorsMapper.delete(Wrappers.lambdaQuery(SlimeSponsors.class).eq(SlimeSponsors::getSponsorId, sponsors.getSponsorId()));
                    slimeSponsorsMapper.insert(sponsors);
                    slimeSponsorAppliesMapper.delete(Wrappers.lambdaQuery(SlimeSponsorApplies.class).eq(SlimeSponsorApplies::getSponsorId, sponsorApplies.getSponsorId()));
                    slimeSponsorAppliesMapper.insert(sponsorApplies);
                    //OTHER
                    judgeSponsor(sponsorApplies.getSponsorId(), sponsorApplies.getUid(), sponsorAppliesVo, vo);
                }

                rowSponsor.close();
                preparedStatementSponsor.close();
            }
            row.close();
            preparedStatement.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    //相关权限迁移-验票
    public void checkTicket() {
        try {
            String sql = "select kcup.performance_id,kcu.mobile,kpr.merchant_id\n" +
                    "from kylin_check_user_performances kcup\n" +
                    "         inner join kylin_check_user kcu on kcu.check_user_id = kcup.check_user_id\n" +
                    "         inner join kylin_performance_relations kpr on kpr.performance_id = kcup.performance_id\n" +
                    "order by kcup.performance_id";
            Connection connection = DriverManager.getConnection(SQL_URL, SQL_USER, SQL_PWD);
            //查询数据
            PreparedStatement preparedStatement = connection.prepareStatement(sql);
            ResultSetImpl row = (ResultSetImpl) preparedStatement.executeQuery();
            while (row.next()) {
                String mobile = row.getString("mobile");
                String merchantId = row.getString("merchant_id");
                String performanceId = row.getString("performance_id");
                if (mobile == null) {
                    continue;
                } else {
                    if (mobile.equals("15810312145")) {
                        mobile = "15810579150";
                    }
                }
                MultiValueMap<String, String> params = CollectionUtil.linkedMultiValueMapStringString();
                params.add("mobile", mobile);
                MultiValueMap<String, String> headers = CollectionUtil.linkedMultiValueMapStringString();
                headers.add("Accept", "application/json;charset=UTF-8");
                String returnData = HttpUtil.post(adamUrl.concat("/adam/rsc/reg/mobile"), params, headers);
                AdamUserInfoVo adamUserInfoVo = JsonUtils.fromJson(returnData, new TypeReference<ResponseDto<AdamUserInfoVo>>() {
                }).getData();
                initPermission("check", merchantId, performanceId, null, adamUserInfoVo.getNickname(), adamUserInfoVo.getUid(), adamUserInfoVo.getMobile());
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    private void judgeSponsor(String sponsorId, String uid, SlimeSponsorAppliesVo appliesVo, SlimeSponsorsVo vo) {
        //MerchantSponsorAppliesVo MONGO
        mongoTemplate.remove(Query.query(Criteria.where("sponsorId").is(appliesVo.getSponsorId())), SlimeSponsorAppliesVo.class, SlimeSponsorAppliesVo.class.getSimpleName());
        mongoTemplate.insert(appliesVo, SlimeSponsorAppliesVo.class.getSimpleName());
        // MerchantSponsorsVo MONGO
        Query query = Query.query(Criteria.where("sponsorId").is(sponsorId));
        Document document = (Document) mongoConverter.convertToMongoType(vo);
        Update update = Update.fromDocument(document);
        mongoTemplate.upsert(query, update, SlimeSponsorsVo.class, SlimeSponsorsVo.class.getSimpleName());

        //MerchantSponsorAppliesVo REDIS
        List<SlimeSponsorAppliesVo> vos = new ArrayList();
        vos.add(appliesVo);
        redisDataSourceUtil.getRedisKylinUtil().set(SlimeRedisConst.INFO_SPONSOR_APPLIES.concat(uid), vos);
        // MerchantSponsorsVo REDIS
        redisDataSourceUtil.getRedisKylinUtil().set(SlimeRedisConst.INFO_SPONSOR.concat(vo.getSponsorId()), vo);
    }

    private void judgeFields(String fieldId, String uid, SlimeFieldAppliesVo appliesVo, SlimeFieldsVo vo) {
        if (appliesVo != null) {
            //MerchantFieldAppliesVo MONGO
            mongoTemplate.remove(Query.query(Criteria.where("fieldId").is(appliesVo.getFieldId())), SlimeFieldAppliesVo.class, SlimeFieldAppliesVo.class.getSimpleName());
            mongoTemplate.insert(appliesVo, SlimeFieldAppliesVo.class.getSimpleName());
            //MerchantFieldAppliesVo REDIS
            Object obj = redisDataSourceUtil.getRedisKylinUtil().get(SlimeRedisConst.INFO_FIELD_APPLIES.concat(uid));
            List<SlimeFieldAppliesVo> vos;
            if (obj == null) {
                vos = new ArrayList<>();
            } else {
                vos = (List<SlimeFieldAppliesVo>) obj;
            }
            vos.add(appliesVo);
            redisDataSourceUtil.getRedisKylinUtil().set(SlimeRedisConst.INFO_FIELD_APPLIES.concat(uid), vos);
        }
        // MerchantFieldsVo MONGO
        Query query = Query.query(Criteria.where("fieldId").is(fieldId));
        Document document = (Document) mongoConverter.convertToMongoType(vo);
        Update update = Update.fromDocument(document);
        mongoTemplate.upsert(query, update, SlimeFieldsVo.class, SlimeFieldsVo.class.getSimpleName());
        // MerchantFieldsVo REDIS
        redisDataSourceUtil.getRedisKylinUtil().set(SlimeRedisConst.INFO_FIELD.concat(fieldId), vo);
    }

    private void initPermission(String type, String cuid, String performanceId, String fieldOwnId, String checkName, String checkId, String checkMobile) {
        LocalDateTime now = LocalDateTime.now();

        SlimeAuthorizationRecords records = new SlimeAuthorizationRecords();
        switch (type) {
            case "sponsor":
                records.setAuthorizationRecordId(IDGenerator.nextSnowId());
                records.setPerformanceId(performanceId);
                records.setUidRole(SlimeAuthorizationConst.PerformanceRole.CREATOR.getRole());
                records.setUid(cuid);
                records.setMobile("");
                records.setName("");
                records.setCuid("");
                records.setCuidRole("");
                records.setCreatedAt(now);
                break;
            case "field":
                records.setAuthorizationRecordId(IDGenerator.nextSnowId());
                records.setPerformanceId(performanceId);
                records.setUidRole(SlimeAuthorizationConst.PerformanceRole.FIELDER.getRole());
                records.setUid(fieldOwnId);
                records.setMobile("");
                records.setName("");
                records.setCuid("");
                records.setCuidRole("");
                records.setCreatedAt(now);
                break;
            case "check":
                records.setAuthorizationRecordId(IDGenerator.nextSnowId());
                records.setPerformanceId(performanceId);
                records.setUidRole(SlimeAuthorizationConst.PerformanceRole.CHECKER.getRole());
                records.setUid(checkId);
                records.setMobile(checkMobile);
                records.setName(checkName);
                records.setCuid(cuid);
                records.setCuidRole(SlimeAuthorizationConst.PerformanceRole.CREATOR.getRole());
                records.setCreatedAt(now);
                break;
        }

        List<SlimeAuthorizationPermissionParam> checkPermissionParam = new ArrayList();
        SlimeAuthorizationPermissionParam paramCheck = SlimeAuthorizationPermissionParam.getNew();
        paramCheck.setPermissionId(SlimeAuthorizationConst.PerformancePermission.CHECK.getId());
        SlimeAuthorizationPermissionParam paramSales = SlimeAuthorizationPermissionParam.getNew();
        paramSales.setPermissionId(SlimeAuthorizationConst.PerformancePermission.SALES.getId());
        SlimeAuthorizationPermissionParam paramGrant = SlimeAuthorizationPermissionParam.getNew();
        paramGrant.setPermissionId(SlimeAuthorizationConst.PerformancePermission.GRANT.getId());
        SlimeAuthorizationPermissionParam paramRead = SlimeAuthorizationPermissionParam.getNew();
        paramRead.setPermissionId(SlimeAuthorizationConst.PerformancePermission.READ.getId());
        SlimeAuthorizationPermissionParam paramEdit = SlimeAuthorizationPermissionParam.getNew();
        paramEdit.setPermissionId(SlimeAuthorizationConst.PerformancePermission.EDIT.getId());
        SlimeAuthorizationPermissionParam paramLine = SlimeAuthorizationPermissionParam.getNew();
        paramLine.setPermissionId(SlimeAuthorizationConst.PerformancePermission.LINE.getId());
        SlimeAuthorizationPermissionParam paramAudit = SlimeAuthorizationPermissionParam.getNew();
        paramAudit.setPermissionId(SlimeAuthorizationConst.PerformancePermission.AUDIT.getId());

        switch (type) {
            case "sponsor":
                checkPermissionParam.add(paramCheck);
                checkPermissionParam.add(paramGrant);
                checkPermissionParam.add(paramRead);
                checkPermissionParam.add(paramEdit);
                checkPermissionParam.add(paramLine);
//                checkPermissionParam.add(paramAudit);
                checkPermissionParam.add(paramSales);
                break;
            case "field":
                checkPermissionParam.add(paramCheck);
                checkPermissionParam.add(paramGrant);
                checkPermissionParam.add(paramRead);
                break;
            case "check":
                checkPermissionParam.add(paramCheck);
                checkPermissionParam.add(paramSales);
                break;
        }

        List<SlimeAuthorizationPermissions> authorizationPermissionsArrayList = new ArrayList<>();
        List<SlimeAuthorizationPermissionsVo> sponsorAuthorizationPermissionsVos = new ArrayList<>();

        for (SlimeAuthorizationPermissionParam item : checkPermissionParam) {
            SlimeAuthorizationPermissions sponsorAuthorizationPermissions = new SlimeAuthorizationPermissions();
            sponsorAuthorizationPermissions.setAuthorizationPermissionId(IDGenerator.nextSnowId());
            sponsorAuthorizationPermissions.setAuthorizationRecordId(records.getAuthorizationRecordId());
            sponsorAuthorizationPermissions.setPermissionId(item.getPermissionId());
            sponsorAuthorizationPermissions.setStartTime(now);
            sponsorAuthorizationPermissions.setEndTime(now.plusYears(10));
            sponsorAuthorizationPermissions.setCreatedAt(now);
            authorizationPermissionsArrayList.add(sponsorAuthorizationPermissions);

            SlimeAuthorizationPermissionsVo sponsorAuthorizationPermissionsVo = SlimeAuthorizationPermissionsVo.getNew();
            sponsorAuthorizationPermissionsVo.copy(sponsorAuthorizationPermissions);
            sponsorAuthorizationPermissionsVos.add(sponsorAuthorizationPermissionsVo);
        }
        // 授权记录 vo
        SlimeAuthorizationRecordsVo authorizationRecordsVo = SlimeAuthorizationRecordsVo.getNew();
        authorizationRecordsVo.copy(records);
        authorizationRecordsVo.setPermissionsVos(sponsorAuthorizationPermissionsVos);

        // mysql
        dmtAuthorizationRecordsService.save(records);
        dmtAuthorizationPermissionService.saveBatch(authorizationPermissionsArrayList);
        // mongo
        mongoTemplate.insert(authorizationRecordsVo, SlimeAuthorizationRecordsVo.class.getSimpleName());
        // updated uid
        getAndSyncAuthorizationPerformanceVo(performanceId, authorizationRecordsVo.getUid());
    }

    private SlimeAuthorizationPerformanceVo getAndSyncAuthorizationPerformanceVo(String performanceId, String uid) {
        // 聚合角色及权限
        Query recordsQuery = Query.query(Criteria.where("performanceId").is(performanceId).and("uid").is(uid).and("deletedAt").is(null));
        List<SlimeAuthorizationRecordsVo> authorizationRecordsVos = mongoTemplate.find(recordsQuery, SlimeAuthorizationRecordsVo.class, SlimeAuthorizationRecordsVo.class.getSimpleName());
        List<String> uidRoles = new ArrayList<>();
        List<String> permissionIds = new ArrayList<>();
        for (SlimeAuthorizationRecordsVo authorizationRecordsVo : authorizationRecordsVos) {
            if (!uidRoles.contains(authorizationRecordsVo.getUidRole())) {
                uidRoles.add(authorizationRecordsVo.getUidRole());
            }
            for (SlimeAuthorizationPermissionsVo authorizationPermissionsVo : authorizationRecordsVo.getPermissionsVos()) {
                if (!permissionIds.contains(authorizationPermissionsVo.getPermissionId())) {
                    permissionIds.add(authorizationPermissionsVo.getPermissionId());
                }
            }
        }
        SlimeAuthorizationPerformanceVo vo = SlimeAuthorizationPerformanceVo.getNew();
        vo.setUid(uid);
        vo.setPerformanceId(performanceId);
        vo.setUidRoles(uidRoles);
        vo.setPermissionIds(permissionIds);
        Query query = Query.query(Criteria.where("performanceId").is(performanceId).and("uid").is(uid));
        Document document = (Document) mongoConverter.convertToMongoType(vo);
        Update update = Update.fromDocument(document);
        mongoTemplate.upsert(query, update, SlimeAuthorizationPerformanceVo.class, SlimeAuthorizationPerformanceVo.class.getSimpleName());
        return vo;
    }
}
