package com.jeequan.jeepay.mch.ctrl.account;

import com.alibaba.fastjson.JSONObject;
import com.jeequan.jeepay.ApiField;
import com.jeequan.jeepay.JeepayClient;
import com.jeequan.jeepay.components.mq.model.AccountBalanceMQ;
import com.jeequan.jeepay.components.mq.vender.IMQSender;
import com.jeequan.jeepay.core.cache.RedisUtil;
import com.jeequan.jeepay.core.constants.CS;
import com.jeequan.jeepay.core.entity.AccountOperate;
import com.jeequan.jeepay.core.entity.SysUser;
import com.jeequan.jeepay.core.exception.BizException;
import com.jeequan.jeepay.core.model.ApiRes;
import com.jeequan.jeepay.core.model.DBApplicationConfig;
import com.jeequan.jeepay.core.model.DBDefaultConfig;
import com.jeequan.jeepay.core.utils.SeqKit;
import com.jeequan.jeepay.db.entity.*;
import com.jeequan.jeepay.exception.JeepayException;
import com.jeequan.jeepay.mch.ctrl.CommonCtrl;
import com.jeequan.jeepay.mch.service.CommonApiService;
import com.jeequan.jeepay.model.DeviceInfo;
import com.jeequan.jeepay.model.JeepayObject;
import com.jeequan.jeepay.request.PayOrderCreateRequest;
import com.jeequan.jeepay.response.PayOrderCreateResponse;
import com.jeequan.jeepay.service.impl.*;
import lombok.Data;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.math.BigDecimal;
import java.util.List;

/**
 * TODO
 *
 * @author crystal
 * @date 2023/12/6 15:11
 */
@RestController
@RequestMapping("/api/account")
public class AccountInfoController extends CommonCtrl {

    @Autowired private AccountInfoService accountInfoService;
    @Autowired private MchAppService mchAppService;
    @Autowired private MchStoreService mchStoreService;
    @Autowired private MchApplymentService mchApplymentService;
    @Autowired private IMQSender mqSender;

    @PreAuthorize("hasAuthority('ENT_ACCOUNT_LIST')")
    @GetMapping
    public ApiRes getAccount() {
        AccountInfo info = getObject(AccountInfo.class);
        SysUser sysUser = getCurrentUser().getSysUser();
        List<AccountInfo> list = accountInfoService.getAccountInfo(info,getCurrentMchNo());
        for (AccountInfo item:list) {
            item.setRealName(sysUser.getRealname());
            item.setPhone(sysUser.getTelphone());
        }
        return ApiRes.ok(list);
    }

    /**
     * 充值
     * @return
     */
    @PreAuthorize("hasAuthority('ENT_ACCOUNT_RECHARGE')")
    @PostMapping(value = "/recharge")
    public ApiRes recharge() {
        JSONObject result = new JSONObject();
        AccountFundInfo.ChangeMethod val = AccountFundInfo.ChangeMethod.getVal(getValRequired("changeMethod",Byte.class));
        AccountOperate operate = new AccountOperate(getValStringRequired("accountNo"),getValLongRequired("rechargeAmt"),AccountFundInfo.ChangeType.RECHARGE.getValue(),val.getValue(),SeqKit.genFlowNo("H"),"账户充值");
        operate.preRechargeCheck();
        MchAppEntity defaultApp = mchAppService.getDefaultApp(getCurrentMchNo());
        switch (val){
            case SCAN:
                DBDefaultConfig dbDefaultConfig = sysConfigService.getDBDefaultConfig();
                if(StringUtils.isEmpty(dbDefaultConfig.getSysPaymentMchNo())){
                    throw new BizException("系统未配置收款商户号，暂时无法使用");
                }
                MchApplyment applyment = mchApplymentService.getById(dbDefaultConfig.getSysPaymentMchNo());
                if(applyment == null){
                    throw new BizException("系统配置的商户号数据异常");
                }
                MchStore mchStore = mchStoreService.getByMchApplyId(applyment.getApplyId());
                PayOrderCreateRequest request = new PayOrderCreateRequest();
                PayOrderCreateReqModelAddStoreId model = new PayOrderCreateReqModelAddStoreId();
                model.setPas(SysConfigService.PLATFORM_API_SECRET);
                model.setMchNo(getCurrentMchNo());
                model.setAppId(defaultApp.getAppId());
                model.setStoreId(mchStore.getStoreId());
                model.setMchOrderNo(SeqKit.genMhoOrderId());
                model.setWayCode(CS.PAY_WAY_CODE.QR_CASHIER);
                model.setAmount(operate.getAmount());
                model.setSubject(mchStore.getStoreName());
                model.setCurrency("CNY");
                model.setBody("退款账户充值");
                model.setMchExtNo(applyment.getApplyId());
                JSONObject extParams = new JSONObject();
                extParams.put("payDataType",CS.PAY_DATA_TYPE.CODE_IMG_URL);
                model.setClientIp(getClientIp());
                model.setChannelExtra(extParams.toString());
                DBApplicationConfig dbApplicationConfig = sysConfigService.getDBApplicationConfig();
                model.setNotifyUrl(dbApplicationConfig.getMchSiteUrl() + "/api/anon/paytestNotify/payOrder"); //回调地址
                String paySiteUrl = sysConfigService.getDBApplicationConfig().getPaySiteUrl();
                JeepayClient jeepayClient = new JeepayClient(paySiteUrl, defaultApp.getAppSecret());
                try {
                    request.setBizModel(model);
                    PayOrderCreateResponse response = jeepayClient.execute(request);
                    if(response.getCode() != 0){
                        throw new BizException(response.getMsg());
                    }
                    result.put("qrCodeUrl",response.get().getPayData());
                    operate.setOrderId(response.get().getPayOrderId());
                } catch (JeepayException e) {
                    throw new BizException(e.getMessage());
                }
                break;
            case PUBIC:
                operate.setFinalAmt(operate.getAmount());
                operate.setState(AccountFundInfo.AUDIT);
                break;
        }
        AccountFundInfo fundInfo = accountInfoService.upAccount(operate);
        result.put("flowNo",fundInfo.getOrderId());
        result.put("amount",operate.getAmount());
        result.put("finalAmt",fundInfo.getFinalAmount());
        String rechargeText = BigDecimal.valueOf(operate.getAmount()).divide(BigDecimal.valueOf(100)).toPlainString() +"(充值金额) * ";
        String rateText = "(1 - 0.6%(费率)) = " + BigDecimal.valueOf(operate.getAmount()).divide(BigDecimal.valueOf(100)).toPlainString() +"(实际到账)";
        result.put("text",rechargeText + rateText);
        return ApiRes.ok(result);
    }

    /**
     * 设置预警规则
     * @return
     */
    @PreAuthorize("hasAuthority('ENT_ACCOUNT_RULE')")
    @PostMapping(value = "/warnRule")
    public ApiRes warnRule() {
        AccountInfo info = getObject(AccountInfo.class);
        accountInfoService.setWarnRule(info);
        if(AccountInfo.REMIND_OPNE.equals(info.getRemindState())){
            Boolean val = RedisUtil.getObject(info.getAccountNo(),Boolean.class);
            if(val == null || !val){
                RedisUtil.set(info.getAccountNo(),true);
                mqSender.send(AccountBalanceMQ.build(info.getAccountNo()),info.getRuleExt().getInterval() * 60 * 60);
            }
        }else{
            RedisUtil.set(info.getAccountNo(),false);
        }
        return ApiRes.ok();
    }


    /**
     * 发起提现
     * @return
     */
    @PreAuthorize("hasAuthority('ENT_ACCOUNT_CASH')")
    @PostMapping(value = "/cash")
    public ApiRes cash() {
        AccountInfo info = getObject(AccountInfo.class);
        accountInfoService.cash(info);
        return ApiRes.ok("发起提现审核，等待后台审核");
    }


    /** 与阿里云sdk一样，  直接extends PayOrderCreateReqModel无法传入到接口中对应的参数。 需要把所有的参数放进来。。。   = = 。   **/
    @Data
    public static class PayOrderCreateReqModelAddStoreId extends JeepayObject {
        private static final long serialVersionUID = -3998573128290306948L;
        @ApiField("pas")
        private String pas;
        @ApiField("storeId")
        private String storeId;
        @ApiField("qrcId")
        private String qrcId;

        @ApiField("mchNo")
        private String mchNo;      // 商户号
        @ApiField("appId")
        private String appId;      // 应用ID
        @ApiField("mchOrderNo")
        String mchOrderNo;          // 商户订单号
        @ApiField("wayCode")
        String wayCode;             // 支付方式
        @ApiField("amount")
        Long amount;                // 支付金额
        @ApiField("currency")
        String currency;            // 货币代码，当前只支持cny
        @ApiField("clientIp")
        String clientIp;            // 客户端IP
        @ApiField("subject")
        String subject;             // 商品标题
        @ApiField("body")
        String body;                // 商品描述
        @ApiField("channelBizData")
        String channelBizData;  // 渠道业务参数
        @ApiField("notifyUrl")
        String notifyUrl;           // 异步通知地址
        @ApiField("returnUrl")
        String returnUrl;           // 跳转通知地址
        @ApiField("expiredTime")
        String expiredTime;         // 订单失效时间
        @ApiField("channelExtra")
        String channelExtra;        // 特定渠道额外支付参数
        @ApiField("extParam")
        String extParam;            // 商户扩展参数
        @ApiField("divisionMode")
        private Byte divisionMode;   // 分账模式： 0-该笔订单不允许分账[默认], 1-支付成功按配置自动完成分账, 2-商户手动分账(解冻商户金额)
        @ApiField("sellerRemark")
        String sellerRemark;            // 卖家备注
        @ApiField("buyerRemark")
        String buyerRemark;            // 买家备注
        @ApiField("deviceInfo")
        private DeviceInfo deviceInfo;   // 设备信息
        @ApiField("mchExtNo")
        private String mchExtNo;   // 新版商户号
    }
}
