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

import cn.superdesk.uniorder.common.enums.accounting.AccountingOrderDimCreateByEnum;
import cn.superdesk.uniorder.common.excel.utils.ExcelExportModePoiHssfUtils;
import cn.superdesk.uniorder.common.excel.ExcelResponse;
import cn.superdesk.uniorder.common.exception.utils.ExceptionUtils;
import cn.superdesk.uniorder.common.json.AnJsonUtils;
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.customer.AccountingUnifiedCustomer;
import cn.superdesk.uniorder.dao.entity.invoice.customer.InvoiceApply;
import cn.superdesk.uniorder.dto.param.invoice.customer.InvoiceApplyCustomerFocusUnifiedOpApplyForm;
import cn.superdesk.uniorder.dto.param.invoice.customer.InvoiceApplyOpCreateSelectedGoodsParams;
import cn.superdesk.uniorder.dto.vo.invoice.customer.ExportExcelInvoiceApplyForceUnifiedDimGoodsVo;
import cn.superdesk.uniorder.dto.vo.invoice.customer.InvoiceApplyCustomerPageVo;
import cn.superdesk.uniorder.dubbo.consumer._permission.PermissionDubboCustomerService;
import cn.superdesk.uniorder.dubbo.consumer.accounting.customer.AccountingUnifiedCustomerDubboConsumerService;
import cn.superdesk.uniorder.dubbo.consumer.invoice.customer.InvoiceApplyCustomerDubboConsumerService;
import cn.superdesk.uniorder.common.numerical.AnCollectionUtils;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.springframework.beans.factory.annotation.Autowired;
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.RestController;

import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;


/**
 * @Description: 客户结算-开票申请
 * @Author: linjinyu 补充 修改
 * @CreateDate: 4/29/20 3:29 PM
 * @UpdateUser: linjinyu
 * @UpdateDate: 4/29/20 3:29 PM
 * @UpdateRemark: 修改内容
 * @Version: 1.0
 */
@Api(value = "客户结算-开票申请)", tags = {"客户结算-开票申请"})
@Slf4j
@RestController
@RequestMapping("/invoice/apply/customer/unified")
public class InvoiceApplyCustomerUnifiedController extends BaseController {

	@Autowired
	private AccountingUnifiedCustomerDubboConsumerService accountingUnifiedCustomerDubboConsumerService;
	@Autowired
	private InvoiceApplyCustomerDubboConsumerService      invoiceApplyCustomerDubboConsumerService;
	@Autowired
	private PermissionDubboCustomerService                permissionDubboCustomerService;


	/**
	 * 客户结算-开票申请-列表
	 *
	 * @return
	 */
	@RequestMapping(value = "/findViewByPage", method = RequestMethod.POST)
	public R<List<InvoiceApplyCustomerPageVo>> findViewByPage() {

		R<List<InvoiceApplyCustomerPageVo>> result = new R<>();

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

		/****************************************** 3、查询栏添加对账单编号查询功能 mark by linjinyu at 20210105 start ******************************************/
		params.put("accountingOrderSn", getString("accountingOrderSn"));
		/****************************************** 3、查询栏添加对账单编号查询功能 mark by linjinyu at 20210105   end ******************************************/

		/**
		 * 时间查询字段
		 * 申请时间
		 * 审核时间
		 */
		params.put("timeField", getString("timeField"));
		// 开始时间
		params.put("startTime", getString("startTime"));
		// 结束时间
		params.put("endTime", getString("endTime"));
		// 审核状态:1-未审核;2-已同意;3-已拒绝;
		params.put("auditStatus", getInteger("auditStatus"));

		// 开票状态;0-未开票;1-已开票;2-重新开票;
		String makeInvoiceStatus = getString("makeInvoiceStatus");
		if (StringUtils.isNotBlank(makeInvoiceStatus)) {
			params.put("makeInvoiceStatus", makeInvoiceStatus.split(","));
		}

		// 企业名称
		params.put("companyName", getString("companyName"));

		// 关键字查询字段
		params.put("keywordsField", getString("keywordsField"));
		// 关键字查询字段
		params.put("keywords", getString("keywords"));

		// 发票号
		params.put("invoiceNumber", getString("invoiceNumber")); // 修改标记 20211201


		/****************************************** 测试用而已 不爽就删除了吧 start ******************************************/

//		Map<String, Object> tokenVo = JwtUtil.getTokenVo(getToken());
//		LoginSysUser loginSysUser = JwtUtil.getLoginSysUser(token);

//		log.info("\n\n\n\nparams \n{}\ntoken  \n{}\nJwt  \n{}\n\n\n\n", JsonUtils.toPrettyJson(params), getToken(), JsonUtils.toPrettyJson(tokenVo));

//		log.info("\nJwt  \n{}",JwtUtil.checkTokenAndGetUserName(getToken()));

//		permissionDubboCustomerService.getPermOutOrgIds(getToken());
//		permissionDubboCustomerService.getPermOutVirtIds(getToken());
//		permissionDubboCustomerService.getSelectPermOrgByToken(getToken());
//		permissionDubboCustomerService.getSelectPermVirtByToken(getToken());

		/****************************************** 测试用而已 不爽就删除了吧   end ******************************************/

		result = invoiceApplyCustomerDubboConsumerService.findViewByPageFocusUnified(getToken(), params, getPageNum(), getPageSize());

		return result;
	}

	/**
	 * 客户结算-开票申请-Head
	 *
	 * @return
	 */
	@RequestMapping(value = "/findViewData", method = RequestMethod.POST)
	public R findViewHeadData() {

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

		/****************************************** 3、查询栏添加对账单编号查询功能 mark by linjinyu at 20210105 start ******************************************/
		params.put("accountingOrderSn", getString("accountingOrderSn"));
		/****************************************** 3、查询栏添加对账单编号查询功能 mark by linjinyu at 20210105   end ******************************************/

		/**
		 * 时间查询字段
		 * 申请时间
		 * 审核时间
		 */
		params.put("timeField", getString("timeField"));
		// 开始时间
		params.put("startTime", getString("startTime"));
		// 结束时间
		params.put("endTime", getString("endTime"));

		// 审核状态:1-未审核;2-已同意;3-已拒绝;
		params.put("auditStatus", getInteger("auditStatus"));

		// 开票状态;0-未开票;1-已开票;2-重新开票;
		String makeInvoiceStatus = getString("makeInvoiceStatus");
		if (StringUtils.isNotBlank(makeInvoiceStatus)) {
			params.put("makeInvoiceStatus", makeInvoiceStatus.split(","));
		}

		// 企业名称
		params.put("companyName", getString("companyName"));

		// 关键字查询字段
		params.put("keywordsField", getString("keywordsField"));
		// 关键字查询字段
		params.put("keywords", getString("keywords"));

		// 发票号
		params.put("invoiceNumber", getString("invoiceNumber")); // 修改标记 20211201

		return new R(invoiceApplyCustomerDubboConsumerService.findViewHeadDataFocusUnified(getToken(), params));
	}

	/**
	 * 客户结算-开票申请-opt 导出报表
	 * web/invoice/apply/customer/unified/getInvoiceApplyExcel
	 *
	 * @param response
	 * @throws IOException
	 */
	@RequestMapping(value = "/getInvoiceApplyExcel", method = RequestMethod.GET)
	public void exportInvoiceApplyExcelFocusUnified(HttpServletResponse response) throws IOException {

		try {

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

			params.put("timeField", getString("timeField"));//时间查询字段
			params.put("startTime", getString("startTime"));//开始时间
			params.put("endTime", getString("endTime"));//结束时间
			params.put("auditStatus", getInteger("auditStatus"));//审核状态

			String makeInvoiceStatus = getString("makeInvoiceStatus");
			if (StringUtils.isNotBlank(makeInvoiceStatus)) {
				params.put("makeInvoiceStatus", makeInvoiceStatus.split(","));//开票状态
			}

			params.put("keywordsField", getString("keywordsField"));//关键字查询字段
			params.put("keywords", getString("keywords"));//关键字查询字段

			List<ExportExcelInvoiceApplyForceUnifiedDimGoodsVo> ls = invoiceApplyCustomerDubboConsumerService.findInvoiceApplyFocusUnifiedDimGoods(params, getToken());

			String[] field = {"parentOrdersn", "", "ordersn", "organizationName", "enterpriseName", "price", "paytypeName", "statusName", "realname",
					"mobile", "addressAddress", "createTime", "merchName", "remark", "", "otherField1", "taxCode", "optionname", "total", "unitPrice",
					"totalPrice", "unit", "taxCode", "addressRealname", "addressMobile", "sendtime", "dispatchPrice", "expressCompanyName", "expressNo", "finishtime", "backAccountStatusName", "invoiceNumber", "makeInvoiceTime", "makeInvoiceStatusName", "invoiceApplySn", "invoiceRemark", "invoiceTitle", "invoiceTypeName"
			};

			String[] fieldZhCn = {"父单编号", "父单金额", "订单编号", "会员所属项目", "会员所属企业(动态)", "订单金额", "支付方式", "订单状态", "下单人姓名",
					"下单人电话", "收货地址", "下单时间", "供应商名称", "买家备注", "卖家备注", "商品信息", "商品编码", "商品规格", "商品数量", "商品单价(折扣后)",
					"商品价格(折扣后)", "商品单位", "财务代码", "收货人姓名", "收货人手机号", "发货时间", "运费", "快递公司", "快递单号", "完成时间", "回款状态", "发票号", "开票时间", "发票状态", "开票申请编号", "开票申请备注", "发票抬头", "发票种类"};

			HSSFWorkbook workbook = ExcelExportModePoiHssfUtils.createWorkbook(ls, fieldZhCn, field, "未对账订单");

//			//准备将Excel的输出流通过response输出到页面下载
//			response.reset();
//			//二进制输出流
//			response.setContentType("application/octet-stream");
//			response.setCharacterEncoding("UTF-8");
//			//这后面可以设置导出Excel的名称,此例中名为student.xls
//			response.setHeader("Content-disposition", "attachment;filename=" + URLEncoder.encode("发票", "UTF-8") + ".xls");
//			//刷新缓冲
//			response.flushBuffer();
//
//			//workbook将Excel写入到response的输出流中,供页面下载
//			workbook.write(response.getOutputStream());

			ExcelResponse.out(workbook, "客户结算" + "_" + "发票(开票申请)" + "_" + "导出报表", response);

		} catch (Exception e) {

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


	/**
	 * 客户结算-开票申请-opt 开票登记
	 *
	 * @return
	 */
	@RequestMapping(value = "/invoiceRegister", method = RequestMethod.POST)
	public R invoiceOptRegister() {

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

		/**
		 * 发票申请Id
		 */
		params.put("id", getString("id"));
		params.put("datestr", getString("datestr"));
		/**
		 * 发票申请Id
		 */
		params.put("invoiceNumber", getString("invoiceNumber"));

		invoiceApplyCustomerDubboConsumerService.opRegister(params, getToken());

		return new R();
	}

	/**
	 * 客户结算-开票申请-发票申请 搜索-出商品 以供选择
	 * 三种方式
	 * 1. 对账单编号
	 * 2. 订单编号
	 * 3. 企业名称
	 * <p>
	 * // TODO 除方式 1 方式 23 可能还有问题 未验证 20200701
	 *
	 * @return
	 */
	@ApiOperation(value = "客户结算-申请开票-opt 搜索")
	@RequestMapping(value = "/invoiceApplySelect", method = RequestMethod.POST)
	public R opApplySelect() {

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


		/****************************************** 重构开始 添加检验 mark by linjinyu at 20210105 start ******************************************/

		String accountingOrderSn = getString("accountingOrderSn");
		if (StringUtils.isBlank(accountingOrderSn)) {
			return ResponseResultOuterUtils.createErrorResult("500", "对账单编号不能为空");
		}

		AccountingUnifiedCustomer check = accountingUnifiedCustomerDubboConsumerService.findByAccountingOrderSn(accountingOrderSn);
		if (null == check) {
			return ResponseResultOuterUtils.createErrorResult("500", "对账单不存在");
		}
		if (!check.getAccountingStatus().equals(1)) {
			return ResponseResultOuterUtils.createErrorResult("500", "对账单未确认");
		}
		if (check.getInvoiceStatus().equals(1)) {
			return ResponseResultOuterUtils.createErrorResult("500", "对账单已全部申请开票");
		}

		/****************************************** 重构开始 添加检验 mark by linjinyu at 20210105 start ******************************************/

		/****************************************** 下拉 start ******************************************/
		// 客户结算 对账单 编号
		params.put("accountingOrderSn", accountingOrderSn);

		// 下单人 企业名称 ---- 禁用
		params.put("purchaseVirtId", getLong("purchaseVirtId"));
		params.put("purchaseVirtName", getString("purchaseVirtName"));

		// 订单编号 ---- 禁用
		params.put("orderSn", getString("orderSn"));
		/****************************************** 下拉   end ******************************************/

		// 对账单状态,0-未确认,1-已确认,-1-已取消
		params.put("accountingStatus", 1);

		log.info("客户结算 -> 发票申请 -> 申请开票 预览页 {}", AnJsonUtils.toJson(params));


//		SELECT
//				auc.id AS accounting_order_id,
//				auc.accounting_order_sn,
//				auc.invoice_company_name,
//				auco.id,
//				auco.order_sn AS order_sn,
//				se.enterprise_id AS purchase_virt_id,
//				se.enterprise_name AS purchase_virt_name,
//				uog.`id` AS goods_id,
//				uog.quantity * uog.price AS `price`,
//				uog.quantity AS quantity,
//				uog.unit AS unit,
//				uog.price AS unit_price,
//				uog.goods_name AS goods_name,
//				uog.fiscal_code,
//				uog.tax_code,
//				uog.tax_rate,
//				real_order_user.realname
//		FROM
//			(accounting_unified_customer_order auco RIGHT JOIN unified_order_goods uog ON auco.order_sn = uog.order_sn )
//		    LEFT JOIN sys_oder_user real_order_user ON auco.realname_id = real_order_user.user_id
//		    LEFT JOIN accounting_unified_customer auc ON auco.dz_id = auc.id
//		    LEFT JOIN sys_enterprise se ON auc.enterprise_id = se.enterprise_id
//		WHERE
//		    NOT EXISTS(
//				SELECT
//		            1
//		        FROM
//		            invoice_order IO
//		            JOIN invoice_apply ir ON IO.invoice_apply_id = ir.id
//		        WHERE IO.dz_good_id = uog.id AND ir.audit_status IN(1, 2)
//)
//		    AND auc.accounting_order_sn LIKE CONCAT(CONCAT('%', 'DZ2020123000016'),'%')
//		    and auc.accounting_status =1

		// 有时候查不出数据是 因为 auc.accounting_status =1 对账单(结算单)状态:0-未确认;1-已确认;-1-已取消;

		/****************************************** 重构开始 mark by linjinyu at 20210105 start ******************************************/

		// 对账单 创建维度:0-订单;1-商品;2-流水;
		switch (AccountingOrderDimCreateByEnum.get(check.getDimCreateBy())) {
			case 订单:
				// TODO 待重构
				return new R(invoiceApplyCustomerDubboConsumerService.invoiceApplySelectFocusUnifiedDimOrder(params));
			case 商品:
//				return ResponseResultUtil.createErrorResult("500", "对账单(维度商品)TO DO");
				return new R(invoiceApplyCustomerDubboConsumerService.invoiceApplySelectFocusUnifiedDimGoods(params));
			case 流水:
				return ResponseResultOuterUtils.createErrorResult("500", "对账单(维度流水) 未支持");
			default:
				return ResponseResultOuterUtils.createErrorResult("500", "对账单 未支持");
		}

		/****************************************** 重构开始 mark by linjinyu at 20210105   end ******************************************/


	}

	/**
	 * TODO 一般订单
	 * 客户结算-开票申请-opt 申请开票 -- 编辑页面 opt 提交
	 * 发票申请
	 *
	 * @return
	 */
	@RequestMapping(value = "/invoiceApply", method = RequestMethod.POST)
	public R opInvoiceApply(@RequestBody InvoiceApplyCustomerFocusUnifiedOpApplyForm params) {

		// 算了 简单写吧
		if (null == params.getInvoiceApplyAmount() || null == params.getFreeAmount() || null == params.getRealAmount()) {
			return ResponseResultOuterUtils.createErrorResult("500", "参数缺失:金额错误,不能为空");
		}

		/****************************************** 添加 检验 mark by linjinyu at 20210105 start ******************************************/
		if (null == params.getDimCreateBy()) {
			return ResponseResultOuterUtils.createErrorResult("500", "参数缺失:对账单创建维度");
		}
		/****************************************** 添加 检验 mark by linjinyu at 20210105   end ******************************************/

		List<InvoiceApplyOpCreateSelectedGoodsParams> applyOrderGoodsParamsList = params.getOrderGoodsObj();

		if (AnCollectionUtils.isEmpty(applyOrderGoodsParamsList)) {
			return ResponseResultOuterUtils.createErrorResult("500", "开票申请项 为空");
		}

		return invoiceApplyCustomerDubboConsumerService.opInvoiceApplyCustomerFocusUnified(getToken(), params);
	}


	/**
	 * 客户结算-开票申请-opt row 审核 (申请开票)
	 *
	 * @return
	 */
	@RequestMapping(value = "/check", method = RequestMethod.POST)
	public R invoiceOptAudit() {

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

		params.put("id", getString("id"));
		params.put("auditStatus", getInteger("auditStatus"));

		invoiceApplyCustomerDubboConsumerService.opAudit(params, getToken());

		return new R();
	}


	/**
	 * 前端
	 * <p>
	 * 客户结算-开票申请-opt 查看详情
	 * 客户结算-发票管理-opt 查看详情
	 *
	 * @return
	 */
	@RequestMapping(value = "/getDetail", method = RequestMethod.POST)
	public R invoiceOptApplyDetail() {

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

		// 发票申请Id invoiceApplyId
		params.put("id", getLong("id"));

		return new R(invoiceApplyCustomerDubboConsumerService.getUnifiedCustomerInvoice2GoodsDetail(params));
	}


	/**
	 * 前端没用到 没用到
	 * 发票列表(分页)-新
	 *
	 * @return
	 */
	@RequestMapping(value = "/findInvoiceByPageNew", method = RequestMethod.POST)
	public R<List<InvoiceApply>> findInvoiceByPageNew() {

		R<List<InvoiceApply>> result = new R<>();

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

		result = invoiceApplyCustomerDubboConsumerService.findInvoiceByPageNew(params, getPageNum(), getPageSize(), getToken());

		return result;
	}


}
