package com.ufida.api.service;

import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.function.Function;
import java.util.stream.Collectors;

import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import com.cku.oa.finance.service.SaPaymentDetailTotalService;
import com.cku.oa.finance.vo.SaPaymentWayAccountVo;
import com.cku.oa.finance.vo.SaVoucherFinishedOrderVo;
import com.cku.oa.finance.vo.SaVoucherRechargeVo;
import com.cku.oa.finance.vo.SaVoucherRefundVo;
import com.cku.oa.finance.vo.SaVoucherTransferAccountVo;
import com.cku.oa.sys.entity.user.Member;
import com.cku.oa.sys.service.user.MemberService;
import com.google.common.collect.Lists;
import com.ufida.api.request.VoucherAddRequest;
import com.ufida.api.vo.AuxiliaryVo;
import com.ufida.api.vo.CashFlowVo;
import com.ufida.api.vo.CreditVo;
import com.ufida.api.vo.DebitVo;
import com.ufida.api.vo.EntryVo;
import com.ufida.api.vo.VoucherVo;

@Service
public class VoucherQueryService {

	@Autowired
	private MemberService memberService;

	@Autowired
	private SaPaymentDetailTotalService saPaymentDetailTotalService;
	
	@Value("${ufida.voucher.type}")
	private String voucherType;
	
	@Value("${ufida.voucher.enter}")
	private String voucherEnter;
	
	private final static SimpleDateFormat SDF_YMD_DESC = new SimpleDateFormat("yyyy年MM月dd日");
	
	private final static SimpleDateFormat SDF_YMD = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
	
	private final static SimpleDateFormat SDF_YM = new SimpleDateFormat("yyyyMM");

	public static Date dayAddNum(Date time, Integer num) {
		Calendar calendar = Calendar.getInstance();
		calendar.setTime(time);
		calendar.add(Calendar.DAY_OF_MONTH, num);
		Date newTime = calendar.getTime();
		return newTime;
	}

	public VoucherAddRequest findRechargeVoucherData(Date startDate,Date endDate) throws Exception {

		Calendar calendar = Calendar.getInstance();
		calendar.setTime(startDate);
		
		List<SaPaymentWayAccountVo> payWayAccountList = saPaymentDetailTotalService.findAllPaymentWayAccounts();
		Map<String, SaPaymentWayAccountVo> payWayAccountMap = payWayAccountList.stream()
				.collect(Collectors.toMap(SaPaymentWayAccountVo::getPaymentWay, Function.identity()));
		List<SaVoucherRechargeVo> detailList = saPaymentDetailTotalService.findRechargeVoucherData(
				SDF_YMD.format(startDate), SDF_YMD.format(endDate));
		if (!CollectionUtils.isEmpty(detailList)) {

			Set<String> memberCodes = detailList.stream().map(SaVoucherRechargeVo::getCentryCustomerCode)
					.collect(Collectors.toSet());
			memberCodes.addAll(detailList.stream().map(SaVoucherRechargeVo::getCentryPaymentMemberCode)
					.collect(Collectors.toSet()));
			memberCodes.remove("");
			Map<String, String> memberMap = new HashMap<>();
			if (memberCodes.size() > 0) {
				List<Member> members = memberService.getByMemberCodes(memberCodes);
				memberMap.putAll(members.stream().collect(Collectors.toMap(Member::getMemberCode, Member::getName)));
			}

			Map<String, List<SaVoucherRechargeVo>> detailMap = detailList.stream()
					.collect(Collectors.groupingBy(SaVoucherRechargeVo::getPaymentWay));
			VoucherVo voucher = new VoucherVo();
			voucher.setAccountingPeriod(calendar.get(Calendar.MONTH) + 1);
			voucher.setVoucherType(voucherType);
			voucher.setFiscalYear(calendar.get(Calendar.YEAR));
			voucher.setEnter(voucherEnter);
			voucher.setDate(calendar.getTime());

			List<EntryVo> credits = new ArrayList<>();
			List<EntryVo> debits = new ArrayList<>();

			detailMap.forEach((key, val) -> {

				EntryVo dentryVo = new EntryVo();
				dentryVo.setAbstracts(SDF_YMD_DESC.format(calendar.getTime()) + " CKU会员充值");// 借摘要
				dentryVo.setAccountCode(payWayAccountMap.get(key).getAccountCode());
				dentryVo.setNaturalDebitCurrency(val.stream().map(SaVoucherRechargeVo::getDentryPaymentMoney)
						.reduce(BigDecimal.ZERO, BigDecimal::add));
				
				dentryVo.setCashFlow(Lists.newArrayList(new CashFlowVo(dentryVo.getNaturalDebitCurrency(),voucher.getDate(), voucher.getFiscalYear().toString(),SDF_YM.format(calendar.getTime()))));
				debits.add(dentryVo);

				val.forEach(detail -> {
					EntryVo centryVo = new EntryVo();
					// 2019年9月14日A会员（付款人：A会员）微信充值/订单
					if (StringUtils.isNotBlank(detail.getCentryCustomerCode())) {
						centryVo.setAbstracts(SDF_YMD_DESC.format(calendar.getTime()) + " "
								+ memberMap.get(detail.getCentryCustomerCode()) + " (付款人："
								+ memberMap.get(detail.getCentryPaymentMemberCode()) + ") "
								+ (detail.getOrderFlag() ? " 订单"
										: payWayAccountMap.get(detail.getPaymentWay()).getRemarks() + "/充值"));
					} else if (StringUtils.isNotBlank(detail.getCentrySupplierCode())) {
						centryVo.setAbstracts(SDF_YMD_DESC.format(calendar.getTime()) + " CKU业务订单-平阳往来款");
					} else {
						centryVo.setAbstracts("");
					}
					centryVo.setAccountCode(detail.getCentryAccountCode());
					centryVo.setNaturalCreditCurrency(detail.getCentryPaymentMoney());
					AuxiliaryVo auxiliary = new AuxiliaryVo();
					auxiliary.setSupplierId(detail.getCentrySupplierCode());
					auxiliary.setCustId(detail.getCentryCustomerCode());
					centryVo.setAuxiliary(auxiliary);
					credits.add(centryVo);
				});
			});
			
			voucher.setDebit(new DebitVo(debits));
			voucher.setCredit(new CreditVo(credits));
			return new VoucherAddRequest(voucher);
		}
		return null;
	}

	public VoucherAddRequest findFinishedOrderVoucherData(Date startDate,Date endDate) throws Exception {
		Calendar calendar = Calendar.getInstance();
		calendar.setTime(startDate);

		List<SaVoucherFinishedOrderVo> detailList = saPaymentDetailTotalService.findFinishedOrderVoucherData(
				SDF_YMD.format(startDate), SDF_YMD.format(endDate));
		if (!CollectionUtils.isEmpty(detailList)) {

			Map<String, List<SaVoucherFinishedOrderVo>> detailMap = detailList.stream()
					.collect(Collectors.groupingBy(p -> {
//    			return p.getCentryDeptCode();
						return p.getCentryAccountCode() + p.getCentryDeptCode() + p.getCentryItemCode();
//    			return p.getDeptCode();
					}));

			VoucherVo voucher = new VoucherVo();
			voucher.setAccountingPeriod(calendar.get(Calendar.MONTH) + 1);
			voucher.setVoucherType(voucherType);
			voucher.setFiscalYear(calendar.get(Calendar.YEAR));
			voucher.setEnter(voucherEnter);
			voucher.setDate(new Date()/* calendar.getTime() */);

			List<EntryVo> credits = new ArrayList<>();
			List<EntryVo> debits = new ArrayList<>();

			detailMap.forEach((key, val) -> {

				List<SaPaymentWayAccountVo> payWayAccountList = saPaymentDetailTotalService.findAllPaymentWayAccounts();
				Map<String, SaPaymentWayAccountVo> payWayAccountMap = payWayAccountList.stream()
						.collect(Collectors.toMap(SaPaymentWayAccountVo::getPaymentWay, Function.identity()));
				Set<String> memberCodes = detailList.stream().map(SaVoucherFinishedOrderVo::getDentryCustomerCode)
						.collect(Collectors.toSet());
				memberCodes.remove("");
				Map<String, String> memberMap = new HashMap<>();
				if (memberCodes.size() > 0) {
					List<Member> members = memberService.getByMemberCodes(memberCodes);
					memberMap
							.putAll(members.stream().collect(Collectors.toMap(Member::getMemberCode, Member::getName)));
				}

				EntryVo centryVo = new EntryVo();
				// 贷摘要 -- 2019年09月24日 全犬种犬籍管理中心
				centryVo.setAbstracts(SDF_YMD_DESC.format(calendar.getTime()) + " " + val.get(0).getCentryDeptName());
				centryVo.setAccountCode(val.get(0).getCentryAccountCode());

				centryVo.setNaturalCreditCurrency(val.stream().map(SaVoucherFinishedOrderVo::getCentryPaymentMoney)
						.reduce(BigDecimal.ZERO, BigDecimal::add).subtract(val.stream()
								.map(SaVoucherFinishedOrderVo::getTaxMoney).reduce(BigDecimal.ZERO, BigDecimal::add)));
				AuxiliaryVo centryAuxiliary = new AuxiliaryVo();
				centryAuxiliary.setDeptId(val.get(0).getCentryDeptCode());
				centryAuxiliary.setItemId(val.get(0).getCentryItemCode());
				if (StringUtils.isNotBlank(val.get(0).getCentryItemCode())) {
					centryAuxiliary.setItemClass("97");
				}
				centryVo.setAuxiliary(centryAuxiliary);
				credits.add(centryVo);

				val.forEach(detail -> {

					EntryVo dentryVo = new EntryVo();
					// 借摘要 -- 2019年09月24日 客户名 订单
					dentryVo.setAbstracts(SDF_YMD_DESC.format(calendar.getTime()) + " "
							+ memberMap.get(detail.getDentryCustomerCode()) + " 订单/"
							+ payWayAccountMap.get(detail.getPaymentWay()).getRemarks());
					dentryVo.setAccountCode(detail.getDentryAccountCode());
					dentryVo.setNaturalDebitCurrency(detail.getDentryPaymentMoney());
					AuxiliaryVo dentryAuxiliary = new AuxiliaryVo();
					dentryAuxiliary.setCustId(detail.getDentryCustomerCode());
					dentryVo.setAuxiliary(dentryAuxiliary);
					debits.add(dentryVo);

					EntryVo centryTaxVo = new EntryVo();
					// 贷税摘要 -- 2019年09月24日 全犬种犬籍管理中心
					centryTaxVo.setAbstracts(
							SDF_YMD_DESC.format(calendar.getTime()) + " 应交增值税 " /* + detail.getCentryDeptName() */);
					centryTaxVo.setAccountCode(detail.getTaxAccountCode());
					centryTaxVo.setNaturalCreditCurrency(detail.getTaxMoney());
//        	    	AuxiliaryVo taxAuxiliary = new AuxiliaryVo();
//        	    	taxAuxiliary.setDeptId(detail.getCentryDeptCode());
//        	    	taxAuxiliary.setItemId(detail.getCentryItemCode());
//        	    	centryTaxVo.setAuxiliary(taxAuxiliary);
					credits.add(centryTaxVo);

				});

				voucher.setDebit(new DebitVo(debits));
				voucher.setCredit(new CreditVo(credits));

			});
			return new VoucherAddRequest(voucher);
		}
		return null;
	}

	public VoucherAddRequest findRefundOrderVoucherData(Date startDate,Date endDate) throws Exception {

		Calendar calendar = Calendar.getInstance();
		calendar.setTime(startDate);

		List<SaVoucherRefundVo> detailList = saPaymentDetailTotalService.findRefundOrderVoucherData(SDF_YMD.format(startDate), SDF_YMD.format(endDate));
		if (!CollectionUtils.isEmpty(detailList)) {

			Map<String, List<SaVoucherRefundVo>> detailMap = detailList.stream().collect(Collectors.groupingBy(p -> {
				return p.getCentryAccountCode();
			}));

			Set<String> memberCodes = detailList.stream().map(SaVoucherRefundVo::getDentryCustomerCode)
					.collect(Collectors.toSet());
			memberCodes.remove("");
			Map<String, String> memberMap = new HashMap<>();
			if (memberCodes.size() > 0) {
				List<Member> members = memberService.getByMemberCodes(memberCodes);
				memberMap.putAll(members.stream().collect(Collectors.toMap(Member::getMemberCode, Member::getName)));
			}

			VoucherVo voucher = new VoucherVo();
			voucher.setAccountingPeriod(calendar.get(Calendar.MONTH) + 1);
			voucher.setVoucherType(voucherType);
			voucher.setFiscalYear(calendar.get(Calendar.YEAR));
			voucher.setEnter(voucherEnter);
			voucher.setDate(calendar.getTime());

			List<EntryVo> credits = new ArrayList<>();
			List<EntryVo> debits = new ArrayList<>();

			detailMap.forEach((key, val) -> {

				EntryVo centryVo = new EntryVo();
				// 贷摘要
				centryVo.setAbstracts(SDF_YMD_DESC.format(calendar.getTime()) + " CKU业务订单-平阳往来款");
				centryVo.setAccountCode(key);
				centryVo.setNaturalCreditCurrency(BigDecimal.ZERO);
				AuxiliaryVo centryAuxiliary = new AuxiliaryVo();
				centryAuxiliary.setSupplierId(val.get(0).getCentrySupplierCode());
				centryAuxiliary.setCustId(val.get(0).getCentryCustomerCode());
				centryVo.setAuxiliary(centryAuxiliary);

				val.forEach(detail -> {

					EntryVo dentryVo = new EntryVo();
					// 借摘要
					dentryVo.setAbstracts(SDF_YMD_DESC.format(calendar.getTime()) + " "
							+ memberMap.get(detail.getDentryCustomerCode()) + " 订单");
					dentryVo.setAccountCode(detail.getDentryAccountCode());
					dentryVo.setNaturalDebitCurrency(detail.getDentryPaymentMoney());
					AuxiliaryVo auxiliary = new AuxiliaryVo();
					auxiliary.setCustId(detail.getDentryCustomerCode());
					dentryVo.setAuxiliary(auxiliary);
					debits.add(dentryVo);
					centryVo.setNaturalCreditCurrency(
							centryVo.getNaturalCreditCurrency().add(dentryVo.getNaturalDebitCurrency()));

				});
				credits.add(centryVo);
			});

			voucher.setDebit(new DebitVo(debits));
			voucher.setCredit(new CreditVo(credits));
			return new VoucherAddRequest(voucher);
		}
		return null;
	}

	public VoucherAddRequest findTransferVoucherData(Date startDate,Date endDate) throws Exception {
		Calendar calendar = Calendar.getInstance();
		calendar.setTime(startDate);
		List<SaVoucherTransferAccountVo> detailList = saPaymentDetailTotalService.findTransferVoucherData(SDF_YMD.format(startDate), SDF_YMD.format(endDate));
		if (!CollectionUtils.isEmpty(detailList)) {
			Map<String, List<SaVoucherTransferAccountVo>> detailMap = detailList.stream()
					.collect(Collectors.groupingBy(p -> {
						return p.getDentryCustomerCode();
					}));

			Set<String> memberCodes = detailList.stream().map(SaVoucherTransferAccountVo::getDentryCustomerCode)
					.collect(Collectors.toSet());
			memberCodes.addAll(detailList.stream().map(SaVoucherTransferAccountVo::getCentryCustomerCode)
					.collect(Collectors.toSet()));
			memberCodes.remove("");
			Map<String, String> memberMap = new HashMap<>();
			if (memberCodes.size() > 0) {
				List<Member> members = memberService.getByMemberCodes(memberCodes);
				memberMap.putAll(members.stream().collect(Collectors.toMap(Member::getMemberCode, Member::getName)));
			}

			VoucherVo voucher = new VoucherVo();
			voucher.setAccountingPeriod(calendar.get(Calendar.MONTH) + 1);
			voucher.setVoucherType(voucherType);
			voucher.setFiscalYear(calendar.get(Calendar.YEAR));
			voucher.setEnter(voucherEnter);
			voucher.setDate(calendar.getTime());

			List<EntryVo> credits = new ArrayList<>();
			List<EntryVo> debits = new ArrayList<>();

			detailMap.forEach((key, val) -> {

				EntryVo dentryVo = new EntryVo();
				// 借摘要
				dentryVo.setAbstracts("付款会员号:" + key + ",付款人:" + memberMap.get(key));
				dentryVo.setAccountCode(val.get(0).getDentryAccountCode());
				dentryVo.setNaturalDebitCurrency(BigDecimal.ZERO);
				dentryVo.setNaturalDebitCurrency(val.stream().map(SaVoucherTransferAccountVo::getDentryPaymentMoney)
						.reduce(BigDecimal.ZERO, BigDecimal::add));
				AuxiliaryVo auxiliary = new AuxiliaryVo();
				auxiliary.setCustId(key);
				dentryVo.setAuxiliary(auxiliary);
				debits.add(dentryVo);

				val.forEach(detail -> {
					EntryVo centryVo = new EntryVo();
					// 贷摘要 付款会员号+付款人+“转入”+收款会员号+收款人
					centryVo.setAbstracts("付款会员号:" + key + ",付款人:" + memberMap.get(key) + ",收款会员号:"
							+ detail.getCentryCustomerCode() + ",收款人:" + memberMap.get(detail.getCentryCustomerCode()));
					centryVo.setAccountCode(detail.getCentryAccountCode());
					centryVo.setNaturalCreditCurrency(detail.getCentryPaymentMoney());
					AuxiliaryVo centryAuxiliary = new AuxiliaryVo();
					centryAuxiliary.setCustId(detail.getCentryCustomerCode());
					centryVo.setAuxiliary(centryAuxiliary);
					credits.add(centryVo);
				});
			});

			voucher.setDebit(new DebitVo(debits));
			voucher.setCredit(new CreditVo(credits));
			return new VoucherAddRequest(voucher);
		}
		return null;
	}
}
