package com.ag.account.service;

import cn.hutool.core.util.ObjectUtil;
import com.ag.account.detail.AccountDetail;
import com.ag.account.detail.CalcManager;
import com.ag.account.feeUtil.RuleUtil;
import com.ag.account.feeUtil.TariffUtil;
import com.ag.base.DefaultBussniessImpl;
import com.ag.entity.account.FeeDetail;
import com.ag.entity.account.vo.BizVO;
import com.ag.entity.fee.BaseChargingItem;
import com.ag.entity.fee.ItemProperties;
import com.ag.entity.fee.TariffRitem;
import com.ag.entity.fee.face.IFeeBase;
import com.ag.entity.fee.face.ReqSource;
import com.ag.entity.fee.face.SourceProperty;
import com.ag.entity.fee.vo.ContractItemVO;
import com.ag.entity.fee.vo.ContractVO;
import com.ag.entity.fee.vo.SourceAndFeeDetail;
import com.ag.entity.fee.vo.TariffVO;
import com.ag.util.StrUtil;
import com.alibaba.fastjson.JSON;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * Created by yangxh on 2019/8/1.
 */
@Controller
public class FeeController implements IFeeBase {

    private Log log = LogFactory.getLog(FeeController.class);
    @Autowired
    private BizContractsService contractsService;
    @Autowired
    private AccountPointsCalcService pointService;
    @Autowired
    private DefaultBussniessImpl<FeeDetail> ctcDao;
    /*@Autowired
    private RedisTemplate redisTemplate;*/


    /**
     * 返回每个数据源对象生成的费用明细
     * @param reqStr
     * @return List<SourceAndFeeDetail>
     */
    @Override
    public String callbackSource(String reqStr){
        log.error("**************"+reqStr);
        BizVO bizVO = execute(reqStr);

        /*Object clientType = redisTemplate.opsForValue().get("KVBUFF_"+ICondition.C_CLIENT_TYPE);
        System.out.println(JSON.toJSONString(clientType));
        List<KvBean> list = SerializeUtil.unserializeForList((byte[])clientType);
        System.out.println("redis==="+JSON.toJSONString(list));*/
        List<SourceAndFeeDetail> sourceAndFees = new ArrayList<>();

        List<SourceProperty> sources = bizVO.getReqSource().getSourceProperties();
        for (SourceProperty source : sources){
            SourceAndFeeDetail sourceAndFee = new SourceAndFeeDetail();
            SourceProperty target = new SourceProperty();
            target.setBizId(source.getBizId());
            target.setBizTime(source.getBizTime());
            target.setBizType(source.getBizType());
            target.setProperty(source.getProperty());
            target.setSpare(source.getSpare());
            target.setBackTariffs(source.getBackTariffs());
            sourceAndFee.setSource(target);
            sourceAndFees.add(sourceAndFee);
        }
        List<FeeDetail> allDetails = bizVO.getDetails();
        for (SourceAndFeeDetail sourceAndFee : sourceAndFees){
            List<FeeDetail> targets = new ArrayList<>();
            sourceAndFee.setFeeDetails(targets);
            for (FeeDetail detail : allDetails) {
                if (sourceAndFee.getSource().getBizId().equals(detail.getBussinessCode())){
                    targets.add(detail);
                }
            }
        }
        return JSON.toJSONString(sourceAndFees);
    }

    @Override
    public String callback(String reqStr){
        log.error("source **************"+reqStr);
        BizVO bizVO = execute(reqStr);
        log.error("result **************");
        log.error(JSON.toJSONString(bizVO.getDetails()));
        return JSON.toJSONString(bizVO.getDetails());
    }

    @Override
    @Transactional
    public void call(String reqStr) {
        BizVO bizVO = execute(reqStr);
        ctcDao.saveAll(bizVO.getDetails());
    }

    private BizVO execute(String reqStr){
        ReqSource reqSource = JSON.parseObject(reqStr, ReqSource.class);
        BizVO bizVO = new BizVO();
        bizVO.setReqSource(reqSource);
        //通过计费事件编号—>所有计费费目，合同编号->所有合同费目=》该合同下满足的计费费目及所有属性
        init(bizVO);
        List<ContractItemVO> itemLst = bizVO.getDefaultContractVo().getItemLst();
        List<SourceProperty> properties = reqSource.getSourceProperties();
        //数据源
        for (SourceProperty property : properties) {
            log.error("数据源对象:"+ JSON.toJSONString(property)+"===============");
            //费目
            for (ContractItemVO item : itemLst) {
                TariffUtil.clear(property);
                Map<String, Integer> eqMap = item.getItemProperties().stream()
                        .collect(Collectors.toMap(ItemProperties::getPropertyCode, ItemProperties::getIsShowOperator));
                //去除显示要素，并按顺序要素重新排序
                List<ItemProperties> orderList = item.getItemProperties().stream().filter(x-> ObjectUtil.equal(0, x.getIsShowOperator()))
                        .sorted(Comparator.comparing(ItemProperties::getDispOrder)).collect(Collectors.toList());
                List<TariffVO> tariffLst = item.getTariffLst();
                if (CollectionUtils.isEmpty(tariffLst)){
                    log.error("合同号["+item.getContractId()+"]费目编号["+item.getItemId()+"]未找到费率");
                    continue;
                }
                List<TariffVO> fits = new ArrayList<>();
                //费率
                for (TariffVO tariffVO : tariffLst) {
                    /*if (tariffVO.getId().equals("b30f40b9222d48629ec2d3ba1216969b")
                            && property.getBizId().equals("56bdf298-4925-4ff8-8f8a-56b6ca18e3e6")
                    ){
                        System.out.println(JSON.toJSONString(tariffVO));
                    }*/
                    //费率有效期检查，有效返回true，无效返回false, 失效日期+1
                    if (!RuleUtil.checkValidity(tariffVO, property.getBizTime())){
                        continue;
                    }
                    List<TariffRitem> ritemList = tariffVO.getRitemList();
                    if (RuleUtil.compareRule(property, ritemList, eqMap)) {
                        fits.add(tariffVO);
                    }
                }
                if (!CollectionUtils.isEmpty(fits)) {
                    //logger.info("满足条件的费率信息：" + fits.size());
                    //logger.info(JSON.toJSONString(fits));
                    //合同费率筛选
                    TariffUtil.compareNum(property, fits, eqMap, orderList);
                    //保存合同费目
                    property.setContractItem(item);
                    //返回费率
                    property.getBackTariffs().add(property.getTariffVO());
                    Map<String, BaseChargingItem> itemMap = bizVO.getItemMap();
                    log.error("合同费目信息::"+itemMap.get(property.getContractItem().getItemId()).getDescription());
                    //log.error("费率信息::"+JSON.toJSONString(property.getTariffVO()));
                    log.error("费率金额::"+property.getTariffVO().getRate());
                    AccountDetail detail = CalcManager.getInstance(item);
                    if(detail != null){
                        detail.getFeeDetail(bizVO, property);
                    }
                }
            }
            log.error("======================================end");
        }
        return bizVO;
    }

    private void init(BizVO bizVO){
        ReqSource reqSource = bizVO.getReqSource();
        bizVO.setTenancyId(reqSource.getTenancyId());

        if (!StrUtil.isEmpty(reqSource.getAccountPointCode())){
            pointService.getFeeItems(bizVO, reqSource.getAccountPointCode());
        }
        if (!StrUtil.isEmpty(reqSource.getItemId())) {
            String itemIds = "'"+subRightString(reqSource.getItemId(), ",").replace(",", "','")+"'";
            bizVO.setItemIds(itemIds);
        }

        if (!StrUtil.isEmpty(reqSource.getContractId())){
            ContractVO contractVO = contractsService.findContractVO(reqSource.getContractId(), bizVO);
            bizVO.setDefaultContractVo(contractVO);
        }
        //按费目编号查询基础费目
        pointService.findBaseItemList(bizVO);

    }

    public static String subRightString(String str, String rightFlag) {
        if (StrUtil.isEmpty(str)){
            return "";
        }
        if (!str.contains(rightFlag)) {
            return str;
        }
        return str.substring(0, str.lastIndexOf(rightFlag));
    }

}
