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

import com.alibaba.fastjson.JSON;
import com.friday.custody.enums.RetCodeEnum;
import com.friday.custody.exception.RRException;
import com.friday.custody.req.PayFeeDetailInfoReq;
import com.friday.custody.req.QueryDataReq;
import com.friday.custody.service.basicService.PayFeeDetailInfoService;
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.PayFeeDetailInfoVO;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang.StringUtils;
import org.springframework.stereotype.Service;

import java.text.SimpleDateFormat;
import java.time.Duration;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.stream.Collectors;

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.dao.PayFeeDetailInfoDao;
import com.friday.custody.entity.PayFeeDetailInfoEntity;
import org.springframework.transaction.annotation.Transactional;


@Service("payFeeDetailInfoService")
@Slf4j
public class PayFeeDetailInfoServiceImpl extends ServiceImpl<PayFeeDetailInfoDao, PayFeeDetailInfoEntity>
        implements PayFeeDetailInfoService , DataProcessService<PayFeeDetailInfoEntity> {



    @Override
    @Transactional(rollbackFor = Exception.class)
    public R saveData(String type, List<PayFeeDetailInfoEntity> datas) {
        String trustNo = null;
        for (PayFeeDetailInfoEntity entity : datas) {
                trustNo = entity.getTrustNo();
                entity.setUniqueKey(entity.getAdmin() + entity.getTrustNo() + entity.getFundCode() + entity.getFundName()
                        + entity.getFeeType() + entity.getFeeDate() + entity.getChargeFee());
                if ("45".equals(entity.getTrustNo())){
                    entity.setUniqueKey(entity.getAdmin() + entity.getTrustNo() + entity.getInnerFundCode()
                            + entity.getFeeDate() + entity.getFeeType() + entity.getChargeFee() + entity.getFeeBalance());
                }
        }
        List<PayFeeDetailInfoEntity> uniquePayFeeDetailInfoList = datas.stream().collect(Collectors.collectingAndThen
                (Collectors.toCollection(() -> new TreeSet<>(Comparator.comparing
                        (PayFeeDetailInfoEntity::getUniqueKey))), ArrayList::new));

        List<String> rawUniqueKeyList = uniquePayFeeDetailInfoList
                .stream()
                .map(PayFeeDetailInfoEntity::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(uniquePayFeeDetailInfoList);
        if (!saveStatus) {
            log.error("保存PayFeeDetailInfo失败:{}", ukList);
        }else {
            log.info("trustNo为{}的托管插入pay_fee_detail_info数据{}条", trustNo, uniquePayFeeDetailInfoList.size());
        }

        return R.ok();
    }

    @Override
    public R queryData(QueryDataReq vo) {
        try {
            log.info("开始查询费用支付明细表...,租户信息为:{}", JSON.toJSONString(vo));
            //1 封装查询参数
            PayFeeDetailInfoReq req = JSON.parseObject(vo.getParams(), PayFeeDetailInfoReq.class);
            //1.1 封装分页查询参数
            Map<String, Object> pageParams = PageUtil.getPageParams(req);
            //1.2 封装查询参数
            QueryWrapper<PayFeeDetailInfoEntity> queryWrapper = new QueryWrapper<>();
            queryWrapper.eq("admin", vo.getTenantName());
            if (StringUtils.isNotBlank(req.getFundCode())) {
                queryWrapper.eq("fund_code", req.getFundCode());
            }
            if (StringUtils.isNotBlank(req.getInnerFundCode())){
                queryWrapper.eq("inner_fund_code",req.getInnerFundCode());
            }
            if (StringUtils.isNotBlank(req.getFeeType())) {
                queryWrapper.eq("fee_type", req.getFeeType());
            }
            SimpleDateFormat format = new SimpleDateFormat("yyyyMMdd");
            Calendar c = Calendar.getInstance();
            //开始和结束时间都为空，默认为一年
            if (StringUtils.isBlank(req.getBeginDate()) && StringUtils.isBlank(req.getEndDate())) {
                c.setTime(new Date());
                c.add(Calendar.YEAR, -1);
                Date m = c.getTime();
                String beginYear = format.format(m);
                req.setBeginDate(beginYear);
                req.setEndDate(format.format(new Date()));
            }
            //开始不为空和结束时间为空，默认当天
            if (StringUtils.isBlank(req.getEndDate()) && StringUtils.isNotBlank(req.getBeginDate())) {
                c.setTime(format.parse(req.getBeginDate()));
                c.add(Calendar.YEAR, 1);
                Date m = c.getTime();
                String endYear = format.format(m);
                req.setBeginDate(req.getBeginDate());
                req.setEndDate(endYear);
            }
            //开始为空和结束时间不为空，默认结束时间往前推一年
            if (StringUtils.isNotBlank(req.getEndDate()) && StringUtils.isBlank(req.getBeginDate())) {
                c.setTime(format.parse(req.getEndDate()));
                c.add(Calendar.YEAR, -1);
                Date m = c.getTime();
                String beginYear = format.format(m);
                req.setBeginDate(beginYear);
            }
            try {
                LocalDate beginDate = LocalDate.parse(req.getBeginDate(), DateTimeFormatter.ofPattern("yyyyMMdd"));
                LocalDate endDate = LocalDate.parse(req.getEndDate(), DateTimeFormatter.ofPattern("yyyyMMdd"));
                Duration duration = Duration.between(beginDate.atTime(0, 0, 0), endDate.atTime(0, 0, 0));
                long days = duration.toDays(); //相差的天数
                if (days < 0) {
                    return R.error(RetCodeEnum.PARAM_ERROR.getCode(), "endDate早于beginDate");
                }
                if (days > 366) {
                    return R.error(RetCodeEnum.PARAM_ERROR.getCode(), "beginDate与endDate间隔的天数不能超过365天");
                }
            } catch (Exception e) {
                log.error("参数有误：beginDate :{" + req.getBeginDate() + "}, endDate :{" + req.getEndDate() + "}", e);
                return R.error(RetCodeEnum.PARAM_ERROR.getCode(), "beginDate或endDate格式不正确");
            }
            queryWrapper.ge("fee_date", req.getBeginDate());
            queryWrapper.le("fee_date", req.getEndDate());
            //（按计提日期feeDate（若存在）、基金备案编码fundCode（若存在）、基金内部代码innerFundCode（若存在）、费用类型编码feeType（若存在）、托管人编码trustNo逆序排列）
            queryWrapper.orderBy(true, false, "fee_date", "fund_code", "inner_fund_code", "fee_type", "trust_no");
            //2 执行检索
            IPage<PayFeeDetailInfoEntity> page = this.page(
                    new Query<PayFeeDetailInfoEntity>().getPage(pageParams),
                    queryWrapper
            );
            //封装数据
            PageUtils pageUtils = new PageUtils(page);
            List<PayFeeDetailInfoEntity> entities = page.getRecords();
            //entities 转vo
            ArrayList<PayFeeDetailInfoVO> vos = new ArrayList<>();
            for (PayFeeDetailInfoEntity entity : entities) {
                vos.add(PayFeeDetailInfoVO.builder()
                        .id(entity.getId())
                        .fundCode(entity.getFundCode())
                        .innerFundCode(entity.getInnerFundCode())
                        .fundName(entity.getFundName())
                        .feeType(entity.getFeeType())
                        .chargeFee(Objects.isNull(entity.getChargeFee()) ? null : entity.getChargeFee().toString())
                        .feeBalance(Objects.isNull(entity.getFeeBalance()) ? null : entity.getFeeBalance().toString())
                        .feeDate(entity.getFeeDate())
                        .summary(entity.getSummary())
                        .currency(entity.getCurrency())
                        .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 PayFeeDetailInfoServiceImpl RRException is :", rrException);
            return R.error(RetCodeEnum.OPERATION_ERROR.getCode(), rrException.getMsg());
        } catch (Exception e) {
            log.error("the QueryDataVo is :" + JSON.toJSONString(vo) + ".the PayFeeDetailInfoServiceImpl Exception is :", e);
            return R.error(RetCodeEnum.OPERATION_ERROR.getCode(), "查询数据失败!");
        }
    }

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