package com.liquidnet.service.merchant.service.impl;

import com.fasterxml.jackson.databind.JsonNode;
import com.liquidnet.common.exception.LiquidnetServiceException;
import com.liquidnet.commons.lang.util.CollectionUtil;
import com.liquidnet.commons.lang.util.IDGenerator;
import com.liquidnet.commons.lang.util.IdentityUtils;
import com.liquidnet.commons.lang.util.JsonUtils;
import com.liquidnet.service.base.ErrorMapping;
import com.liquidnet.service.base.PagedResult;
import com.liquidnet.service.base.SqlMapping;
import com.liquidnet.service.base.constant.MQConst;
import com.liquidnet.service.merchant.dto.param.MerchantSponsorApplyParam;
import com.liquidnet.service.merchant.dto.vo.MerchantSponsorAppliesVo;
import com.liquidnet.service.merchant.dto.vo.MerchantSponsorsVo;
import com.liquidnet.service.merchant.service.IMerchantSponsorsService;
import com.liquidnet.service.merchant.service.MerchantRdmService;
import com.liquidnet.service.merchant.util.ObjectUtil;
import com.liquidnet.service.merchant.util.QueueUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.time.LocalDateTime;
import java.util.LinkedList;
import java.util.List;
import java.util.regex.Pattern;
import java.util.stream.IntStream;

@Slf4j
@Service
public class MerchantSponsorsServiceImpl implements IMerchantSponsorsService {
    @Autowired
    MerchantRdmService merchantRdmService;

    @Autowired
    private MongoTemplate mongoTemplate;

    @Autowired
    QueueUtil queueUtils;

    @Override
    public PagedResult<MerchantSponsorsVo> search(String name, int page, int size) {
        // 查询条件
        Query query = new Query();
        String regex = String.format("%s%s%s", "^.*", name, ".*$");
        Pattern pattern = Pattern.compile(regex, Pattern.CASE_INSENSITIVE);
        query.addCriteria(Criteria.where("name").regex(pattern));
        query.addCriteria(Criteria.where("isOnline").is(1));

        // 总数
        long count = mongoTemplate.count(query, MerchantSponsorsVo.class, MerchantSponsorsVo.class.getSimpleName());

        // 分页
        PagedResult<MerchantSponsorsVo> pagedResult = ObjectUtil.getMerchantSponsorsVoPagedResult();
        if (count > 0) {
            query.fields().include("sponsorId").include("isOnline").include("name").include("uid");

            // 查询分页
            Pageable pageable = PageRequest.of(page - 1, size, Sort.by(Sort.Direction.DESC, "createdAt"));
            query.with(pageable);
            List<MerchantSponsorsVo> sponsorsVoList = mongoTemplate.find(query, MerchantSponsorsVo.class, MerchantSponsorsVo.class.getSimpleName());

            pagedResult.setList(sponsorsVoList).setTotal(count, size);
        }

        return pagedResult;
    }

    @Override
    public String apply(String uid, MerchantSponsorApplyParam parameter) {
        LinkedList<String> toMqSqls = CollectionUtil.linkedListString();
        LinkedList<Object[]> sponsorApplyInsertObjs = CollectionUtil.linkedListObjectArr();

        // 申请主办 vos 上限
        List<MerchantSponsorAppliesVo> sponsorAppliesVos = merchantRdmService.getSponsorAppliesVosByUid(uid);
        if (!CollectionUtils.isEmpty(sponsorAppliesVos)) {
            if (sponsorAppliesVos.size() >= 10) {
                ErrorMapping.ErrorMessage errorMessage = ErrorMapping.get("13201");
                throw new LiquidnetServiceException(errorMessage.getCode(), errorMessage.getMessage());
            }
        }

        LocalDateTime now = LocalDateTime.now();

        // 申请主办 vo
        MerchantSponsorAppliesVo sponsorAppliesVo = MerchantSponsorAppliesVo.getNew();
        BeanUtils.copyProperties(parameter, sponsorAppliesVo);
        sponsorAppliesVo.setSponsorApplyId(IDGenerator.nextSnowId());
        sponsorAppliesVo.setApplyStatus(0);
        sponsorAppliesVo.setApplyType("create");
        sponsorAppliesVo.setReject("");
        sponsorAppliesVo.setUid(uid);
        sponsorAppliesVo.setCreatedAt(now);
        if (parameter.getSkipCompany() < 1) {
            sponsorAppliesVo.setCompanyName("");
            sponsorAppliesVo.setLicenseCode("");
            sponsorAppliesVo.setLicenseImg("");
            sponsorAppliesVo.setLegalName("");
            sponsorAppliesVo.setLegalIdentity("");
            sponsorAppliesVo.setLegalIdentityObverse("");
            sponsorAppliesVo.setLegalIdentityReverse("");
        } else {
            if (sponsorAppliesVo.getCompanyName().isEmpty()
                    || sponsorAppliesVo.getLicenseCode().isEmpty()
                    || sponsorAppliesVo.getLicenseImg().isEmpty()
                    || sponsorAppliesVo.getLegalName().isEmpty()
                    || sponsorAppliesVo.getLegalIdentity().isEmpty()
                    || sponsorAppliesVo.getLegalIdentityObverse().isEmpty()
                    || sponsorAppliesVo.getLegalIdentityReverse().isEmpty()) {
                ErrorMapping.ErrorMessage errorMessage = ErrorMapping.get("13202");
                throw new LiquidnetServiceException(errorMessage.getCode(), errorMessage.getMessage());
            }

            // 身份证检查
//            String respStr = IdentityUtils.aliThird(sponsorAppliesVo.getLegalName(), sponsorAppliesVo.getLegalIdentity());;
//            JsonNode respJNode = JsonUtils.fromJson(respStr, JsonNode.class);
//            if (null == respJNode || !"0".equals(respJNode.get("error_code").asText())) {
//                log.info("###法人实名认证失败[{}]", respStr);
//                ErrorMapping.ErrorMessage errorMessage = ErrorMapping.get("13001");
//                throw new LiquidnetServiceException(errorMessage.getCode(), errorMessage.getMessage());
//            }
        }

        // 身份证检查
//        String respStr = IdentityUtils.aliThird(sponsorAppliesVo.getContactName(), sponsorAppliesVo.getContactIdentity());;
//        JsonNode respJNode = JsonUtils.fromJson(respStr, JsonNode.class);
//        if (null == respJNode || !"0".equals(respJNode.get("error_code").asText())) {
//            log.info("###联系人实名认证失败[{}]", respStr);
//            ErrorMapping.ErrorMessage errorMessage = ErrorMapping.get("13002");
//            throw new LiquidnetServiceException(errorMessage.getCode(), errorMessage.getMessage());
//        }

        // 申请主办 redis
        long s = System.currentTimeMillis();
        merchantRdmService.addSponsorAppliesVoByUid(uid, sponsorAppliesVos, sponsorAppliesVo);
        log.debug("#RDS耗时:{}ms", System.currentTimeMillis() - s);

        // 申请主办 sql
        toMqSqls.add(SqlMapping.get("merchant_sponsor_applies.insert"));
        sponsorApplyInsertObjs.add(new Object[]{
                sponsorAppliesVo.getSponsorApplyId(), sponsorAppliesVo.getApplyStatus(), sponsorAppliesVo.getApplyType(), sponsorAppliesVo.getReject(), sponsorAppliesVo.getUid(),
                sponsorAppliesVo.getName(), sponsorAppliesVo.getLogo(), sponsorAppliesVo.getBackground(), sponsorAppliesVo.getDescription(),
                sponsorAppliesVo.getContactName(), sponsorAppliesVo.getContactIdentity(), sponsorAppliesVo.getContactIdentityObverse(), sponsorAppliesVo.getContactIdentityReverse(), sponsorAppliesVo.getContactEmail(),
                sponsorAppliesVo.getCompanyName(), sponsorAppliesVo.getLicenseCode(), sponsorAppliesVo.getLicenseImg(),
                sponsorAppliesVo.getLegalName(), sponsorAppliesVo.getLegalIdentity(), sponsorAppliesVo.getLegalIdentityObverse(), sponsorAppliesVo.getLegalIdentityReverse(), sponsorAppliesVo.getCreatedAt()
        });

        // mq
        s = System.currentTimeMillis();
        queueUtils.sendMsgByRedis(
                MQConst.MerchantQueue.SQL_MERCHANT_SPONSOR.getKey(),
                SqlMapping.gets(toMqSqls, sponsorApplyInsertObjs)
        );
        log.debug("#MQ耗时:{}ms", System.currentTimeMillis() - s);

        return sponsorAppliesVo.getSponsorApplyId();
    }

    @Override
    public void applyDel(String uid, String sponsorApplyId) {
        // 查找场地申请，是否存在且已经驳回
        List<MerchantSponsorAppliesVo> sponsorAppliesVos = merchantRdmService.getSponsorAppliesVosByUid(uid);
        if (CollectionUtils.isEmpty(sponsorAppliesVos)) {
            ErrorMapping.ErrorMessage errorMessage = ErrorMapping.get("13203");
            throw new LiquidnetServiceException(errorMessage.getCode(), errorMessage.getMessage());
        }
        int idx = IntStream.range(0, sponsorAppliesVos.size())
                .filter(i -> sponsorAppliesVos.get(i).getSponsorApplyId().equals(sponsorApplyId))
                .findFirst()
                .orElse(-1);
        if (idx < 0) {
            ErrorMapping.ErrorMessage errorMessage = ErrorMapping.get("13203");
            throw new LiquidnetServiceException(errorMessage.getCode(), errorMessage.getMessage());
        }
        MerchantSponsorAppliesVo sponsorAppliesVo = sponsorAppliesVos.get(idx);
        if (sponsorAppliesVo.getApplyStatus() != 2) {
            ErrorMapping.ErrorMessage errorMessage = ErrorMapping.get("13204");
            throw new LiquidnetServiceException(errorMessage.getCode(), errorMessage.getMessage());
        }

        LocalDateTime now = LocalDateTime.now();
        sponsorAppliesVo.setUpdatedAt(now);
        sponsorAppliesVo.setDeletedAt(now);

        // 场地默认验票员 redis
        long s = System.currentTimeMillis();
        merchantRdmService.delSponsorAppliesVoByUid(uid, sponsorAppliesVos, sponsorAppliesVo);
        log.debug("#RDS耗时:{}ms", System.currentTimeMillis() - s);

        // 场地默认验票员 sql
        LinkedList<String> toMqSqls = CollectionUtil.linkedListString();
        LinkedList<Object[]> sponsorAppliesUpdateObjs = CollectionUtil.linkedListObjectArr();
        toMqSqls.add(SqlMapping.get("merchant_sponsor_applies.update"));
        sponsorAppliesUpdateObjs.add(new Object[]{
                sponsorAppliesVo.getUpdatedAt(), sponsorAppliesVo.getDeletedAt(), sponsorAppliesVo.getSponsorApplyId()
        });

        // mq
        s = System.currentTimeMillis();
        queueUtils.sendMsgByRedis(
                MQConst.MerchantQueue.SQL_MERCHANT_SPONSOR.getKey(),
                SqlMapping.gets(toMqSqls, sponsorAppliesUpdateObjs)
        );
        log.debug("#MQ耗时:{}ms", System.currentTimeMillis() - s);
    }

    @Override
    public MerchantSponsorAppliesVo applyInfo(String uid, String sponsorApplyId) {
        // 查找场地申请，是否存在
        List<MerchantSponsorAppliesVo> sponsorAppliesVos = merchantRdmService.getSponsorAppliesVosByUid(uid);
        if (CollectionUtils.isEmpty(sponsorAppliesVos)) {
            ErrorMapping.ErrorMessage errorMessage = ErrorMapping.get("13203");
            throw new LiquidnetServiceException(errorMessage.getCode(), errorMessage.getMessage());
        }
        int idx = IntStream.range(0, sponsorAppliesVos.size())
                .filter(i -> sponsorAppliesVos.get(i).getSponsorApplyId().equals(sponsorApplyId))
                .findFirst()
                .orElse(-1);
        if (idx < 0) {
            ErrorMapping.ErrorMessage errorMessage = ErrorMapping.get("13203");
            throw new LiquidnetServiceException(errorMessage.getCode(), errorMessage.getMessage());
        }

        return sponsorAppliesVos.get(idx);
    }
}
