package com.iformall.controller;


import com.github.pagehelper.PageInfo;
import com.iformall.common.ErrorCode;
import com.iformall.common.ResultData;
import com.iformall.domain.po.*;
import com.iformall.domain.vo.WxCardSpendVo;
import com.iformall.enums.EnumMerchantStatus;
import com.iformall.exception.MallinkException;
import com.iformall.service.*;
import com.iformall.utils.Constant;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import java.math.BigDecimal;
import java.util.List;
import java.util.Map;

/**
 * @author Stormeye Wu wuguoqiang@iformall.com
 */
@RestController
@Api(description = "C端扫B端商户码储值卡支付")
@RequestMapping("/api/cardPay")
public class WxCardPayController extends BaseController {
    private final Logger logger = LoggerFactory.getLogger(this.getClass());

    @Autowired
    WxMerchantService wxMerchantService;

    @Autowired
    WxOrderService wxOrderService;

    @Autowired
    WxCardInfoService wxCardInfoService;

    @Autowired
    WxCardSpendService wxCardSpendService;

    @Autowired
    WxCouponOrderService wxCouponOrderService;

    @ApiOperation(value = "C端扫B端储值卡支付订单", notes = "params:{\"cardId\":\"String\",\"merchantId\":\"String\",\"totalFee\":\"String(元)\"}")
    @PostMapping("order_create")
    public ResultData saveCardPayOrder(@RequestBody Map<String, String> paramMap, HttpServletRequest request) {
        String ipStr = getIpAddr();
        logger.info("saveCardPayOrder: " + ipStr + " ：" + paramMap.toString());
        String cardIdStr = paramMap.get("cardId");
        String merchantStr = paramMap.get("merchantId");
        String totalFeeStr = paramMap.get("totalFee");

        if (StringUtils.isBlank(cardIdStr) || cardIdStr.equalsIgnoreCase(Constant.UNDEFINED)) {
            logger.error("cardId不能为空");
            return new ResultData(ErrorCode.SYS_PARAMETER_NOT_NULL.getCode(), "cardId不能为空");
        }
        if (StringUtils.isBlank(merchantStr) || merchantStr.equalsIgnoreCase(Constant.UNDEFINED)) {
            logger.error("merchantId不能为空");
            return new ResultData(ErrorCode.SYS_PARAMETER_NOT_NULL.getCode(), "merchantId不能为空");
        }
        if (StringUtils.isBlank(totalFeeStr) || totalFeeStr.equalsIgnoreCase(Constant.UNDEFINED)) {
            logger.error("totalFee不能为空");
            return new ResultData(ErrorCode.SYS_PARAMETER_NOT_NULL.getCode(), "totalFee不能为空");
        }

        BigDecimal totalFee = new BigDecimal(totalFeeStr);
        totalFee.setScale(2, BigDecimal.ROUND_HALF_UP); // 第一个变量是小数位数，第二个变量是取舍方法(四舍五入)
        Integer payment = totalFee.multiply(new BigDecimal(100)).intValue();

        Long cardId = null;
        Long merchantId = null;
        try {
            cardId = Long.valueOf(cardIdStr);
        } catch (Exception e) {
            logger.error("cardId convert failed:" + cardIdStr);
            return new ResultData(ErrorCode.SYS_PARAMETER_NOT_NULL.getCode(), "cardIdStr转换失败");
        }
        try {
            merchantId = Long.valueOf(merchantStr);
        } catch (Exception e) {
            logger.error("merchantCode convert failed:" + merchantStr);
            return new ResultData(ErrorCode.SYS_PARAMETER_NOT_NULL.getCode(), "merchantId转换失败");
        }

        WxCardInfo cardInfo = wxCardInfoService.getById(cardId);
        if(cardInfo == null) {
            logger.error("卡不存在: " + cardIdStr);
            return new ResultData(ErrorCode.CARD_IS_NOT_FOUND);
        }

        if(payment > cardInfo.getRemainingAmount()) {
            logger.error("卡余额不足: " + cardIdStr);
            return new ResultData(ErrorCode.CARD_REMAIN_AMOUNT_IS_NOT_ENOUGH);
        }

        //查看所有者与扫码者是否为一致
        WxCouponOrder couponOrder = wxCouponOrderService.getById(cardId);
        if (!couponOrder.getOwnerId().equals(getUserId())) {
            logger.error("卡已被领取: " + cardIdStr);
            return new ResultData(ErrorCode.CARD_TRANSFERED);
        }

        WxCouponMerchant couponMerchant = wxCardSpendService.checkMerchantInCoupon(cardInfo, merchantId);
        if(couponMerchant == null) {
            logger.error("商户不支持此卡 " + cardIdStr);
            return new ResultData(ErrorCode.COUPON_ORDER_MERANT_IS_NULL.getCode(), "商户不支持此卡");
        }

        WxMerchant merchant = wxMerchantService.getById(merchantId);
        if (merchant.getStatus() == EnumMerchantStatus.NOT_VALID.getCode()) {
            logger.error("商户已禁用, merchantId: " + merchant.getId());
            return new ResultData(ErrorCode.MERCHANT_INFO_NOT_VALID);
        }

        WxOrder order = null;
        try {
            order = wxOrderService.saveCardPayOrder(merchant, getUserId(), totalFeeStr, payment);
        } catch (MallinkException e) {
            logger.error("saveCardPayOrder 1" + e.getMessage());
            return new ResultData(e.getErrorCode(), e.getMessage());
        } catch (Exception e) {
            logger.error("saveCardPayOrder 2" + e.getMessage());
            return new ResultData(ErrorCode.ORDER_IS_FAIL, e.getMessage());
        }

        WxCardSpend record = new WxCardSpend();
        record.setTenantId(merchant.getTenantId());
        record.setCardId(cardId);
        record.setOwnerId(getUserId());
        record.setMerchantId(merchantId);
        record.setOrderId(order.getId());
        record.setIp(ipStr);
        record.setDeductionAmount(payment);

        try {
            return wxCardSpendService.createCardSpend(record, order, couponMerchant);
        } catch (MallinkException e) {
            logger.error("card spend error, req 2: " + record.toString() + ", e:" + e.getMessage());
            return new ResultData(e.getErrorCode(), e.getMessage());
        } catch (Exception e) {
            logger.error("card spend error, req 3: " + record.toString() + ", e:" + e.getMessage());
            return new ResultData(ErrorCode.PAY_ORDER_ERROR, e.getMessage());
        }
    }

    @ApiOperation("C端扫B端储值卡交易流水列表接口")
    @GetMapping("list")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "pageNum", value = "页数", dataType = "int", paramType = "query", required = true),
            @ApiImplicitParam(name = "pageSize", value = "每页条数", dataType = "int", paramType = "query", required = true)})
    public ResultData cardSpendList(@ModelAttribute WxCardSpendVo wxCardSpend, Integer pageNum, Integer pageSize) {
        String ipStr = getIpAddr();
        logger.info("saveCardPayOrder: " + ipStr + " ：" + wxCardSpend.toString());
        if (wxCardSpend == null) wxCardSpend = new WxCardSpendVo();
        wxCardSpend.setTenantId(getTenantId());
        wxCardSpend.setOwnerId(getUserId());
        final PageInfo<WxCardSpendVo> page = wxCardSpendService.listAsPage(wxCardSpend, pageNum, pageSize);
        return new ResultData(page);
    }

    @ApiOperation("C端扫B端储值卡交易流水SUM接口")
    @GetMapping("sum")
    public ResultData sumCardSpendList(@ModelAttribute WxCardSpendVo wxCardSpend) {
        String ipStr = getIpAddr();
        logger.info("sumCardSpendList: " + ipStr + " ：" + wxCardSpend.toString());
        if (wxCardSpend == null) wxCardSpend = new WxCardSpendVo();
        wxCardSpend.setTenantId(getTenantId());
        wxCardSpend.setOwnerId(getUserId());
        final List<Map<String, Object>> mapList = wxCardSpendService.sumCardSpendForOwner(wxCardSpend);
        return new ResultData(mapList);
    }
}
