package com.friday.custody.service.basicService.impl;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.friday.custody.service.logicService.impl.DataDictionaryBasicServiceImpl;
import com.friday.custody.service.trustService.htsc.common.HtscConstants;
import com.friday.custody.common.CustodyContants;
import com.friday.custody.dao.MjAccountBalanceInfoDao;
import com.friday.custody.entity.MjAccountBalanceInfoEntity;
import com.friday.custody.enums.RetCodeEnum;
import com.friday.custody.exception.RRException;
import com.friday.custody.req.MjAccountBalanceInfoReq;
import com.friday.custody.req.QueryDataReq;
import com.friday.custody.service.basicService.MjAccountBalanceInfoService;
import com.friday.custody.service.logicService.DataProcessService;
import com.friday.custody.utils.PageUtil;
import com.friday.custody.utils.PageUtils;
import com.friday.custody.utils.Query;
import com.friday.custody.utils.R;
import com.friday.custody.vo.MjAccountBalanceInfoVo;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 18 募集⼾银⾏账⼾余额信息表（MJAccount_balance_info）
 */
@Service("mjAccountBalanceInfoService")
@Slf4j
public class MjAccountBalanceInfoServiceImpl extends ServiceImpl<MjAccountBalanceInfoDao, MjAccountBalanceInfoEntity>
        implements MjAccountBalanceInfoService, DataProcessService<MjAccountBalanceInfoEntity> {

    @Autowired
    MjAccountBalanceInfoDao mjAccountBalanceInfoDao;
    @Autowired
    DataDictionaryBasicServiceImpl dataDictionaryBasicService;
    @Resource
    AccoBalanceChangeRecordServiceImpl accoBalanceChangeRecordService;


    @Override
    @Transactional(rollbackFor = Exception.class)
    public R saveData(String type, List<MjAccountBalanceInfoEntity> datas) {
        if (datas != null) {
            //设置主键
            datas.forEach(x -> {
                x.setUniqueKey(x.getAdmin() + x.getBankAcco());
            });
            //根据主键去重
            List<MjAccountBalanceInfoEntity> newList = datas.stream().collect(Collectors.collectingAndThen
                    (Collectors.toCollection(() -> new TreeSet<>(Comparator.comparing
                            (MjAccountBalanceInfoEntity::getUniqueKey))), ArrayList::new));
            for (MjAccountBalanceInfoEntity entity : newList) {
                try {
                    //有些托管需传时间参数, 更新一年数据 所以判断次数如果为12 则不提醒 如光大
                    if (!String.valueOf(CustodyContants.INIT_BY_MONTH_LOOP_TIME).equals(type)) {
                        //1.查询库中数据的余额 并查看是否变动
                        MjAccountBalanceInfoEntity oldEntity = baseMapper.selectOne(new QueryWrapper<MjAccountBalanceInfoEntity>()
                                .eq("unique_key", entity.getUniqueKey())
                                .eq("trust_no", entity.getTrustNo()));
                        if (oldEntity != null && oldEntity.getAccoBalance() != null
                                && entity.getAccoBalance() != null && oldEntity.getAccoBalance().compareTo(entity.getAccoBalance()) != 0) {
                            //查询出该条数据对应的产品名称,产品代码
                            Map<String, String> fundPrdMap = baseMapper.queryMjFundPrt(entity.getAdmin(), entity.getTrustNo(), entity.getBankAcco());
                            accoBalanceChangeRecordService.balanceChangeRemind(fundPrdMap, entity.getAccoBalance(), oldEntity.getAccoBalance(),
                                    entity.getAdmin(), HtscConstants.MJ_ACCOUNT_TYPE_CODE, entity.getTrustNo());
                        }
                    }
                } catch (Exception e) {
                    log.error("募集户变动提醒失败!", e);
                }
            }
            List<String> rawUniqueKeyList = newList
                    .stream()
                    .map(MjAccountBalanceInfoEntity::getUniqueKey)
                    .collect(Collectors.toList());

            String ukList = String.join("--", rawUniqueKeyList);

            if (CollectionUtils.isNotEmpty(rawUniqueKeyList)) {
                Set<String> uniqueKeySet = baseMapper.queryUniqueKeyList(rawUniqueKeyList);
                if (CollectionUtils.isNotEmpty(uniqueKeySet)) {
                    baseMapper.deleteByUniqueKeys(uniqueKeySet);
                }

            }
            boolean saveStatus = this.saveBatch(newList);
            if (!saveStatus) {
                log.error("保存MjAccountBalanceInfo失败:{}", ukList);
            }
        }
        return R.ok();
    }

    @Override
    public R queryData(QueryDataReq vo) {
        try {
            log.info("开始查询募集户银行账户余额信息表...,租户信息为:{}", JSON.toJSONString(vo));
            //1 封装查询参数
            MjAccountBalanceInfoReq mjAccountBalanceInfoReq = JSON.parseObject(vo.getParams(), MjAccountBalanceInfoReq.class);
            //1.1 封装分页查询参数
            Map<String, Object> pageParams = PageUtil.getPageParams(mjAccountBalanceInfoReq);
            //1.2 封装查询参数
            QueryWrapper<MjAccountBalanceInfoEntity> queryWrapper = new QueryWrapper<>();
            queryWrapper.eq("admin", vo.getTenantName());
            if (StringUtils.isNotBlank(mjAccountBalanceInfoReq.getBankAcco())) {
                queryWrapper.eq("bank_acco", mjAccountBalanceInfoReq.getBankAcco());
            }
            //（按银行账号bankAcco（若存在）、账户类型accoTypeCode（若存在）、更新日期updateDate（若存在）、托管人编码trustNo逆序排列）
            queryWrapper.orderBy(true,false, "bank_acco","acco_type_code","update_date","trust_no");
            //2 执行检索
            IPage<MjAccountBalanceInfoEntity> page = this.page(
                    new Query<MjAccountBalanceInfoEntity>().getPage(pageParams),
                    queryWrapper
            );
            //封装数据
            PageUtils pageUtils = new PageUtils(page);
            List<MjAccountBalanceInfoEntity> entities = page.getRecords();
            //entities 转vo
            ArrayList<MjAccountBalanceInfoVo> vos = new ArrayList<>();
            for (MjAccountBalanceInfoEntity entity : entities) {
                vos.add(MjAccountBalanceInfoVo.builder()
                        .id(entity.getId())
                        .bankAcco(entity.getBankAcco())
                        .accoTypeCode(entity.getAccoTypeCode())
                        .accoBalance(Objects.isNull(entity.getAccoBalance())?null:entity.getAccoBalance().toString())
                        .availableBalance(Objects.isNull(entity.getAvailableBalance())?null:entity.getAvailableBalance().toString())
                        .currency(entity.getCurrency())
                        .summary(entity.getSummary())
                        .updateDate(entity.getUpdateDate())
                        .trustNo(entity.getTrustNo())
                        .build());
            }
            pageUtils.setList(vos);
            log.info("募集户银行账户余额信息查询成功...");
            return R.ok("募集户银行账户余额信息查询成功").put("data", pageUtils);
        } catch (RRException rrException) {
            log.error("the QueryDataVo is :" + JSON.toJSONString(vo) + ".the MjAccountBalanceInfoServiceImpl RRException is :", rrException);
            return R.error(RetCodeEnum.OPERATION_ERROR.getCode(), rrException.getMsg());
        } catch (Exception e) {
            log.error("the QueryDataVo is :" + JSON.toJSONString(vo) + ".the MjAccountBalanceInfoServiceImpl Exception is :", e);
            return R.error(RetCodeEnum.OPERATION_ERROR.getCode(), "查询数据失败!");
        }
    }

    @Override
    public R updateData(String type, List<MjAccountBalanceInfoEntity> datas) {
        return null;
    }

    public List<String> getBankAccoList(String trustNo,String admin){
        return mjAccountBalanceInfoDao.getBankAccoList(trustNo,admin);
    }
}