package com.palmnest.service.estateserve.impl;

import com.palmnest.application.bean.Page;
import com.palmnest.application.core.util.DateUtils;
import com.palmnest.application.core.util.LogExceptionStackUtil;
import com.palmnest.dao.estateserve.GeneralBillsDao;
import com.palmnest.dao.property.PropertyDao;
import com.palmnest.model.bill.DepositRecord;
import com.palmnest.model.bill.GeneralBillOrders;
import com.palmnest.model.bill.GeneralBills;
import com.palmnest.model.bill.GeneralbillService;
import com.palmnest.model.property.VirtualArchitecture;
import com.palmnest.service.estateserve.GeneralBillsManager;
import com.palmnest.service.impl.GenericManagerImpl;
import lombok.extern.slf4j.Slf4j;
import net.sf.json.JSONArray;
import net.sf.json.JSONObject;
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 java.math.BigDecimal;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Slf4j
@Service("generalBillsManager")
public class GeneralBillsManagerImpl extends GenericManagerImpl<Object, Integer> implements GeneralBillsManager {


	private GeneralBillsDao generalBillsDao;

	@Autowired
	public void setGeneralBillsDao(GeneralBillsDao generalBillsDao) {
		this.generalBillsDao = generalBillsDao;
		this.dao = generalBillsDao;
	}

	@Autowired
	private PropertyDao propertyDao;


	@Override
	public Page generalBillsPage(Integer pageSzie, Integer pageNo,
								 Integer virtualId, String dateTime) throws Exception {
		try {
			Page                      page      = generalBillsDao.generalBillsPage(pageSzie, pageNo, virtualId, dateTime);
			List<Map<String, Object>> itemsList = page.getItems();
			for (int i = 0; i < itemsList.size(); i++) {
				Map<String, Object> result = itemsList.get(i);
				if (result.get("totalFee") != null && result.get("payFee") != null && result.get("dedFee") != null) {
					BigDecimal totalFee = new BigDecimal(result.get("totalFee") + "");
					BigDecimal payFee   = new BigDecimal(result.get("payFee") + "");
					BigDecimal dedFee   = new BigDecimal(result.get("dedFee") + "");
					result.put("unpaidAmount", totalFee.subtract(payFee).subtract(dedFee).doubleValue());
					itemsList.set(i, result);
				}
			}
			page.setItems(itemsList);
			return page;
		} catch (Exception e) {
			LogExceptionStackUtil.LogExceptionStack(e);
		}
		return null;
	}


	@Override
	public Map<String, Object> saveUpdateDepositRecord(
			DepositRecord depositRecord) throws Exception {
		Map<String, Object> reulstMap = new HashMap<String, Object>();
		try {
			VirtualArchitecture virtualArchitecture = propertyDao.getVirtualArchitectureById(depositRecord.getVirtualId());//获取企业信息
			if (depositRecord.getStatus().equals("1")) {
				reulstMap.put("desc", "充值成功！");
				reulstMap.put("flag", true);
				virtualArchitecture.setReserveBalance(virtualArchitecture.getReserveBalance().add(depositRecord.getAmountFee()));
			} else {
				Double value = virtualArchitecture.getReserveBalance().subtract(depositRecord.getAmountFee()).doubleValue();
				if (value < 0) {
					reulstMap.put("desc", "扣减的余额已经不足！");
					reulstMap.put("flag", false);
					return reulstMap;
				}
				reulstMap.put("desc", "扣减成功！");
				reulstMap.put("flag", true);
				virtualArchitecture.setReserveBalance(new BigDecimal(value));
			}
			propertyDao.updateObj(virtualArchitecture);
			generalBillsDao.saveObj(depositRecord);

		} catch (Exception e) {
			reulstMap.put("desc", "操作失败！");
			reulstMap.put("flag", false);
			LogExceptionStackUtil.LogExceptionStack(e);
		}
		return reulstMap;
	}


	@Override
	public Page getDepositRecordPage(Integer pageSzie, Integer pageNo,
									 Integer virtualId) throws Exception {
		try {
			return generalBillsDao.getDepositRecordPage(pageSzie, pageNo, virtualId);
		} catch (Exception e) {
			LogExceptionStackUtil.LogExceptionStack(e);
		}
		return null;
	}


	@Override
	public BigDecimal getArrearsRecord(String mothTime, Integer virtualId) throws Exception {
		return generalBillsDao.getArrearsRecord(mothTime, virtualId);
	}


	@Override
	public GeneralBills getGeneralBillsById(Integer id) throws Exception {
		return generalBillsDao.getGeneralBillsById(id);
	}


	@Override
	public List<GeneralbillService> getGeneralbillServiceList(Integer billId)
			throws Exception {
		return generalBillsDao.getGeneralbillServiceList(billId);
	}


	@Override
	public List<GeneralBillOrders> geteneralBillOrdersList(Integer billId,
														   String serviceCode) throws Exception {
		return generalBillsDao.geteneralBillOrdersList(billId, serviceCode);
	}


	@Transactional
	@Override
	public Map<String, Object> saveUpdateGeneralBills(String generalBissData,
													  String delServiceData, String delOrderData, String generalBillsDate, String user) throws Exception {
		Map<String, Object> resultMap = new HashMap<String, Object>();
		try {
			if (StringUtils.isNotBlank(generalBillsDate)) {
				//修改账单主体信息
				JSONObject   generalBills = JSONObject.fromObject(generalBillsDate);
				GeneralBills general      = generalBillsDao.getGeneralBillsById(generalBills.getInt("generalBillsId"));
				general.setModifier(user);
				general.setModifyTime(new Date());
				general.setMakePerson(generalBills.getString("makePerson"));
				general.setMakeTime(generalBills.getString("makeTime"));
				general.setTotalFee(new BigDecimal(generalBills.getString("totalFee")));
				general.setStartTime(DateUtils.StrToDate(generalBills.getString("startTime"), "yyyy-MM-dd"));
				general.setEndTime(DateUtils.StrToDate(generalBills.getString("endTime"), "yyyy-MM-dd"));
				generalBillsDao.updateObj(general);
				if (StringUtils.isNotBlank(generalBissData)) {
					JSONArray generlBissJsonArray = JSONObject.fromObject(generalBissData).getJSONArray("serviceBill");
					for (int i = 0; i < generlBissJsonArray.size(); i++) {
						JSONObject jsonObject = generlBissJsonArray.getJSONObject(i);
						if (jsonObject != null) {
							GeneralbillService generalbillService = null;
							String             billServiceId      = jsonObject.getString("billServiceId");
							if (StringUtils.isNotBlank(billServiceId)) {
								generalbillService = generalBillsDao.getGeneralbillServiceById(Integer.parseInt(billServiceId));
								generalbillService.setModifier(user);
								generalbillService.setModifyTime(new Date());
								String freeFee = jsonObject.getString("freeFee");
								generalbillService.setTotalFee(new BigDecimal(jsonObject.getString("totalFee")));
								if (StringUtils.isNotBlank(freeFee)) {
									generalbillService.setFreeFee(new BigDecimal(freeFee));
								} else {
									generalbillService.setFreeFee(new BigDecimal(0));
								}
								generalbillService.setPayFee(new BigDecimal(jsonObject.getString("totalFee")));
								generalbillService.setServiceCode(jsonObject.getString("serviceCode"));
								generalbillService.setServiceName(jsonObject.getString("serviceName"));
								generalBillsDao.updateObj(generalbillService);
							} else {
								generalbillService = new GeneralbillService();
								generalbillService.setBillId(general.getId());
								generalbillService.setCreateTime(new Date());
								generalbillService.setCreator(user);
								String freeFee = jsonObject.getString("freeFee");
								if (StringUtils.isNotBlank(freeFee)) {
									generalbillService.setFreeFee(new BigDecimal(freeFee));
									generalbillService.setTotalFee(new BigDecimal(jsonObject.getString("totalFee")).add(generalbillService.getFreeFee()));
								} else {
									generalbillService.setFreeFee(new BigDecimal(0));
									generalbillService.setTotalFee(new BigDecimal(jsonObject.getString("totalFee")));
								}
								generalbillService.setPayFee(new BigDecimal(jsonObject.getString("totalFee")));
								generalbillService.setServiceCode(jsonObject.getString("serviceCode"));
								generalbillService.setServiceName(jsonObject.getString("serviceName"));
								generalBillsDao.saveObj(generalbillService);
							}

							JSONArray orderList = jsonObject.getJSONArray("orderList");
							for (int j = 0; j < orderList.size(); j++) {
								JSONObject        jsonObject2       = orderList.getJSONObject(j);
								String            orderId           = jsonObject2.getString("orderId");
								GeneralBillOrders generalBillOrders = null;
								if (StringUtils.isNotBlank(orderId)) {
									String str[] = orderId.split("_");
									generalBillOrders = generalBillsDao.geteneralBillOrdersById(Integer.parseInt(str[1]));
									generalBillOrders.setModifyTime(new Date());
									generalBillOrders.setModifier(user);
									generalBillOrders.setGoodName(jsonObject2.getString("goodName"));
									generalBillOrders.setIsEnabled("1");
									if (StringUtils.isBlank(jsonObject2.getString("amount"))) {
										generalBillOrders.setAmount(0);
									} else {
										generalBillOrders.setAmount(jsonObject2.getInt("amount"));
									}
									generalBillOrders.setOrderTime(DateUtils.StrToDate(jsonObject2.getString("orderTime"), "yyyy-MM-dd"));
									generalBillOrders.setTotalFee(new BigDecimal(jsonObject2.getString("totalFee")));
									generalBillOrders.setPrice(generalBillOrders.getTotalFee().divide(new BigDecimal(generalBillOrders.getAmount()), 2, BigDecimal.ROUND_HALF_EVEN));
									generalBillOrders.setServiceCode(generalbillService.getServiceCode());
									generalBillOrders.setServiceName(generalbillService.getServiceName());
									generalBillsDao.updateObj(generalBillOrders);
								} else {
									generalBillOrders = new GeneralBillOrders();
									generalBillOrders.setBillId(general.getId());
									generalBillOrders.setCreateTime(new Date());
									generalBillOrders.setCreator(user);
									generalBillOrders.setGoodName(jsonObject2.getString("goodName"));
									generalBillOrders.setIsEnabled("1");
									if (StringUtils.isBlank(jsonObject2.getString("amount"))) {
										generalBillOrders.setAmount(0);
									} else {
										generalBillOrders.setAmount(jsonObject2.getInt("amount"));
									}
									generalBillOrders.setOrderTime(DateUtils.StrToDate(jsonObject2.getString("orderTime"), "yyyy-MM-dd"));
									generalBillOrders.setTotalFee(new BigDecimal(jsonObject2.getString("totalFee")));
									generalBillOrders.setPrice(generalBillOrders.getTotalFee().divide(new BigDecimal(generalBillOrders.getAmount()), 2, BigDecimal.ROUND_HALF_EVEN));
									generalBillOrders.setServiceCode(generalbillService.getServiceCode());
									generalBillOrders.setServiceName(generalbillService.getServiceName());
									generalBillsDao.save(generalBillOrders);
								}
							}
						}
					}
				}
				if (JSONObject.fromObject(delServiceData).getJSONArray("delServiceBill").size() > 0) {
					JSONArray jsonArray = JSONObject.fromObject(delServiceData).getJSONArray("delServiceBill");
					for (int i = 0; i < jsonArray.size(); i++) {
						generalBillsDao.deleteGeneralbillService(jsonArray.getJSONObject(i).getInt("billServiceId"));
					}
				}
				if (JSONObject.fromObject(delOrderData).getJSONArray("delOrderBill").size() > 0) {
					JSONArray jsonArray = JSONObject.fromObject(delOrderData).getJSONArray("delOrderBill");
					for (int i = 0; i < JSONObject.fromObject(delOrderData).getJSONArray("delOrderBill").size(); i++) {
						generalBillsDao.deleteGeneralBillOrders(jsonArray.getJSONObject(i).getInt("orderId"));
					}
				}
			}
			resultMap.put("desc", "操作成功！");
			resultMap.put("flag", true);
		} catch (Exception e) {
			LogExceptionStackUtil.LogExceptionStack(e);
			resultMap.put("desc", "操作失败！");
			resultMap.put("flag", false);
		}
		return resultMap;
	}


	@Override
	public List<GeneralBills> getGeneralBillsList(int virtualId,
												  String payStatus) throws Exception {
		return generalBillsDao.getGeneralBillsList(virtualId, payStatus);
	}


	@Override
	public Map<String, String> updateGeneralBillPaystatus(String virtualId, String billId,
														  String payFee, String dedFee, String operateUser) {
		Map<String, String> retMap = new HashMap<String, String>();
		try {
			VirtualArchitecture virtual      = propertyDao.getVirtualArchitectureById(Integer.parseInt(virtualId));
			BigDecimal          payFee_      = new BigDecimal(payFee);
			BigDecimal          dedFee_      = new BigDecimal(dedFee);
			BigDecimal          fromTotalFee = payFee_.add(dedFee_);
			if (virtual.getReserveBalance().compareTo(dedFee_) >= 0) {
				//所有未支付账单
				if ("-1".equals(billId)) {
					List<GeneralBills> bills    = generalBillsDao.getGeneralBillsList(Integer.parseInt(virtualId), "0");
					BigDecimal         totalFee = new BigDecimal(0);
					for (GeneralBills generalBills : bills) {
						totalFee = totalFee.add(generalBills.getTotalFee());
					}
					//如果相等
					if (totalFee.compareTo(fromTotalFee) == 0) {
						StringBuffer remark     = new StringBuffer();
						BigDecimal   tempDedFee = dedFee_;
						for (GeneralBills bill : bills) {
							//存款抵扣
							if (payFee_.compareTo(new BigDecimal(0)) == 0) {
								bill.setPayFee(new BigDecimal(0.00));
								bill.setDedFee(bill.getTotalFee());
								remark.append(bill.getOutMonth() + "账单扣减;");
							}
							//实收
							else if (dedFee_.compareTo(new BigDecimal(0)) == 0) {
								bill.setPayFee(bill.getTotalFee());
								bill.setDedFee(new BigDecimal(0.00));
							}
							//混合支付（实收+预存款一起用）
							else {
								if (payFee_.compareTo(bill.getTotalFee()) >= 0) {
									bill.setPayFee(bill.getTotalFee());
									bill.setDedFee(new BigDecimal(0.00));
									payFee_ = payFee_.subtract(bill.getTotalFee());
								} else {
									if (payFee_.compareTo(new BigDecimal(0)) == 0) {
										bill.setPayFee(new BigDecimal(0.00));
										bill.setDedFee(bill.getTotalFee());
										dedFee_ = dedFee_.subtract(bill.getTotalFee());

										remark.append(bill.getOutMonth() + "账单扣减;");
									} else {
										BigDecimal tempFee = bill.getTotalFee().subtract(payFee_);
										bill.setPayFee(payFee_);
										bill.setDedFee(tempFee);
										dedFee_ = dedFee_.subtract(tempFee);

										remark.append(bill.getOutMonth() + "账单扣减;");
									}
								}
							}
							bill.setPayStatus("1");
							bill.setPayTime(new Date());
							bill.setPayType("cash");  //默认现金
							bill.setModifier(operateUser);
							bill.setModifyTime(new Date());
							generalBillsDao.updateObj(bill);
						}
						if (tempDedFee.compareTo(new BigDecimal(0)) > 0) {
							updateVirtualReserveBalance(virtual, tempDedFee, operateUser, remark.toString());
						}
					} else {
						retMap.put("dealFlag", "fail");
						retMap.put("resultDesc", "更新失败，未缴合计金额与收款总金额不匹配");
					}
				}
				//更新某月未付账单
				else {
					GeneralBills bill     = generalBillsDao.getGeneralBillsById(Integer.parseInt(billId));
					BigDecimal   totalFee = bill.getTotalFee();
					StringBuffer remark   = new StringBuffer();
					//如果相等
					if (totalFee.compareTo(fromTotalFee) == 0) {
						//存款抵扣
						if (payFee_.compareTo(new BigDecimal(0)) == 0) {
							bill.setPayFee(new BigDecimal(0.00));
							bill.setDedFee(bill.getTotalFee());
							remark.append(bill.getOutMonth() + "账单扣减;");
						}
						//实收
						else if (dedFee_.compareTo(new BigDecimal(0)) == 0) {
							bill.setPayFee(bill.getTotalFee());
							bill.setDedFee(new BigDecimal(0.00));
						}
						//混合支付（实收+存款一起用）
						else {
							bill.setPayFee(payFee_);
							bill.setDedFee(dedFee_);
						}
						bill.setPayStatus("1");
						bill.setPayTime(new Date());
						bill.setPayType("cash");  //默认现金
						bill.setModifier(operateUser);
						bill.setModifyTime(new Date());
						generalBillsDao.updateObj(bill);
						if (dedFee_.compareTo(new BigDecimal(0)) > 0) {
							updateVirtualReserveBalance(virtual, dedFee_, operateUser, remark.toString());
						}
					} else {
						retMap.put("dealFlag", "fail");
						retMap.put("resultDesc", "更新失败，未缴合计金额与收款总金额不匹配");
					}
				}
			} else {
				retMap.put("dealFlag", "fail");
				retMap.put("resultDesc", "更新失败，预存款余额信息不匹配");
			}
		} catch (Exception e) {
			log.error("updateGeneralBillPaystatus occur error." + LogExceptionStackUtil.LogExceptionStack(e));
			retMap.put("dealFlag", "fail");
			retMap.put("resultDesc", "系统异常，请稍后再试或者联系管理员");
		}
		return retMap;
	}

	private void updateVirtualReserveBalance(VirtualArchitecture virtual, BigDecimal dedFee_, String operateUser, String remark) {
		DepositRecord record = new DepositRecord();
		record.setVirtualId(virtual.getId());
		record.setOrganizationId(virtual.getOrganizationId());
		record.setStatus("-1");
		record.setAmountFee(dedFee_);
		record.setRemark(remark.toString());
		record.setCreator(operateUser);
		record.setCreateTime(new Date());
		generalBillsDao.saveObj(record);

		//更新预存款余额
		virtual.setReserveBalance(virtual.getReserveBalance().subtract(dedFee_));
		virtual.setModifier(operateUser);
		virtual.setModifyTime(new Date());
		propertyDao.updateObj(virtual);
	}


	@Override
	public List<Map<String, Object>> getHistoryBill(Integer generalBillsId, String starTime,
													String endTime, String organizationId, String virtualId) throws Exception {
		List<Map<String, Object>> list = generalBillsDao.getHistoryBill(generalBillsId, starTime, endTime, organizationId, virtualId);
		for (int i = 0; i < list.size(); i++) {
			Map<String, Object>      map          = list.get(i);
			StringBuffer             stringBuffer = new StringBuffer();
			List<GeneralbillService> lists        = generalBillsDao.getGeneralbillServiceList(Integer.parseInt(map.get("ID").toString()));
			for (GeneralbillService service : lists) {
				stringBuffer.append(service.getServiceName() + "/");
			}
			if (StringUtils.isNotBlank(stringBuffer.toString())) {
				map.put("serviceName", stringBuffer.toString().substring(0, stringBuffer.toString().length() - 1));
				list.set(i, map);
			}
		}
		return list;
	}
}
