package com.gxwebsoft.shop.controller;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.RandomUtil;
import com.alibaba.fastjson.JSONObject;
import com.gxwebsoft.common.core.config.ConfigProperties;
import com.gxwebsoft.common.core.security.JwtUtil;
import com.gxwebsoft.common.core.utils.JSONUtil;
import com.gxwebsoft.common.core.utils.RedisUtil;
import com.gxwebsoft.common.core.utils.RequestUtil;
import com.gxwebsoft.common.core.web.BaseController;
import com.gxwebsoft.common.system.entity.Payment;
import com.gxwebsoft.shop.consts.BalanceScene;
import com.gxwebsoft.shop.entity.DealerCapital;
import com.gxwebsoft.shop.entity.UserBalanceLog;
import com.gxwebsoft.shop.service.DealerCapitalService;
import com.gxwebsoft.shop.service.DealerWithdrawService;
import com.gxwebsoft.shop.entity.DealerWithdraw;
import com.gxwebsoft.shop.param.DealerWithdrawParam;
import com.gxwebsoft.common.core.web.ApiResult;
import com.gxwebsoft.common.core.web.PageResult;
import com.gxwebsoft.common.core.web.BatchParam;
import com.gxwebsoft.common.system.entity.User;
import com.gxwebsoft.shop.service.OrderService;
import com.gxwebsoft.shop.service.UserBalanceLogService;
import com.wechat.pay.java.core.RSAAutoCertificateConfig;
import com.wechat.pay.java.core.exception.ValidationException;
import com.wechat.pay.java.core.notification.NotificationConfig;
import com.wechat.pay.java.core.notification.NotificationParser;
import com.wechat.pay.java.core.notification.RequestParam;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.http.HttpStatus;
import org.springframework.http.RequestEntity;
import org.springframework.http.ResponseEntity;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.math.BigDecimal;
import java.util.List;
import java.util.Map;

import static com.gxwebsoft.shop.consts.OrderPayType.PAY_TYPE_WECHAT;

/**
 * 分销商提现明细表控制器
 *
 * @author 科技小王子
 * @since 2024-07-28 11:57:41
 */
@Api(tags = "分销商提现明细表管理")
@RestController
@RequestMapping("/api/shop/dealer-withdraw")
public class DealerWithdrawController extends BaseController {
    @Resource
    private DealerWithdrawService dealerWithdrawService;
    @Resource
    private UserBalanceLogService userBalanceLogService;
    @Resource
    private DealerCapitalService dealerCapitalService;
    @Resource
    private OrderService orderService;
    @Resource
    private RedisUtil redisUtil;
    @Resource
    private ConfigProperties configProperties;

    @ApiOperation("分页查询分销商提现明细表")
    @GetMapping("/page")
    public ApiResult<PageResult<DealerWithdraw>> page(DealerWithdrawParam param) {
        // 使用关联查询
        return success(dealerWithdrawService.pageRel(param));
    }

    @PostMapping("/notify")
    public void transferNotify(@RequestBody String data, HttpServletRequest request, HttpServletResponse response) throws IOException {
        String key2 = "Payment:".concat(PAY_TYPE_WECHAT.toString()).concat(":").concat("10559");
        final Payment payment = redisUtil.get(key2, Payment.class);
        final String uploadPath = configProperties.getUploadPath();
        String wechatPaySerial = request.getHeader("Wechatpay-Serial");
        String wechatpayNonce = request.getHeader("Wechatpay-Nonce");
        String wechatSignature = request.getHeader("Wechatpay-Signature");
        String wechatTimestamp = request.getHeader("Wechatpay-Timestamp");
        RequestParam requestParam = new RequestParam.Builder()
                .serialNumber(wechatPaySerial)
                .nonce(wechatpayNonce)
                .signature(wechatSignature)
                .timestamp(wechatTimestamp)
                .body(data)
                .build();

        String privateKey = uploadPath.concat("/file").concat(payment.getApiclientKey());    // 秘钥证书
        NotificationConfig config = new RSAAutoCertificateConfig.Builder()
                .merchantId(payment.getMchId())
                .privateKeyFromPath(privateKey)
                .merchantSerialNumber(payment.getMerchantSerialNumber())
                .apiV3Key(payment.getApiKey())
                .build();
        NotificationParser parser = new NotificationParser(config);
        try {
            Map transaction = parser.parse(requestParam, Map.class);
            if (transaction.get("state").equals("SUCCESS") || transaction.get("state").equals("FAIL")) {
                String orderNo = (String) transaction.get("out_bill_no");
                DealerWithdraw dealerWithdraw = dealerWithdrawService.getByOrderNo(orderNo);
                if (dealerWithdraw != null && (dealerWithdraw.getApplyStatus().equals(10) || dealerWithdraw.getApplyStatus().equals(20))) {
                    final RequestUtil requestUtil = new RequestUtil();
                    requestUtil.setTenantId("10559");
                    User user = requestUtil.getByUserId(dealerWithdraw.getUserId());
                    if (transaction.get("state").equals("SUCCESS")) {
                        dealerWithdraw.setApplyStatus(40);
                        dealerWithdrawService.updateById(dealerWithdraw);
                        user.setCashedMoney(user.getCashedMoney().add(dealerWithdraw.getMoney()));
                        requestUtil.updateUserBalanceWithoutLogin(user);
                    }else if (transaction.get("state").equals("FAIL")) {
                        dealerWithdraw.setApplyStatus(30);
                        dealerWithdraw.setRejectReason("提现失败,请联系客服");
                        dealerWithdrawService.updateById(dealerWithdraw);
                        user.setBalance(user.getBalance().add(dealerWithdraw.getMoney()));
                        requestUtil.updateUserBalanceWithoutLogin(user);
                    }
                }
            }
        } catch (ValidationException e) {
            response.setStatus(HttpStatus.BAD_REQUEST.value());
            JSONObject json = new JSONObject();
            json.put("code", "ERROR");
            json.put("message", "验签失败");
            response.getWriter().append(JSONUtil.toJSONString(json));
        }

        response.setStatus(HttpStatus.OK.value());
        response.getWriter().append("SUCCESS");
    }

    @GetMapping("/uncheck-num")
    public ApiResult<Integer> page() {
        // 使用关联查询
        List<DealerWithdraw> list = dealerWithdrawService.listRel(new DealerWithdrawParam() {{
            setApplyStatus(10);
        }});
        return success(list.size());
    }

    @ApiOperation("查询全部分销商提现明细表")
    @GetMapping()
    public ApiResult<List<DealerWithdraw>> list(DealerWithdrawParam param) {
        // 使用关联查询
        param.setUserId(getLoginUserId());
        return success(dealerWithdrawService.listRel(param));
    }

    @PreAuthorize("hasAuthority('shop:dealerWithdraw:list')")
    @ApiOperation("根据id查询分销商提现明细表")
    @GetMapping("/{id}")
    public ApiResult<DealerWithdraw> get(@PathVariable("id") Integer id) {
        // 使用关联查询
        return success(dealerWithdrawService.getByIdRel(id));
    }

    @ApiOperation("添加分销商提现明细表")
    @PostMapping()
    public ApiResult<?> save(@RequestBody DealerWithdraw dealerWithdraw, HttpServletRequest request) {
        // 记录当前登录用户id
        User loginUser = getLoginUser();
        if (loginUser != null) {
            dealerWithdraw.setUserId(loginUser.getUserId());
            if (loginUser.getBalance().compareTo(dealerWithdraw.getMoney()) < 0) return fail("余额不足");
        } else {
            return fail("请先登录");
        }
        dealerWithdraw.setOrderNo(RandomUtil.randomString(32));
        if (dealerWithdrawService.save(dealerWithdraw)) {
            BigDecimal newBalance = loginUser.getBalance().subtract(dealerWithdraw.getMoney());

            final RequestUtil requestUtil = new RequestUtil();
            String access_token = JwtUtil.getAccessToken(request);
            requestUtil.setAccessToken(access_token);
            requestUtil.setTenantId(getTenantId().toString());
            loginUser.setBalance(loginUser.getBalance().subtract(dealerWithdraw.getMoney()));
            requestUtil.updateUserBalance("/system/user/updateUserBalance", loginUser);

            userBalanceLogService.save(new UserBalanceLog() {{
                setUserId(loginUser.getUserId());
                setScene(BalanceScene.BALANCE_SCENE_DIFF);
                setMoney(dealerWithdraw.getMoney());
                setBalance(newBalance);
                setMerchantId(loginUser.getMerchantId());
                setTenantId(getTenantId());
            }});
            dealerCapitalService.save(new DealerCapital() {{
                setUserId(loginUser.getUserId());
                setFlowType(20);
                setMoney(dealerWithdraw.getMoney());
                setDescribe("提现");
                setTenantId(getTenantId());
            }});

            // 微信提现
            if (dealerWithdraw.getPayType().equals(10)) {
                dealerWithdraw.setOpenId(loginUser.getOpenid());
                JSONObject res = orderService.transferBill(dealerWithdraw);
                if (res == null) {
                    loginUser.setBalance(loginUser.getBalance().add(dealerWithdraw.getMoney()));
                    requestUtil.updateUserBalance("/system/user/updateUserBalance", loginUser);
                    userBalanceLogService.save(new UserBalanceLog() {{
                        setUserId(loginUser.getUserId());
                        setScene(BalanceScene.BALANCE_SCENE_DIFF);
                        setMoney(dealerWithdraw.getMoney());
                        setBalance(loginUser.getBalance().add(dealerWithdraw.getMoney()));
                        setMerchantId(loginUser.getMerchantId());
                        setTenantId(getTenantId());
                    }});
                    dealerCapitalService.save(new DealerCapital() {{
                        setUserId(loginUser.getUserId());
                        setFlowType(10);
                        setMoney(dealerWithdraw.getMoney());
                        setDescribe("提现失败退回");
                        setTenantId(getTenantId());
                    }});
                    dealerWithdraw.setApplyStatus(30);
                    dealerWithdraw.setAuditTime((int) DateUtil.currentSeconds());
                    dealerWithdraw.setRejectReason("提现失败,请联系客服");
                    dealerWithdrawService.updateById(dealerWithdraw);
                    return fail("提现失败,请联系客服");
                }
                res.put("id", dealerWithdraw.getId());
                return success(res);
            }
            return success("添加成功");
        }
        return fail("添加失败");
    }

    @ApiOperation("修改分销商提现明细表")
    @PutMapping()
    public ApiResult<?> update(@RequestBody DealerWithdraw dealerWithdraw, HttpServletRequest request) {
        if (dealerWithdrawService.updateById(dealerWithdraw)) {
            if (dealerWithdraw.getApplyStatus().equals(30)) {
                DealerWithdraw dealerWithdraw1 = dealerWithdrawService.getByIdRel(dealerWithdraw.getId());
                final RequestUtil requestUtil = new RequestUtil();
                String access_token = JwtUtil.getAccessToken(request);
                requestUtil.setAccessToken(access_token);
                requestUtil.setTenantId(getTenantId().toString());
                User user = requestUtil.getByUserId(dealerWithdraw1.getUserId());
                user.setBalance(user.getBalance().add(dealerWithdraw1.getMoney()));
                user.setCashedMoney(user.getCashedMoney().subtract(dealerWithdraw1.getMoney()));
                requestUtil.updateUserBalance("/system/user/updateUserBalance", user);
            }
            return success("修改成功");
        }
        return fail("修改失败");
    }

    @ApiOperation("删除分销商提现明细表")
    @DeleteMapping("/{id}")
    public ApiResult<?> remove(@PathVariable("id") Integer id) {
        if (dealerWithdrawService.removeById(id)) {
            return success("删除成功");
        }
        return fail("删除失败");
    }

    @ApiOperation("批量添加分销商提现明细表")
    @PostMapping("/batch")
    public ApiResult<?> saveBatch(@RequestBody List<DealerWithdraw> list) {
        if (dealerWithdrawService.saveBatch(list)) {
            return success("添加成功");
        }
        return fail("添加失败");
    }

    @ApiOperation("批量修改分销商提现明细表")
    @PutMapping("/batch")
    public ApiResult<?> removeBatch(@RequestBody BatchParam<DealerWithdraw> batchParam) {
        if (batchParam.update(dealerWithdrawService, "id")) {
            return success("修改成功");
        }
        return fail("修改失败");
    }

    @ApiOperation("批量删除分销商提现明细表")
    @DeleteMapping("/batch")
    public ApiResult<?> removeBatch(@RequestBody List<Integer> ids) {
        if (dealerWithdrawService.removeByIds(ids)) {
            return success("删除成功");
        }
        return fail("删除失败");
    }

}
