package cn.superdesk.uniorder.controller.invoice.supplier;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.superdesk.uniorder.common.constants.ResponseMsgConstants;
import cn.superdesk.uniorder.common.enums.invoice.customer.InvoiceApplyCustomerMakeInvoiceStatusEnum;
import cn.superdesk.uniorder.common.enums.invoice.supplier.InvoiceApplySupplierItemPayOffStatusEnum;
import cn.superdesk.uniorder.common.enums.invoice.supplier.InvoiceApplySupplierPayOffAccountStatusEnum;
import cn.superdesk.uniorder.common.enums.pay.UnifiedOrderPayTypeEnum;
import cn.superdesk.uniorder.common.enums.accounting.customer.AccountingOrderCustomerAccountingStatusEnum;
import cn.superdesk.uniorder.common.enums.accounting.AccountingOrderInvoiceApplyStatusEnum;
import cn.superdesk.uniorder.common.exception.utils.ExceptionUtils;
import cn.superdesk.uniorder.common.json.AnJsonUtils;
import cn.superdesk.uniorder.common.lamda.AnLamdaUtils;
import cn.superdesk.uniorder.common.numerical.AnBeanUtils;
import cn.superdesk.uniorder.common.rest.response.R;
import cn.superdesk.uniorder.common.rest.response.ResponseResultOuterUtils;
import cn.superdesk.uniorder.controller.base.BaseController;
import cn.superdesk.uniorder.dao.entity.accounting.unified.supplier.AccountingUnifiedSupplier;
import cn.superdesk.uniorder.dao.entity.invoice.supplier.InvoiceApplySupplier;
import cn.superdesk.uniorder.dto.param.invoice.supplier.InvoiceApplySupplierOpApplyPreViewQueryCriteria;
import cn.superdesk.uniorder.dto.param.invoice.supplier.InvoiceApplySupplierOpApplyForm;
import cn.superdesk.uniorder.dto.param.invoice.supplier.InvoiceApplySupplierPageVoListQueryCriteria;
import cn.superdesk.uniorder.dto.param.invoice.supplier.status.InvoiceApplySupplierOpCommonDimAccountingOrderForm;
import cn.superdesk.uniorder.dto.param.invoice.supplier.status.InvoiceApplySupplierOpCommonDimAccountingOrderItem;
import cn.superdesk.uniorder.dto.vo.invoice.supplier.*;
import cn.superdesk.uniorder.dubbo.consumer.accounting.supplier.AccountingUnifiedSupplierDubboConsumerService;
import cn.superdesk.uniorder.dubbo.consumer.invoice.supplier.InvoiceApplySupplierDubboConsumerService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@Api(value = "[开票发票]-供应商结算-开票申请(发票申请管理)", tags = {"[开票发票]-供应商结算-开票申请(发票申请管理)"})
@Slf4j
@RestController
@RequestMapping("/invoice/apply/supplier")
public class InvoiceApplySupplierController extends BaseController {

	@Autowired
	private InvoiceApplySupplierDubboConsumerService invoiceApplySupplierDubboConsumerService;

	@Autowired
	private AccountingUnifiedSupplierDubboConsumerService accountingUnifiedSupplierDubboConsumerService;

	@Deprecated
	@ApiOperation(value = "供应商结算-发票登记管理|货款管理-列表(共用接口) - 弃用", notes = "供应商结算2.0,伪表单计划整改")
	@PostMapping("/getdatapage")
	@ResponseBody
	public R<List<InvoiceApplySupplier>> getInvoiceApplyList() {

		R<List<InvoiceApplySupplier>> response = new R<>();

		try {

			Map<String, Object> params = new HashMap<>();

			params.put("invoiceApplySn", getString("invoiceApplySn")); // 修改标记 20211201

			// 开票状态 0未开票 1 已开票 2重新开票 前端写死了?
			params.put("invoiceStatus", getString("invoiceStatus"));

			// 回款状态
			params.put("backAccountStatus", getString("backAccountStatus"));

			params.put("supplierId", getLong("supplierId"));
			params.put("supplierName", getString("supplierName"));

			// 申请人 姓名
			params.put("applyUserName", getString("applyUserName"));

			params.put("startTime", getString("startTime"));
			params.put("endTime", getString("endTime"));

			log.info("供应商结算-发票登记管理|货款管理-列表(共用接口) - 弃用 - params : \n{}", AnJsonUtils.toJson(params));

			response = invoiceApplySupplierDubboConsumerService.getInvoiceApplySupplierList(getToken(), params, getPageNum(), getPageSize());

			InvoiceApplySupplierHeadVo invoiceApplySupplierHeadVo = invoiceApplySupplierDubboConsumerService.getInvoiceApplyListHeadSum(getToken(), params);

			response.setHeadData(AnBeanUtils.beanToMap(invoiceApplySupplierHeadVo));

		} catch (Exception e) {

			response.setCode(String.valueOf(e.hashCode()));
			response.setSuccess(false);
			response.setMessage(e.getMessage());

			log.error(ExceptionUtils.getMessage(e));
			e.printStackTrace();
		}

		return response;
	}

	@ApiOperation(value = "供应商结算-发票登记管理-列表(共用接口) - 新版", notes = "供应商结算2.0,伪表单计划整改")
	@PostMapping("/getInvoiceApplySupplierPageVoList")
	@ResponseBody
	public R<List<InvoiceApplySupplierPageVo>> getInvoiceApplySupplierPageVoList(@RequestBody InvoiceApplySupplierPageVoListQueryCriteria queryCriteria) {

		R<List<InvoiceApplySupplierPageVo>> response = new R<>();

		try {


			log.info("供应商结算-发票登记管理|货款管理-列表(共用接口) - 新版 queryCriteria : \n{}", AnJsonUtils.toJson(queryCriteria));

			response = invoiceApplySupplierDubboConsumerService.getInvoiceApplySupplierPageVoList(getToken(), queryCriteria);

			Map<String, Object>        params                     = AnBeanUtils.beanToMap(queryCriteria);
			InvoiceApplySupplierHeadVo invoiceApplySupplierHeadVo = invoiceApplySupplierDubboConsumerService.getInvoiceApplyListHeadSum(getToken(), params);

			response.setHeadData(AnBeanUtils.beanToMap(invoiceApplySupplierHeadVo));

		} catch (Exception e) {

			response.setCode(String.valueOf(e.hashCode()));
			response.setSuccess(false);
			response.setMessage(e.getMessage());

			log.error(ExceptionUtils.getMessage(e));
			e.printStackTrace();
		}

		return response;
	}


	@ApiOperation(value = "供应商结算-发票登记管理|货款管理-详情(共用接口)", notes = "供应商结算2.0,伪表单计划整改")
	@PostMapping("/getdetail")
	@ResponseBody
	public R<InvoiceApplySupplierDetailDimGoodsVo> getInvoiceApplySupplierDetailByInvoiceApplySupplierId(@RequestBody InvoiceApplySupplierOpApplyPreViewQueryCriteria queryCriteria) {

		R<InvoiceApplySupplierDetailDimGoodsVo> response = new R<>();

		try {

			InvoiceApplySupplierDetailDimGoodsVo detail = invoiceApplySupplierDubboConsumerService.getInvoiceApplySupplierDetailByInvoiceApplySupplierId(getToken(), queryCriteria.getInvoiceApplyId());

			for (InvoiceApplySupplierDetailDimGoodsItemVo vo : detail.getGoods()) {
				vo.setPayTypeName(UnifiedOrderPayTypeEnum.getDesc(vo.getPayType()));
			}

			response.setData(detail);
			response.setSuccess(true);

		} catch (Exception e) {

			response.setCode(String.valueOf(e.hashCode()));
			response.setSuccess(false);
			response.setMessage(e.getMessage());

			log.error(ExceptionUtils.getMessage(e));
			e.printStackTrace();
		}

		return response;
	}


	@ApiOperation(value = "供应商结算-发票登记管理-opt 申请开票(搜索) 前端修改成 进入页面直接调用出数据", notes = "供应商结算2.0,伪表单计划整改")
	@PostMapping("/getdzgoods")
	@ResponseBody
	public R<List<InvoiceApplySupplierSelectGoodsVo>> getInvoiceApplySelect(@RequestBody InvoiceApplySupplierOpApplyPreViewQueryCriteria queryCriteria) {

		R<List<InvoiceApplySupplierSelectGoodsVo>> response = new R<>();

		try {

			Boolean checkParams = false;

			// 用的是原来的逻辑,有空再想清楚
			if (ObjectUtil.isNotNull(queryCriteria.getAccountingOrderSn())
					|| ObjectUtil.isNotNull(queryCriteria.getOrderSn())
					|| ObjectUtil.isNotNull(queryCriteria.getSupplierName())) {
				checkParams = true;
			}

			if (checkParams.equals(false)) {
				response.setCode(500);
				response.setSuccess(false);
				response.setMessage("请选择一种条件进行搜索 [accountingOrderSn] [orderSn] [supplierName]");
				return response;
			}

//			Map<String, Object> params = new HashMap<>();
//
//			// 对账单编号
//			params.put("accountingOrderSn", getString("accountingOrderSn"));
//			// 订单编号
//			params.put("orderSn", getString("orderSn"));
//			// 供应商名称
//			params.put("supplierName", getString("supplierName"));
//
//			log.info("供应商结算-发票申请管理-opt 申请开票 params: \n{}", AnJsonUtils.toJson(params));

			String accountingOrderSn = queryCriteria.getAccountingOrderSn();

			// TODO 在此加入判定
			AccountingUnifiedSupplier statementOfAccount = accountingUnifiedSupplierDubboConsumerService.findByAccountingOrderSn(accountingOrderSn);

//<!--			已取消(-1, "已取消"),-->
//<!--			未确认(0, "未确认"),-->
//<!--			已确认(1, "已确认"),-->
//<!--			已拒绝(2, "已拒绝"),-->
//<!--			待提交(3, "待提交"),-->
			if (!statementOfAccount.getAccountingStatus().equals(AccountingOrderCustomerAccountingStatusEnum.已确认.getKey())) {
				response.setCode(500);
				response.setSuccess(false);
//                result.setMessage("对账单 对账状态 非[已确认] 不能申请开票");
				response.setMessage("只有 [已确认] 的账单可进行发票申请管理,请选进行商户确认");
				return response;
			}

//<!--			已开票(1, "已开票"),-->
//<!--			未开票(2, "未开票"),-->
//<!--			部分开票(3, "部分开票");-->
			if (statementOfAccount.getInvoiceStatus().equals(AccountingOrderInvoiceApplyStatusEnum.全部申请.getKey())) {
				response.setCode(500);
				response.setSuccess(false);
				response.setMessage("对账单 开票状态 为[已开票] 不能重复申请开票");
				return response;
			}

			// 对账单 部分 申请开票问题未解决
			List<InvoiceApplySupplierSelectGoodsVo> goods = new ArrayList<>();
			// 没有过滤 已经 开票申请的商品
//            goods = unifiedSupplierInvDubboConsumerService.getStatementOfAccountGoodsListByAccountingOrderSn(accountingOrderSn);
			// 过滤 已经 开票申请的商品
			goods = invoiceApplySupplierDubboConsumerService.invoiceApplySelectFocusUnified(accountingOrderSn);

			response.setData(goods);
			response.setSuccess(true);

		} catch (Exception e) {

			response.setCode(String.valueOf(e.hashCode()));
			response.setSuccess(false);
			response.setMessage(e.getMessage());

			log.error(ExceptionUtils.getMessage(e));
			e.printStackTrace();
		}
		return response;
	}


	@ApiOperation(value = "供应商结算-发票登记管理-opt 申请开票 前端结合一键分票逻辑 分别调用", notes = "供应商结算2.0,伪表单计划整改")
	@PostMapping("/apply")
	@ResponseBody
	public R<InvoiceApplySupplier> opInvoiceApply(@RequestBody InvoiceApplySupplierOpApplyForm invoiceApplySupplierOpApplyForm) {

		R<InvoiceApplySupplier> response = new R<>();

		try {

//			if (!StringUtils.isNotEmpty(invoiceApplySupplierOpApplyForm.getJsonStr())) {
//			    return ResponseResultOuterUtils.createErrorResult("500","请选择要对账的商品");
//			}

			if (CollUtil.isEmpty(invoiceApplySupplierOpApplyForm.getPackageList())) {
				return ResponseResultOuterUtils.createErrorResult("500", "请选择要对账的商品");
			}

			InvoiceApplySupplier invoiceApplySupplierEntity = invoiceApplySupplierDubboConsumerService.opInvoiceApply(getToken(), invoiceApplySupplierOpApplyForm);

			response.setData(invoiceApplySupplierEntity);
			response.setSuccess(true);

		} catch (Exception e) {

			response.setCode(String.valueOf(e.hashCode()));
			response.setSuccess(false);
			response.setMessage(e.getMessage());

			log.error(ExceptionUtils.getMessage(e));
			e.printStackTrace();
		}

		return response;
	}

	@Deprecated
	@ApiOperation(value = "供应商结算-发票登记管理-opt row 开票登记", notes = "供应商结算2.0,未整改")
	@PostMapping("/register")
	@ResponseBody
	public R<InvoiceApplySupplier> opRegister() {

		R<InvoiceApplySupplier> response = new R<>();

		try {
			Long   id              = getLong("id");
			String invoiceNumber   = getString("invoiceNumber");
			String makeInvoiceTime = getString("makeInvoiceTime");

			SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");

			InvoiceApplySupplier forUpdateInvoiceApplySupplier = new InvoiceApplySupplier();

			forUpdateInvoiceApplySupplier.setId(id);
			forUpdateInvoiceApplySupplier.setMakeInvoiceTime(sdf.parse(makeInvoiceTime));
			forUpdateInvoiceApplySupplier.setInvoiceNumber(invoiceNumber);
			forUpdateInvoiceApplySupplier.setMakeInvoiceStatus(InvoiceApplyCustomerMakeInvoiceStatusEnum.已开票.getKey());

			InvoiceApplySupplier invoiceApplySupplier = invoiceApplySupplierDubboConsumerService.updateObj(getToken(), forUpdateInvoiceApplySupplier);

			response.setData(invoiceApplySupplier);
			response.setSuccess(true);

		} catch (Exception e) {

			response.setCode(String.valueOf(e.hashCode()));
			response.setSuccess(false);
			response.setMessage(e.getMessage());

			log.error(ExceptionUtils.getMessage(e));
			e.printStackTrace();
		}

		return response;
	}

	@Deprecated
	@ApiOperation(value = "供应商结算-货款管理-opt row 确定付款", notes = "供应商结算2.0,未整改")
	@PostMapping("/payment")
	@ResponseBody
	public R<InvoiceApplySupplier> opConfirmPay() {

		R<InvoiceApplySupplier> response = new R<>();

		try {
			Long id = getLong("id");

			InvoiceApplySupplier invoiceApplySupplier4Update = new InvoiceApplySupplier();
			invoiceApplySupplier4Update.setId(id);
			invoiceApplySupplier4Update.setPayoffAccountStatus(InvoiceApplySupplierItemPayOffStatusEnum.已付款.getKey());

			InvoiceApplySupplier invoiceApplySupplier = invoiceApplySupplierDubboConsumerService.opConfirmPay(getToken(), invoiceApplySupplier4Update);

			response.setData(invoiceApplySupplier);
			response.setSuccess(true);

		} catch (Exception e) {

			response.setCode(String.valueOf(e.hashCode()));
			response.setSuccess(false);
			response.setMessage(e.getMessage());

			log.error(ExceptionUtils.getMessage(e));
			e.printStackTrace();
		}

		return response;
	}

	/**
	 * 供应商结算-货款管理-opt row 删除
	 * /invoice/apply/supplier/opDelete/{invoiceApplyId}
	 *
	 * @return
	 */
	@ApiOperation(value = "供应商结算-货款管理-opt row 物理删除", notes = "供应商结算2.0,未整改")
	@RequestMapping(value = "/opDelete/{invoiceApplyId}", method = RequestMethod.GET)
	@ResponseBody
	public R<?> opDelete(@PathVariable("invoiceApplyId") Long invoiceApplyId) {

		R<?> response = new R<>();

		try {

			InvoiceApplySupplier entity = invoiceApplySupplierDubboConsumerService.findById(invoiceApplyId);

			// TODO 逻辑判定 如果有的话

			invoiceApplySupplierDubboConsumerService.opPhysicsDelete(getToken(), entity);

			response.setSuccess(true);
			response.setMessage("删除成功");

		} catch (Exception e) {

			response.setSuccess(false);
			response.setMessage(ResponseMsgConstants.ERROR_UNKNOW);

			log.error(ExceptionUtils.getMessage(e));

			e.printStackTrace();

		}

		return response;
	}

	@Deprecated
	@ApiOperation(value = "供应商结算-货款管理-opt row 重新开票", notes = "供应商结算2.0,未整改")
	@PostMapping("/openagain")
	@ResponseBody
	public R<InvoiceApplySupplier> opBecomeInvalid() {

		R<InvoiceApplySupplier> response = new R<>();

		try {

			Long invoiceApplyId = getLong("id");

			InvoiceApplySupplier entity = invoiceApplySupplierDubboConsumerService.findById(invoiceApplyId);

			// TODO 逻辑判定 如果有的话

			invoiceApplySupplierDubboConsumerService.opBecomeInvalid(getToken(), entity);

			response.setSuccess(true);

		} catch (Exception e) {

			response.setCode(String.valueOf(e.hashCode()));
			response.setSuccess(false);
			response.setMessage(e.getMessage());

			log.error(ExceptionUtils.getMessage(e));
			e.printStackTrace();
		}

		return response;
	}

	@ApiOperation(value = "InvoiceApplySupplier - InvoiceStatus - 对账单维度 - 操作 op撤销开票")
	@RequestMapping(value = "/opBecomeInvalid/dim/accountingOrder", method = RequestMethod.POST)
	@ResponseBody
	public R<?> opBecomeInvalidDimAccountingOrder(@RequestBody InvoiceApplySupplierOpCommonDimAccountingOrderForm form) {

		R<?> response = new R<>();

		// TODO 简单验证

		if (CollUtil.isEmpty(form.getInvoiceApplySupplierList())) {
			return ResponseResultOuterUtils.createErrorResult("500", "提交的数据异常");
		}

		try {

			List<Long> invoiceApplyIds = form.getInvoiceApplySupplierList().stream().map(InvoiceApplySupplierOpCommonDimAccountingOrderItem::getInvoiceApplyId).collect(Collectors.toList());

			List<InvoiceApplySupplier> entitys = invoiceApplySupplierDubboConsumerService.findByIds(invoiceApplyIds);

			if (CollUtil.isEmpty(invoiceApplyIds)) {
				return ResponseResultOuterUtils.createErrorResult("500", "提交的数据异常");
			}
			if (CollUtil.isEmpty(entitys)) {
				return ResponseResultOuterUtils.createErrorResult("500", "提交的数据异常");
			}
			if (invoiceApplyIds.size() != entitys.size()) {
				return ResponseResultOuterUtils.createErrorResult("500", "提交的数据异常");
			}

			/****************************************** 申请状态 start ******************************************/

			List<Integer> invoiceStatus = entitys.stream().filter(AnLamdaUtils.distinctByKey(o -> o.getInvoiceStatus())).map(InvoiceApplySupplier::getInvoiceStatus).collect(Collectors.toList());

			if (CollUtil.isEmpty(invoiceStatus)) {
				return ResponseResultOuterUtils.createErrorResult("500", "提交的数据异常");
			}
			if (invoiceStatus.size() > 1) {
				return ResponseResultOuterUtils.createErrorResult("500", "提交的数据异常");
			}

			List<Integer> payoffAccountStatus = entitys.stream().filter(AnLamdaUtils.distinctByKey(o -> o.getPayoffAccountStatus())).map(InvoiceApplySupplier::getPayoffAccountStatus).collect(Collectors.toList());

			if (CollUtil.isEmpty(payoffAccountStatus)) {
				return ResponseResultOuterUtils.createErrorResult("500", "提交的数据异常");
			}
			if (payoffAccountStatus.size() > 1) {
				return ResponseResultOuterUtils.createErrorResult("500", "提交的数据异常");
			}

			InvoiceApplySupplierPayOffAccountStatusEnum invoiceApplySupplierPayOffAccountStatusEnum = InvoiceApplySupplierPayOffAccountStatusEnum.get(payoffAccountStatus.get(0));

			if (invoiceApplySupplierPayOffAccountStatusEnum == InvoiceApplySupplierPayOffAccountStatusEnum.付款中 || invoiceApplySupplierPayOffAccountStatusEnum == InvoiceApplySupplierPayOffAccountStatusEnum.已付款) {
				return ResponseResultOuterUtils.createErrorResult("500", "提交的数据异常,要求状态不为[付款中] [已付款],");
			}



			String report = invoiceApplySupplierDubboConsumerService.opBecomeInvalid(getToken(), entitys, form);


			response.setSuccess(true);
			response.setMessage(report);

		} catch (Exception e) {

			response.setSuccess(false);
			response.setMessage(ResponseMsgConstants.ERROR_UNKNOW);
			log.error(ExceptionUtils.getMessage(e));
			e.printStackTrace();
		}
		return response;
	}


	@ApiOperation(value = "InvoiceApplySupplier - Remark - 对账单维度 - 操作 op备注")
	@RequestMapping(value = "/opSetRemark/dim/accountingOrder", method = RequestMethod.POST)
	@ResponseBody
	public R<?> opSetRemarkDimAccountingOrder(@RequestBody InvoiceApplySupplierOpCommonDimAccountingOrderForm form) {

		R<?> result = new R<>();

		// TODO 简单验证

		if (CollUtil.isEmpty(form.getInvoiceApplySupplierList())) {
			return ResponseResultOuterUtils.createErrorResult("500", "提交的数据异常");
		}

		int count = 0;

		try {

			List<Long> invoiceApplyIds = form.getInvoiceApplySupplierList().stream().map(InvoiceApplySupplierOpCommonDimAccountingOrderItem::getInvoiceApplyId).collect(Collectors.toList());

			List<InvoiceApplySupplier> entitys = invoiceApplySupplierDubboConsumerService.findByIds(invoiceApplyIds);

			if (CollUtil.isEmpty(invoiceApplyIds)) {
				return ResponseResultOuterUtils.createErrorResult("500", "提交的数据异常");
			}
			if (CollUtil.isEmpty(entitys)) {
				return ResponseResultOuterUtils.createErrorResult("500", "提交的数据异常");
			}
			if (invoiceApplyIds.size() != entitys.size()) {
				return ResponseResultOuterUtils.createErrorResult("500", "提交的数据异常");
			}

//			invoiceApplySupplierDubboConsumerService.opSetRemarkDimAccountingOrder(getToken(), entitys, form);

			entitys.forEach(invoiceApplySupplierIter -> {

				InvoiceApplySupplier invoiceApplySupplier4Update = new InvoiceApplySupplier();
				invoiceApplySupplier4Update.setId(invoiceApplySupplierIter.getId());
				invoiceApplySupplier4Update.setRemark(form.getReason());

				int ret = invoiceApplySupplierDubboConsumerService.updateInvoiceApplySupplierByPrimaryKeySelective(invoiceApplySupplier4Update);

//				if (ret == 1) {
//					count++;
//				}
			});

			result.setSuccess(true);

		} catch (Exception e) {

			result.setSuccess(false);
			result.setMessage(ResponseMsgConstants.ERROR_UNKNOW);
			log.error(ExceptionUtils.getMessage(e));
			e.printStackTrace();
		}
		return result;
	}
}
