/*
 *      Copyright (c) 2018-2028, Chill Zhuang All rights reserved.
 *
 *  Redistribution and use in source and binary forms, with or without
 *  modification, are permitted provided that the following conditions are met:
 *
 *  Redistributions of source code must retain the above copyright notice,
 *  this list of conditions and the following disclaimer.
 *  Redistributions in binary form must reproduce the above copyright
 *  notice, this list of conditions and the following disclaimer in the
 *  documentation and/or other materials provided with the distribution.
 *  Neither the name of the dreamlu.net developer nor the names of its
 *  contributors may be used to endorse or promote products derived from
 *  this software without specific prior written permission.
 *  Author: Chill 庄骞 (smallchill@163.com)
 */
package org.springblade.modules.guosen.bussiness.controller;

import cn.hutool.core.lang.Assert;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import com.github.xiaoymin.knife4j.annotations.ApiOperationSupport;
import javax.validation.Valid;

import lombok.extern.slf4j.Slf4j;
import org.springblade.common.constant.SystemConstant;
import org.springblade.core.mp.support.Condition;
import org.springblade.core.mp.support.Query;
import org.springblade.core.tool.api.R;
import org.springblade.core.tool.utils.DateUtil;
import org.springblade.core.tool.utils.Func;
import org.springblade.core.tool.utils.StringUtil;
import org.springblade.modules.guosen.billRecord.service.IBillRecordService;
import org.springblade.modules.guosen.bussiness.dto.BussinessBonusRecordsDTO;
import org.springblade.modules.guosen.bussiness.entity.BussinessBonusAccount;
import org.springblade.modules.guosen.bussiness.entity.BussinessBonusStatic;
import org.springblade.modules.guosen.bussiness.service.IBussinessBonusAccountService;
import org.springblade.modules.guosen.bussiness.service.IBussinessBonusStaticService;
import org.springblade.modules.guosen.bussinessTransferOrder.entity.BussinessTransferOrder;
import org.springblade.modules.guosen.bussinessTransferOrder.service.IBussinessTransferOrderService;
import org.springblade.modules.guosen.bussinessuserinfo.entity.BussinessUserInfo;
import org.springblade.modules.guosen.bussinessuserinfo.service.IBussinessUserInfoService;
import org.springblade.modules.guosen.withdrawRecords.entity.WithdrawRecords;
import org.springblade.modules.guosen.withdrawRecords.service.IWithdrawRecordsService;
import org.springblade.modules.system.service.IParamService;
import org.springblade.yeePay.common.YeePayConst;
import org.springblade.yeePay.entity.PayOrderDto;
import org.springblade.yeePay.service.BussinessPayService;
import org.springblade.yeePay.service.YeePayService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.bind.annotation.RequestParam;
import com.baomidou.mybatisplus.core.metadata.IPage;
import org.springblade.modules.guosen.bussiness.entity.BussinessBonusRecords;
import org.springblade.modules.guosen.bussiness.vo.BussinessBonusRecordsVO;
import org.springblade.modules.guosen.bussiness.service.IBussinessBonusRecordsService;
import org.springblade.core.boot.ctrl.BladeController;

import java.math.BigDecimal;
import java.text.DecimalFormat;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.UUID;

/**
 *  控制器
 *
 * @author BladeX
 * @since 2021-07-22
 */
@RestController
@RequestMapping("cyzh-guosen/bussinessbonusrecords")
@Api(value = "", tags = "接口")
@Slf4j
public class BussinessBonusRecordsController extends BladeController {

	@Autowired
	private IBussinessBonusRecordsService bussinessBonusRecordsService;
	@Autowired
	private YeePayService yeePayService;
	@Autowired
	private IWithdrawRecordsService withdrawRecordsService;
	@Autowired
	private IBussinessBonusAccountService bussinessBonusAccountService;
	@Autowired
	private IBussinessBonusStaticService bussinessBonusStaticService;
	@Autowired
	private IParamService paramService;
	@Autowired
	private IBussinessTransferOrderService transferOrderService;
	@Autowired
	private IBussinessUserInfoService userInfoService;
	@Autowired
	private BussinessPayService bussinessPayService;

	/**
	 * 详情
	 */
	@GetMapping("/detail")
	@ApiOperationSupport(order = 1)
	@ApiOperation(value = "详情", notes = "传入bussinessBonusRecords")
	public R<BussinessBonusRecords> detail(BussinessBonusRecords bussinessBonusRecords) {
		BussinessBonusRecords detail = bussinessBonusRecordsService.getOne(Condition.getQueryWrapper(bussinessBonusRecords));
		return R.data(detail);
	}

	/**
	 * 分页
	 */
	@GetMapping("/list")
	@ApiOperationSupport(order = 2)
	@ApiOperation(value = "分页", notes = "传入bussinessBonusRecords")
	public R<IPage<BussinessBonusRecords>> list(@RequestParam Map<String, Object> bussinessBonusRecordsDTO, Query query) {
		String beginDate = null;
		String endDate = null;
		Long bonusAccountId = null;
		Integer bonusStatus = null;
		if(bussinessBonusRecordsDTO.get("beginDate") != null && bussinessBonusRecordsDTO.get("endDate") != null){
			beginDate =  (String) bussinessBonusRecordsDTO.get("beginDate");
			endDate = (String)bussinessBonusRecordsDTO.get("endDate");
			bussinessBonusRecordsDTO.remove("beginDate");
			bussinessBonusRecordsDTO.remove("endDate");
		}
		if(bussinessBonusRecordsDTO.get("bonusAccountId") != null){
			bonusAccountId = Long.valueOf((String) bussinessBonusRecordsDTO.get("bonusAccountId"));
			bussinessBonusRecordsDTO.remove("bonusAccountId");
		}
		if(bussinessBonusRecordsDTO.get("bonusStatus") != null){
			bonusStatus = Integer.valueOf((String) bussinessBonusRecordsDTO.get("bonusStatus"));
			bussinessBonusRecordsDTO.remove("bonusStatus");
		}
		LambdaQueryWrapper<BussinessBonusRecords> lambda = Condition.getQueryWrapper(bussinessBonusRecordsDTO, BussinessBonusRecords.class).lambda();
		lambda.ge(beginDate != null, BussinessBonusRecords::getBonusDate, beginDate);
		lambda.le(endDate != null, BussinessBonusRecords::getBonusDate, endDate);
		lambda.eq(bonusAccountId != null, BussinessBonusRecords::getBonusAccountId, bonusAccountId);
		lambda.eq(bonusStatus != null, BussinessBonusRecords::getBonusStatus, bonusStatus);
		IPage<BussinessBonusRecords> pages = bussinessBonusRecordsService.page(Condition.getPage(query), lambda);
		return R.data(pages);
	}

	/**
	 * 自定义分页
	 */
	@GetMapping("/page")
	@ApiOperationSupport(order = 3)
	@ApiOperation(value = "分页", notes = "传入bussinessBonusRecords")
	public R<IPage<BussinessBonusRecordsVO>> page(BussinessBonusRecordsVO bussinessBonusRecords, Query query) {
		IPage<BussinessBonusRecordsVO> pages = bussinessBonusRecordsService.selectBussinessBonusRecordsPage(Condition.getPage(query), bussinessBonusRecords);
		return R.data(pages);
	}

	/**
	 * 新增
	 */
	@PostMapping("/save")
	@ApiOperationSupport(order = 4)
	@ApiOperation(value = "新增", notes = "传入bussinessBonusRecords")
	public R save(@Valid @RequestBody BussinessBonusRecords bussinessBonusRecords) {
		return R.status(bussinessBonusRecordsService.save(bussinessBonusRecords));
	}

	/**
	 * 修改
	 */
	@PostMapping("/update")
	@ApiOperationSupport(order = 5)
	@ApiOperation(value = "修改", notes = "传入bussinessBonusRecords")
	public R update(@Valid @RequestBody BussinessBonusRecords bussinessBonusRecords) {
		return R.status(bussinessBonusRecordsService.updateById(bussinessBonusRecords));
	}

	/**
	 * 新增或修改
	 */
	@PostMapping("/submit")
	@ApiOperationSupport(order = 6)
	@ApiOperation(value = "新增或修改", notes = "传入bussinessBonusRecords")
	public R submit(@Valid @RequestBody BussinessBonusRecords bussinessBonusRecords) {
		return R.status(bussinessBonusRecordsService.saveOrUpdate(bussinessBonusRecords));
	}


	/**
	 * 删除
	 */
	@PostMapping("/remove")
	@ApiOperationSupport(order = 7)
	@ApiOperation(value = "逻辑删除", notes = "传入ids")
	public R remove(@ApiParam(value = "主键集合", required = true) @RequestParam String ids) {
		return R.status(bussinessBonusRecordsService.deleteLogic(Func.toLongList(ids)));
	}

	/**
	 * 分润（代付版本）
	 */
	@PostMapping("/payForBonus")
	@ApiOperationSupport(order = 8)
	@ApiOperation(value = "分润", notes = "传入bussinessBonusRecords")
	public R payForBonus(@Valid @RequestBody BussinessBonusRecords bussinessBonusRecords) {
		BussinessBonusRecords record = bussinessBonusRecordsService.getById(bussinessBonusRecords.getId());
		//分佣
		Assert.isFalse(record.getBonusStatus() == SystemConstant.BussinessBonusStatus.SUCCESS.getValue()
			|| record.getBonusStatus() == SystemConstant.BussinessBonusStatus.BONUSING.getValue(),
			"不能重复分配");
		BigDecimal price = bussinessBonusRecords.getPrice();
		if(record.getPrice().compareTo(price) == -1){
			R.fail("分润金额不能高于可分润金额");
		}
		if(record.getPrice().compareTo(new BigDecimal(1)) == -1){
			return R.fail("可分润金额不足以抵扣手续费");
		}
		PayOrderDto payOrderDto = this.recordToPayOrder(record);
		Long userInfoId = record.getUserInfoId();
		BussinessUserInfo userInfo = this.userInfoService.getById(userInfoId);
		R result = yeePayService.bonusOrder(payOrderDto, userInfo.getParentMerchantNo());
		JSONObject data = JSONUtil.parseObj(result.getData());
		String returnCode = data.getStr("returnCode");
		String returnMsg = data.getStr("returnMsg");
		String orderNo = data.getStr("orderNo");
		String msg = returnMsg;
		if(StringUtil.isNotBlank(returnCode) && returnCode.equals("UA00000")) { //代付发起成功
			log.info("========================单笔分润发起成功====================");
			record.setFailReason(returnMsg);
			record.setThirdPayLog(JSONUtil.toJsonStr(data));
			record.setBonusStatus(SystemConstant.BussinessBonusStatus.BONUSING.getValue());
			record.setThirdOrderNo(orderNo);
			bussinessBonusRecordsService.saveOrUpdate(record);
			return R.data(data, msg);
		}else{
			log.info("========================单笔分润发起失败====================");
			record.setBonusStatus(SystemConstant.BussinessDebitStatus.FAIL.getValue());
			record.setFailReason(returnMsg);
			record.setThirdPayLog(JSONUtil.toJsonStr(data));
			bussinessBonusRecordsService.saveOrUpdate(record);
			return R.data(400, data, msg);
		}
	}

	private Long saveWithdraw(BussinessBonusRecords bussinessBonusRecords, PayOrderDto transferDto) {
		WithdrawRecords withdrawRecords = new WithdrawRecords();
		BussinessBonusAccount bussinessBonusAccout = bussinessBonusAccountService.getById(bussinessBonusRecords.getBonusAccountId());
		Assert.notNull(bussinessBonusAccout,"账号找不到");
		if(bussinessBonusAccout.getReceiverAccountNo() == null || bussinessBonusAccout.getReceiverAccountName() == null
		   || bussinessBonusAccout.getReceiverBankCode() == null || bussinessBonusAccout.getBankAccountType() == null){
			Assert.isFalse(true,"分佣账号的账号转账信息不全，请保证账号的分佣银行卡的开户行编码、" +
				"账号类型、姓名和银行卡信息全部已经填写");
		}
		withdrawRecords.setReceiverAccountNo(bussinessBonusAccout.getReceiverAccountNo());
		withdrawRecords.setReceiverAccountName(bussinessBonusAccout.getReceiverAccountName());
		withdrawRecords.setOrderNo(transferDto.getRequestNo());
		withdrawRecords.setType(SystemConstant.WithdrawRecordType.ADS_BONUS.getValue());
		withdrawRecords.setWithdrawStatus(SystemConstant.WithdrawRecordStatus.WATTING.getValue());
		withdrawRecords.setUserId(bussinessBonusAccout.getId());
		withdrawRecords.setBankCode(bussinessBonusAccout.getReceiverBankCode());
		withdrawRecords.setCashValue(bussinessBonusRecords.getPrice());
		withdrawRecords.setRequestNo(transferDto.getRequestNo());
		if(withdrawRecordsService.save(withdrawRecords)){
			return withdrawRecords.getId();
		}
		return null;
	}

	private PayOrderDto recordToPayOrder(BussinessBonusRecords bussinessBonusRecords) {
		PayOrderDto payOrderDto = new PayOrderDto();
		payOrderDto.setRequestNo(UUID.randomUUID().toString().replaceAll("-", "").toUpperCase());
		payOrderDto.setOrderAmount(Double.parseDouble(bussinessBonusRecords.getPrice().toString()));
		payOrderDto.setFeeChargeSide("PAYER");
		payOrderDto.setReceiveType("REAL_TIME");
		BussinessBonusAccount bussinessBonusAccount = bussinessBonusAccountService.getById(bussinessBonusRecords.getBonusAccountId());
		Assert.notNull(bussinessBonusAccount,"账号找不到");
		if(bussinessBonusAccount.getReceiverAccountNo() == null || bussinessBonusAccount.getReceiverAccountName() == null
			|| bussinessBonusAccount.getReceiverBankCode() == null || bussinessBonusAccount.getBankAccountType() == null){
			Assert.isFalse(true,"分佣账号的账号转账信息不全，请保证账号的分佣银行卡的开户行编码、" +
				"账号类型、姓名和银行卡信息全部已经填写");
		}
		payOrderDto.setReceiverAccountNo(bussinessBonusAccount.getReceiverAccountNo());
		payOrderDto.setReceiverAccountName(bussinessBonusAccount.getReceiverAccountName());
		payOrderDto.setReceiverBankCode(bussinessBonusAccount.getReceiverBankCode());
		payOrderDto.setBankAccountType(bussinessBonusAccount.getBankAccountType());
		return payOrderDto;
	}

	/**
	 * 手动生成历史分润记录
	 */
	@PostMapping("/generateHistoryRecords")
	@ApiOperationSupport(order = 9)
	public R generateHistoryRecords(@RequestParam(value = "beginDateStr") String beginDateStr, @RequestParam(value = "endDateStr") String endDateStr){
		Date beginDate = DateUtil.parse(beginDateStr, "yyyy-MM-dd");
		Date endDate = DateUtil.parse(endDateStr, "yyyy-MM-dd");
		String fromDateStr = beginDateStr;
		List<BussinessBonusAccount> accountList = bussinessBonusAccountService.list();
		if(accountList == null || accountList.size() == 0){
			R.fail("无账号需要分润");
		}
		while(beginDate.before(DateUtil.plusDays(endDate, 1))){
//			//查询采购商充值记录
//			List<BillRecord> billRecords = billRecordService.getBaseMapper().selectList(new QueryWrapper<>(new BillRecord()).lambda()
//					.eq(BillRecord::getType, SystemConstant.BillRecordType.ADS.getValue()).like(BillRecord::getCreateTime, fromDateStr)
//					.eq(BillRecord::getPayStatus, SystemConstant.BillRecordPayStatus.PAYED.getValue()));
//			//采购商充值技术服务总费用-即可分配利润
//			BigDecimal bonusAmt = billRecords.stream().map(BillRecord::getBussinessFee).reduce(BigDecimal.ZERO, BigDecimal::add);
//			if(bonusAmt == null){
//				bonusAmt = new BigDecimal(0.00);
//			}
			BussinessBonusStatic bonusStatic = bussinessBonusStaticService.getBaseMapper().selectOne(new QueryWrapper<>(new BussinessBonusStatic()).lambda()
					.like(BussinessBonusStatic::getDate, fromDateStr));
			for(BussinessBonusAccount account : accountList){
				LambdaQueryWrapper<BussinessBonusRecords> recordWrapper = new LambdaQueryWrapper<>();
				recordWrapper.like(BussinessBonusRecords::getBonusDate, fromDateStr);
				recordWrapper.eq(BussinessBonusRecords::getBonusAccountId, account.getId());
				BussinessBonusRecords record = bussinessBonusRecordsService.getOne(recordWrapper);
				if(record == null){ //指定日期下无分润记录存在，则可以生成一个新的分润记录
					BussinessBonusRecords newRecord = new BussinessBonusRecords();
					newRecord.setBonusAccountId(account.getId());
					newRecord.setBonusAccountName(account.getAccount());
					newRecord.setBonusDate(beginDate);
					BigDecimal bonusAmt = bonusStatic.getBonusAmt();
					newRecord.setPrice((bonusAmt.multiply(account.getRate())).setScale(2, BigDecimal.ROUND_HALF_UP));
					newRecord.setRate(account.getRate());
					newRecord.setBonusStatus(SystemConstant.BussinessBonusStatus.WATING.getValue());
					bussinessBonusRecordsService.save(newRecord);
				}
			}
			beginDate = DateUtil.plusDays(beginDate, 1);
			fromDateStr = DateUtil.format(beginDate, "yyyy-MM-dd");
		}
		return R.status(true);
	}

	/**
	 * 分润（提现版本）
	 */
	@PostMapping("/withdrawForBonus")
	@ApiOperationSupport(order = 10)
	@ApiOperation(value = "分润", notes = "传入bussinessBonusRecords")
	public R withdrawForBonus(@Valid @RequestBody BussinessBonusRecordsDTO bussinessBonusRecordsDTO){
		R result = this.bussinessBonusRecordsService.withdrawForBonus(bussinessBonusRecordsDTO);
		return  result;
	}
}
