package com.cku.oa.finance.web;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.Hashtable;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import com.google.common.collect.Maps;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.util.CollectionUtils;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.servlet.mvc.support.RedirectAttributes;

import com.cku.core.ResultDto;
import com.cku.core.ZAErrorCode;
import com.cku.core.ZAException;
import com.cku.oa.finance.entity.PaymentOrder;
import com.cku.oa.finance.entity.PaymentOrderDetail;
import com.cku.oa.finance.entity.PaymentOrderRefund;
import com.cku.oa.finance.service.PaymentChargingItemService;
import com.cku.oa.finance.service.PaymentOrderRefundService;
import com.cku.oa.finance.service.PaymentOrderService;
import com.google.common.collect.Lists;
import com.thinkgem.jeesite.common.config.Global;
import com.thinkgem.jeesite.common.persistence.Page;
import com.thinkgem.jeesite.common.utils.IdGen;
import com.thinkgem.jeesite.common.utils.StringUtils;
import com.thinkgem.jeesite.common.utils.excel.ExportExcel;
import com.thinkgem.jeesite.common.utils.excel.ImportExcel;
import com.thinkgem.jeesite.common.web.BaseController;
import com.thinkgem.jeesite.modules.sys.utils.UserUtils;

import edu.emory.mathcs.backport.java.util.Arrays;

/**
 * 退费记录Controller
 * @author Sunny
 * @version 2021-06-17
 */
@Controller
@RequestMapping(value = "${adminPath}/finance/paymentOrderRefund")
public class PaymentOrderRefundController extends BaseController {
	@Autowired
	private PaymentOrderService paymentOrderService;
	@Autowired
	private PaymentChargingItemService paymentChargingItemService;
	@Autowired
	private PaymentOrderRefundService paymentOrderRefundService;
	
	@ModelAttribute
	public PaymentOrderRefund get(@RequestParam(required=false) String id) {
		PaymentOrderRefund entity = null;
		if (StringUtils.isNotBlank(id)){
			entity = paymentOrderRefundService.get(id);
		}
		if (entity == null){
			entity = new PaymentOrderRefund();
		}
		return entity;
	}
	
	@RequiresPermissions("finance:paymentOrderRefund:edit")
	@RequestMapping(value = {"list", ""})
	public String list(PaymentOrderRefund paymentOrderRefund, HttpServletRequest request, HttpServletResponse response, Model model) {
		boolean auditPermission = UserUtils.getSubject().isPermitted("finance:paymentOrderRefund:audit");
		if(!auditPermission) {
			paymentOrderRefund.setCreateBy(UserUtils.getUser());
		}
		Page<PaymentOrderRefund> reqPage = new Page<PaymentOrderRefund>(request, response);
		reqPage.setOrderBy("process_state asc,create_date desc,process_time desc");
		Page<PaymentOrderRefund> page = paymentOrderRefundService.findPage(reqPage, paymentOrderRefund); 
		model.addAttribute("page", page);
		model.addAttribute("currentUser",UserUtils.getUser());
		return "oa/finance/paymentOrderRefundList";
	}

	@RequiresPermissions("finance:paymentOrderRefund:edit")
	@RequestMapping(value = "form")
	public String form(PaymentOrderRefund paymentOrderRefund, Model model) {
		model.addAttribute("paymentOrderRefund", paymentOrderRefund);
		model.addAttribute("itemList", paymentChargingItemService.findRefundItemList());
		if(StringUtils.isNotBlank(paymentOrderRefund.getId())) {
			return "oa/finance/paymentOrderRefundEdit";
		}
		return "oa/finance/paymentOrderRefundForm";
	}
	
	@RequiresPermissions("finance:paymentOrderRefund:edit")
	@RequestMapping(value = "save")
	@ResponseBody
	public ResultDto<Boolean> save(@RequestBody List<PaymentOrderRefund> refundList, Model model) {
		//退款记录保存
		try {
			paymentOrderRefundService.saveBatch(refundList);
		} catch (Exception e) {
			return ResultDto.error(ZAErrorCode.ZA_ERC_UNKNOWN, e.getMessage());
		}
		//返回处理结果
		return ResultDto.success(Boolean.TRUE);
	}
	
	@RequiresPermissions("finance:paymentOrderRefund:edit")
	@RequestMapping(value = "edit")
	@ResponseBody
	public ResultDto<Boolean> edit(PaymentOrderRefund orderRefund, Model model) {
		//退款记录修改
		try {
			paymentOrderRefundService.update(orderRefund);
		} catch (Exception e) {
			return ResultDto.error(ZAErrorCode.ZA_ERC_UNKNOWN, e.getMessage());
		}
		//返回处理结果
		return ResultDto.success(Boolean.TRUE);
	}
	
	@RequiresPermissions("finance:paymentOrderRefund:audit")
	@RequestMapping(value = "audit")
	@ResponseBody
	public ResultDto<Boolean> audit(@RequestBody List<String> refundOrderIds, Model model, RedirectAttributes redirectAttributes) {
		//退款处理
		try {
			paymentOrderRefundService.applyRefund(refundOrderIds);
		} catch (Exception e) {
			return ResultDto.error(ZAErrorCode.ZA_ERC_UNKNOWN, e.getMessage());
		}
		//返回处理结果
		return ResultDto.success(Boolean.TRUE);
	}
	
	@RequiresPermissions("finance:paymentOrderRefund:edit")
	@RequestMapping(value = "delete")
	public String delete(PaymentOrderRefund paymentOrderRefund, RedirectAttributes redirectAttributes) {
		if(!"0".equals(paymentOrderRefund.getProcessState())) {
			addMessage(redirectAttributes,"错误提示","已处理的退费记录不允许删除！");
		}else {
			paymentOrderRefundService.delete(paymentOrderRefund);
			addMessage(redirectAttributes, "删除退费记录成功");
		}
		return "redirect:"+Global.getAdminPath()+"/finance/paymentOrderRefund/?repage";
	}
	
	@RequiresPermissions("finance:paymentOrderRefund:edit")
	@RequestMapping(value = "/order/{orderCode}")
	public String order(@PathVariable("orderCode") String orderCode, Model model) {
		try {
			//1、校验订单是否存在
			if (StringUtils.isEmpty(orderCode)) {
				throw new ZAException(ZAErrorCode.ZA_ERC_UNKNOWN, "订单号不能为空");
			}
			PaymentOrder order = paymentOrderService.getByOrderCode(orderCode);
			if (Objects.isNull(order) || StringUtils.isBlank(order.getId())) {
				throw new ZAException(ZAErrorCode.ZA_ERC_UNKNOWN, "订单不存在，请输入正确的订单号");
			}
			List<PaymentOrderDetail> orderDetailList = paymentOrderService.findOrderDetailByOrderCode(order.getOrderCode());
			//2、校验是否已提交过该订单的退款记录
			paymentOrderRefundService.checkRefundRecord(Arrays.asList(new String[]{orderCode}));
			//3、校验订单是否可退款
			paymentOrderRefundService.checkRefund(order,orderDetailList);
			//4、返回对象信息
			model.addAttribute("order",PaymentOrderRefund.builder()
					.orderCode(order.getOrderCode())
					.memberCode(order.getMemberCode())
					.memberName(order.getMemberName())
					.totalPrice(order.getTotalPrice())
					.partRefundPrice(order.getTotalPrice())
					.refundRemark("订单退费-原订单号" + order.getOrderCode()+"。")
					.build());
			model.addAttribute("itemList", paymentChargingItemService.findRefundItemList());
			model.addAttribute("partId", IdGen.uuid());
		}catch (ZAException e) {
			e.printStackTrace();
			model.addAttribute("errorMsg",e.getMessage());
		}catch (Exception e) {
			e.printStackTrace();
			model.addAttribute("errorMsg","后台处理异常，请联系管理员！");
		}
		return "oa/finance/paymentOrderRefundRecord";
	}
	
	
	/**
	 * 订单导入
	 */
	@RequiresPermissions("finance:paymentOrderRefund:edit")
	@RequestMapping(value = "import", method = RequestMethod.POST)
	public String importFile(@RequestParam MultipartFile file, Model model,RedirectAttributes redirectAttributes) {
		try {
			ImportExcel ei = new ImportExcel(file, 0, 0);
			int maxRow = ei.getLastDataRowNum();
			List<String> orderCodes = Lists.newArrayList();
			Map<String,String> remarkMap = Maps.newHashMap();
			for (int i = 2; i < maxRow; i++) {
				Object orderCode = ei.getCellValue(ei.getRow(i), 4);
				if (Objects.nonNull(orderCode) && StringUtils.isNotBlank(orderCode.toString())) {
					orderCodes.add(orderCode.toString());
					Object remark = ei.getCellValue(ei.getRow(i), 7);
					if (Objects.nonNull(remark) && StringUtils.isNotBlank(remark.toString())) {
						remarkMap.put(orderCode.toString(), remark.toString());
					}
				}
			}
			if(CollectionUtils.isEmpty(orderCodes)) {
				throw new ZAException(ZAErrorCode.ZA_ERC_UNKNOWN, "请使用正确的Excel模板导入");
			}
			if(orderCodes.size()>999) {
				throw new ZAException(ZAErrorCode.ZA_ERC_UNKNOWN, "超过最大导入条数请分批导入，最大支持导入999条！");
			}
			
			//校验订单是否有重复记录
			Map<String, Long> map = orderCodes.stream().collect(Collectors.groupingBy(p -> p,Collectors.counting()));
			if(map.size() < orderCodes.size()) {
				List<String> repeatOrder = new ArrayList<>();
				map.forEach((key,value)->{
					if(value > 1L) {
						repeatOrder.add(key);
					}
				});
				throw new ZAException(ZAErrorCode.ZA_ERC_UNKNOWN,"订单号"+String.join(",",repeatOrder)+"重复，请修改后重试！");
			}

			List<PaymentOrder> orderList = paymentOrderService.getByOrderCodes(orderCodes);
			//1、校验订单记录是否存在
			if (CollectionUtils.isEmpty(orderList) || orderList.size() != orderCodes.size()) {
				orderCodes.removeAll(orderList.stream().map(PaymentOrder::getOrderCode).collect(Collectors.toList()));
				throw new ZAException(ZAErrorCode.ZA_ERC_UNKNOWN, "订单号"+String.join(",",orderCodes)+"不存在，请填写正确的订单号");
			}
			//2、校验是否已提交过该订单的退款记录
			paymentOrderRefundService.checkRefundRecord(orderCodes);
			List<PaymentOrderDetail> orderDetailList = paymentOrderService.findOrderDetailByOrderCodes(orderCodes);
			Map<String,List<PaymentOrderDetail>> detailMap = orderDetailList.stream().collect(Collectors.groupingBy(PaymentOrderDetail::getOrderCode,Collectors.toList()));
			//3、校验订单是否可退款
			orderList.forEach(order->{
				paymentOrderRefundService.checkRefund(order,detailMap.get(order.getOrderCode()));
			});
			//4、返回对象信息
			List<PaymentOrderRefund> orderRefunds = orderList.stream().map(order->{
				//设置备注
				String refundRemark = remarkMap.get(order.getOrderCode());
				if (Objects.isNull(refundRemark)) {
					refundRemark = "";
				} else {
					refundRemark += "; ";
				}
				refundRemark += "订单退费-原订单号" + order.getOrderCode() + "。";
				//build列表页参数
				PaymentOrderRefund refund = PaymentOrderRefund.builder()
				.orderCode(order.getOrderCode())
				.memberCode(order.getMemberCode())
				.memberName(order.getMemberName())
				.totalPrice(order.getTotalPrice())
				.partRefundPrice(order.getTotalPrice())
				.refundRemark(refundRemark)
				.build();
				refund.setId(IdGen.uuid());
				return refund;
			}).collect(Collectors.toList());
			model.addAttribute("orderRefunds",orderRefunds);
			model.addAttribute("itemList", paymentChargingItemService.findRefundItemList());
		} catch (Exception e) {
			addMessage(redirectAttributes,"错误提示","导入失败！失败信息：" + e.getMessage());
			return "redirect:"+Global.getAdminPath()+"/finance/paymentOrderRefund/?repage";
		}
		return "oa/finance/paymentOrderRefundForm";
	}
	
	
	@RequiresPermissions("finance:paymentOrderRefund:edit")
    @RequestMapping(value = "import/template")
    public String importFileTemplate(HttpServletResponse response, RedirectAttributes redirectAttributes) {
		try {
            String fileName = "退费订单导入模板.xlsx";
    		List<PaymentOrderRefund> list = Lists.newArrayList();
    		list.add(PaymentOrderRefund.builder()
    	    		.index("1")
    	    		.memberName("韩梅梅")
    	    		.memberCode("10000")
    	    		.kennelName("梅梅犬舍")
    	    		.orderCode("20210621198273@10000")
    	    		.totalPrice("1100")
    	    		.partRefundPrice("1000")
					.refundRemark("备注")
					.build());
    		new ExportExcel("退费订单明细表", PaymentOrderRefund.class, 2).setDataList(list).write(response, fileName).dispose();
    		return null;
		} catch (Exception e) {
			addMessage(redirectAttributes, "导入模板下载失败！失败信息："+e.getMessage());
		}
		return "redirect:"+Global.getAdminPath()+"/finance/paymentOrderRefund/?repage";
    }

}