package com.neusoft.smart.pos.trade.service;

import com.neusoft.smart.pos.constants.DictionaryConstant;
import com.neusoft.smart.pos.framework.task.RedisTask;
import com.neusoft.smart.pos.framework.utils.DateUtils;
import com.neusoft.smart.pos.framework.utils.ListUtils;
import com.neusoft.smart.pos.framework.utils.SpringUtils;
import com.neusoft.smart.pos.order.persistent.domain.OrderMaster;
import com.neusoft.smart.pos.order.persistent.domain.OrderMasterExample;
import com.neusoft.smart.pos.order.repository.OrderMasterRepository;
import com.neusoft.smart.pos.trade.persistent.domain.*;
import com.neusoft.smart.pos.trade.persistent.ext.domain.BillCycleExt;
import com.neusoft.smart.pos.trade.persistent.ext.domain.BillProfitExt;
import com.neusoft.smart.pos.trade.persistent.ext.domain.BillSettlementRuleDetailExt;
import com.neusoft.smart.pos.trade.persistent.ext.domain.BillSettlementRuleExt;
import com.neusoft.smart.pos.trade.repository.*;
import lombok.Setter;
import lombok.extern.slf4j.Slf4j;
import lombok.val;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.Collections;
import java.util.Comparator;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Slf4j
@Service("billTaskService")
public class BillTaskService {

	private final static Logger logger = LoggerFactory.getLogger(BillTaskService.class);
	
	@Autowired
	private BillSettlementCycleRepository billSettlementCycleRepository;
	
	@Resource
	private BillSettlementRuleRepository billSettlementRuleRepository;
	
	@Resource
	private BillSettlementRuleDetailRepository billSettlementRuleDetailRepository;
	
	@Resource
	private OrderMasterRepository orderMasterRepository;
	
	@Autowired
	private BillDetailRepository billDetailRepository;
	
	@Autowired
	private BillMasterRepository billMasterRepository;
	
	@Autowired
	private BillRuleRepository billRuleRepository;
	
	@Autowired
	private BillDetailProfitRepository billDetailProfitRepository;
	
	@Autowired
	private BillSettlementTaskRepository billSettlementTaskRepository;
	
	private Map<Integer,String> commonRuleMap;
	
	/**
	 * 根据账单编号及门店列表生成账单信息
	 */
	public void generateBillByBillNumber(Integer orgId,List<Integer> shopIds,String billNumber){
		//1.根据账单编号计算账单周期，返回本期账期的开始时间和结束时间，时间精确到日
		BillCycleExt billCycleExt = getBillCycleByBillNumber(orgId,billNumber);
		if(null == billCycleExt){
			return;
		}
		//2.根据门店列表整理账单信息
		shopIds.forEach(shopId->{
			generateBillByShopId(shopId,billCycleExt);
		});
	}
	
	/**
	 * 根据门店Id生成账单信息
	 * @return
	 */
	private void generateBillByShopId(Integer shopId,BillCycleExt billCycleExt){
		//1.查询该门店规则列表
		List<BillSettlementRule> billSettlementRuleList = billSettlementRuleRepository.queryBillSettlementRulesByShopId(billCycleExt.getOrgId(),shopId);
		List<BillSettlementRuleExt> billSettlementRuleExtList = ListUtils.convertListToList(billSettlementRuleList,BillSettlementRuleExt.class);
		billSettlementRuleExtList.forEach(billSettlementRuleExt -> {
			List<BillSettlementRuleDetail> billSettlementRuleDetailList = billSettlementRuleDetailRepository.queryBillSettlementRuleDetails(billSettlementRuleExt.getId());
			
			Collections.sort(billSettlementRuleDetailList, new Comparator<BillSettlementRuleDetail>() {
				@Override
				public int compare(BillSettlementRuleDetail u1, BillSettlementRuleDetail u2) {
					return (u1.getPayType().compareTo(u2.getPayType())) * -1;
				}
			}); 
			
			billSettlementRuleExt.setBillSettlementRuleDetailExtList(ListUtils.convertListToList(billSettlementRuleDetailList, BillSettlementRuleDetailExt.class));
		});
		
		
		
		
		//2.查询该门店账期内订单列表
		val orderMasterExample = getOrderMasterExampleHandle(billCycleExt.getOrgId(),shopId,billCycleExt.getBillStartTime(),billCycleExt.getBillEndTime());
		List<OrderMaster> orderMasterList = orderMasterRepository.queryShopOrderDetails(orderMasterExample);
		
		//3.通过规则处理订单信息
		billRuleExecuteHandle(shopId,billSettlementRuleExtList,orderMasterList,billCycleExt);
		
	}
	
	/**
	 * 执行规则处理订单信息方法
	 */
	private void billRuleExecuteHandle(Integer shopId,List<BillSettlementRuleExt> billSettlementRuleExtList,List<OrderMaster> orderMasterList,BillCycleExt billCycleExt){
		commonRuleMap = new HashMap<>();
		BigDecimal billTotalAmount = new BigDecimal(0.0);    //账单总金额(收入金额+分润金额)
		BillDetail billDetail;
		
		BillSettlementRuleExt billSettlementRuleExt;
		//1.遍历订单信息
		for(int i=0;i<orderMasterList.size();i++){
			billDetail = new BillDetail();
			BeanUtils.copyProperties(orderMasterList.get(i),billDetail);
			billDetail.setOrderAmount(new BigDecimal(orderMasterList.get(i).getOrderAmount()).divide(new BigDecimal(100)));
			billDetail.setRealPayAmount(new BigDecimal(orderMasterList.get(i).getRealPayAmount()).divide(new BigDecimal(100)));
			//2.遍历规则信息
			for(int j=0;j<billSettlementRuleExtList.size();j++){
				billSettlementRuleExt = billSettlementRuleExtList.get(j);
				BillProfitExt billProfitExt = calculationProfitAmountByRule(billCycleExt.getBillNumber(),billSettlementRuleExt,orderMasterList.get(i));
				//2.1 为空表示不适用此规则，进行下一次循环，否则跳出循环返回结果
				if(null == billProfitExt){
					continue;
				}else{
					saveBillDetailProfit(billProfitExt.getBillProfitDetails());
					break;
				}
			}
			billTotalAmount = billTotalAmount.add(billDetail.getRealPayAmount());  //计算账单总金额
			//3.将账单详情存储至数据库中
			billDetail.setBillNumber(billCycleExt.getBillNumber());
			billDetailRepository.saveBillDetail(billDetail);
		}
		
		//4.存储主表信息
		BillMaster billMaster = new BillMaster();
		billMaster.setBillNumber(billCycleExt.getBillNumber());
		billMaster.setBillName(billCycleExt.getBillName());
		billMaster.setOrgId(billCycleExt.getOrgId());
		billMaster.setShopId(shopId);
		billMaster.setCycleStartTime(billCycleExt.getBillStartTime());
		billMaster.setCycleEndTime(billCycleExt.getBillEndTime());
		billMaster.setBillAmount(billTotalAmount);
		billMasterRepository.saveBillMaster(billMaster);
	}
	
	/**
	 * 保存账单分润明细详情信息
	 */
	private void saveBillDetailProfit(List<BillProfitExt.BillProfitDetailExt> billProfitDetailExtList){
		Date currentDate = new Date();
		List<BillDetailProfit> billDetailProfitList = ListUtils.convertListToList(billProfitDetailExtList,BillDetailProfit.class);
		billDetailProfitList.forEach(billDetailProfit -> {
			billDetailProfit.setRemark("");
			billDetailProfit.setVersion(1);
			billDetailProfit.setCreatedAt(currentDate);
			billDetailProfit.setCreatedBy("");
			billDetailProfit.setUpdatedAt(currentDate);
			billDetailProfit.setUpdatedBy("");
		});
		billDetailProfitRepository.saveBillDetailProfitBatch(billDetailProfitList);
	}
	
	/**
	 * 根据规则计算分润金额
	 * @return
	 */
	private BillProfitExt calculationProfitAmountByRule(String billNumber,BillSettlementRuleExt billSettlementRuleExt,OrderMaster orderMaster){
		//1.根据系统规则ID查询规则信息
		String beanName;
		if(commonRuleMap.containsKey(billSettlementRuleExt.getRuleId())){
			beanName = commonRuleMap.get(billSettlementRuleExt.getRuleId());
		}else{
			BillRuleDict billRuleDict = billRuleRepository.queryBillRuleDictById(billSettlementRuleExt.getRuleId());
			if(null == billRuleDict){
				return null;
			}
			beanName = billRuleDict.getBeanName();
			commonRuleMap.put(billSettlementRuleExt.getRuleId(),beanName);
		}
		IBillRuleService billRuleService = SpringUtils.getBean(beanName,IBillRuleService.class);
		return billRuleService.executeRule(billNumber,billSettlementRuleExt,orderMaster);
	}
	
	/**
	 * 根据账单编号获取账单周期详细信息（目前只支持月结）
	 * @param orgId
	 * @param billNumber:20180101
	 * @return
	 */
	private BillCycleExt getBillCycleByBillNumber(Integer orgId,String billNumber){
		//1.查询该集团周期规则
		BillSettlementCycle billSettlementCycle = billSettlementCycleRepository.queryBillSettlementCycleByOrgId(orgId);
		if(null == billSettlementCycle){
			return null;
		}
		
		//2.整理账单周期信息
		BillCycleExt billCycleExt = new BillCycleExt();
		billCycleExt.setOrgId(billSettlementCycle.getOrgId());
		billCycleExt.setShopId(billSettlementCycle.getShopId());
		billCycleExt.setCycleType(billSettlementCycle.getCycleType());  //周期类型@1:月结@2:年结@3:季结@4:周结
		DictionaryConstant dict = DictionaryConstant.getEnumByCode(DictionaryConstant.BILL_CYCLE_TYPE.getCode(),billSettlementCycle.getCycleType());
		switch (dict){
			case BILL_CYCLE_TYPE_MONTH:
				//月结,计算本次账单开始时间及结束时间，精确到日
				//结算账单日类型@1:自然日@2:结算周期最后一日
				if(billSettlementCycle.getBillDayType().equals("1")){
//					if(billSettlementCycle.getBillDay()<10){
//						billNumber = billNumber.substring(0,6)+"0"+billSettlementCycle.getBillDay();
//					}else{
//						billNumber = billNumber.substring(0,6)+billSettlementCycle.getBillDay();
//					}
					Date billTimeDate = DateUtils.parse(billNumber,DateUtils.FORMAT_SHORT_EXT);
//					Date billStartDate = DateUtils.getDayStartTime(billTimeDate);
					Date billStartDate = DateUtils.getDayStartTime(DateUtils.addDay(DateUtils.subMonth(billTimeDate,1),1));
					Date billEndDate = DateUtils.getDayEndTime(billTimeDate);
//					Date billEndDate = DateUtils.subDay(DateUtils.getDayEndTime(DateUtils.addMonth(billTimeDate,1)),1);
					billCycleExt.setBillName(DateUtils.format(billStartDate,DateUtils.FORMAT_SHORT_EXT)+"-"+DateUtils.format(billEndDate,DateUtils.FORMAT_SHORT_EXT));
					billCycleExt.setBillStartTime(billStartDate);
					billCycleExt.setBillEndTime(billEndDate);
					billCycleExt.setBillNumber(DateUtils.format(billEndDate,DateUtils.FORMAT_SHORT_EXT));
				}else if(billSettlementCycle.getBillDayType().equals("2")){
					Date billTimeDate = DateUtils.parse(billNumber,DateUtils.FORMAT_SHORT_EXT);
					Date billStartDate = DateUtils.getDayStartTime(DateUtils.getMonthFirstDay(billTimeDate));
					Date billEndDate = DateUtils.getDayEndTime(DateUtils.getMonthLastDay(billTimeDate));
					billNumber = DateUtils.format(billEndDate,DateUtils.FORMAT_SHORT_EXT);
					billCycleExt.setBillName(DateUtils.format(billStartDate,DateUtils.FORMAT_SHORT_EXT)+"-"+DateUtils.format(billEndDate,DateUtils.FORMAT_SHORT_EXT));
					billCycleExt.setBillStartTime(billStartDate);
					billCycleExt.setBillEndTime(billEndDate);
					billCycleExt.setBillNumber(DateUtils.format(billEndDate,DateUtils.FORMAT_SHORT_EXT));
				}
				break;
			case BILL_CYCLE_TYPE_QUARTER:
				//季结
				break;
			case BILL_CYCLE_TYPE_WEEK:
				//周结
				break;
			case BILL_CYCLE_TYPE_YEAR:
				//年结
				break;
		}
		//整理返回数据
		return billCycleExt;
	}
    
	/**
	 * 整理查询条件信息
	 * @return
	 */
	private OrderMasterExample getOrderMasterExampleHandle(Integer orgId, Integer shopId, Date startDate, Date endDate) {
		val example = new OrderMasterExample();
		example.createCriteria()
				.andOrgIdEqualTo(orgId)
				.andShopIdEqualTo(shopId)
				.andOrderStatusEqualTo(DictionaryConstant.ORDER_UPDATE_STATUS_ZFWC.getCode())
				.andOrderTypeNotEqualTo(DictionaryConstant.ORDER_TYPE_HYCZ.getCode())
		;
		//8.处理查询时间
		example.getOredCriteria().get(0).andCreatedAtGreaterThanOrEqualTo(startDate);
		example.getOredCriteria().get(0).andCreatedAtLessThanOrEqualTo(endDate);
		return example;
	}
	
	/**
	 * 保存账单结算任务信息
	 * @param billSettlementTask
	 */
	public void saveBillSettlementTask(BillSettlementTask billSettlementTask){
		billSettlementTaskRepository.saveBillSettlementTask(billSettlementTask);
	}
	
	/**
	 * 保存账单结算任务信息
	 * @param billSettlementTask
	 */
	public void updateBillSettlementTask(BillSettlementTask billSettlementTask,Integer orgId,String billNumber){
		billSettlementTaskRepository.updateBillSettlementTask(billSettlementTask,orgId,billNumber);
	}
}
