package com.sqx.modules.pay.controller.app;

import cn.hutool.core.date.DateUtil;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.sqx.common.utils.DateUtils;
import com.sqx.common.utils.Result;
import com.sqx.modules.app.entity.UserEntity;
import com.sqx.modules.app.entity.UserMoneyDetails;
import com.sqx.modules.app.service.UserMoneyDetailsService;
import com.sqx.modules.app.service.UserMoneyService;
import com.sqx.modules.app.service.UserService;
import com.sqx.modules.common.service.CommonInfoService;
import com.sqx.modules.invite.service.InviteService;
import com.sqx.modules.orders.entity.Orders;
import com.sqx.modules.orders.service.OrdersService;
import com.sqx.modules.pay.dao.CashOutDao;
import com.sqx.modules.pay.dao.PayDetailsDao;
import com.sqx.modules.pay.entity.CashOut;
import com.sqx.modules.pay.entity.PayDetails;
import com.sqx.modules.pay.wuyou.BaseResp;
import com.sqx.modules.pay.wuyou.Encrypt;
import com.sqx.modules.pay.wuyou.NotifyDto;
import com.sqx.modules.pay.wuyou.WuyouPay;
import com.sqx.modules.utils.AliPayOrderUtil;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.CompletableFuture;

/**
 * @author GYJ
 */
@Slf4j
@RestController
@Api(value = "无忧支付", tags = {"无忧支付"})
@RequestMapping("/app/wuyou")
public class WuyouController {

    private final OrdersService ordersService;
    private final PayDetailsDao payDetailsDao;
    private final UserService userService;
    private final InviteService inviteService;
    private final UserMoneyService userMoneyService;
    private final UserMoneyDetailsService userMoneyDetailsService;
    private final CommonInfoService commonRepository;
    private final CashOutDao cashOutDao;

    private final SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

    WuyouController(OrdersService ordersService, PayDetailsDao payDetailsDao, UserService userService, InviteService inviteService, CashOutDao cashOutDao,
                    UserMoneyService userMoneyService, UserMoneyDetailsService userMoneyDetailsService, CommonInfoService commonRepository) {
        this.ordersService = ordersService;
        this.payDetailsDao = payDetailsDao;
        this.userService = userService;
        this.inviteService = inviteService;
        this.cashOutDao = cashOutDao;
        this.userMoneyService = userMoneyService;
        this.userMoneyDetailsService = userMoneyDetailsService;
        this.commonRepository = commonRepository;
    }

    @ApiOperation("支付订单")
    @GetMapping("/payOrder/{orderId}")
    public Result payOrder(HttpServletRequest request, @PathVariable("orderId") Long orderId) {
        Orders order = ordersService.getById(orderId);
        if (order == null) {
            return Result.error("订单不存在");
        }

        if (order.getStatus() != 0) {
            return Result.error("订单已支付");
        }

        PayDetails payDetails = payDetailsDao.selectByOrderId(order.getOrdersNo());
        if (payDetails == null) {
            payDetails = new PayDetails();
            payDetails.setState(0);
            payDetails.setCreateTime(sdf.format(new Date()));
            payDetails.setOrderId(order.getOrdersNo());
            payDetails.setUserId(order.getUserId());
            payDetails.setMoney(order.getPayMoney().doubleValue());
            payDetails.setType(1);
            payDetails.setClassify(9);
            payDetails.setTradeNo(AliPayOrderUtil.createOrderId());
            payDetailsDao.insert(payDetails);
        } else {
            payDetails.setTradeNo(AliPayOrderUtil.createOrderId());
            payDetailsDao.updateById(payDetails);
        }

        BaseResp baseResp = WuyouPay.payOrder(payDetails.getTradeNo(), order.getPayMoney().toString(), request.getHeader("User-Agent"));
        if (baseResp.getCode() != 200) {
            return Result.error(baseResp.getMsg());
        }

        return Result.success().put("data", baseResp.getData());
    }

    @PostMapping("/extractNotify")
    public String extractNotify(HttpServletRequest request, NotifyDto notifyDto) {
        log.info("无忧支付提现回调， {}", notifyDto);
        Map<String, Object> params = new HashMap<>();
        params.put("callbacks", notifyDto.getCallbacks());
        params.put("total", notifyDto.getTotal());
        params.put("out_trade_no", notifyDto.getOut_trade_no());
        params.put("status", notifyDto.getStatus());
        params.put("msg", notifyDto.getMsg());

        String sign = Encrypt.getParamsSign(params);
        if (!sign.equals(notifyDto.getSign())) {
            log.error("无忧支付提现回调签名错误, 参数: {}，签名结果：{}", JSONObject.toJSONString(notifyDto), sign);
//            return "签名错误";
        }
        CashOut cashOut = cashOutDao.selectOne(new QueryWrapper<CashOut>().eq("order_number", notifyDto.getOut_trade_no()));
        if (cashOut != null) {
            if ("2".equals(notifyDto.getStatus())) {
                cashOut.setState(1);
            } else {
                cashOut.setState(2);
                cashOut.setRefund(notifyDto.getMsg());

                UserMoneyDetails userMoneyDetails = new UserMoneyDetails(
                        cashOut.getUserId(),null,null,"提现失败",4,1,1,
                        new BigDecimal(cashOut.getMoney()),"提现失败存入余额" + cashOut.getMoney() + "元");
                //存入余额 钱
                userMoneyService.updateAmount(1, cashOut.getUserId(), Double.parseDouble(cashOut.getMoney()));
                userMoneyDetailsService.save(userMoneyDetails);
            }
            cashOutDao.updateById(cashOut);
        }
        return "success";
    }

    @PostMapping("/notify")
    public String notify(HttpServletRequest request, NotifyDto notifyDto) {
        log.info("无忧支付回调， {}", notifyDto);
        Map<String, Object> params = new HashMap<>();
        params.put("callbacks", notifyDto.getCallbacks());
        params.put("total", notifyDto.getTotal());
        params.put("out_trade_no", notifyDto.getOut_trade_no());
        params.put("pay_time", notifyDto.getPay_time());

        String sign = Encrypt.getParamsSign(params);
        if (!sign.equals(notifyDto.getSign())) {
            log.error("无忧支付回调签名错误, 参数: {}，签名结果：{}", JSONObject.toJSONString(notifyDto), sign);
//            return "签名错误";
        }

        log.info("无忧支付回调成功, 参数: {}", JSONObject.toJSONString(notifyDto));

        PayDetails payDetails = payDetailsDao.selectByTradeNo(notifyDto.getOut_trade_no());

        if (payDetails.getState() != 0) {
            log.info("订单表信息丢失！");
        }

        Orders order = ordersService.selectOrderByOrdersNo(payDetails.getOrderId());
        if (order == null) {
            log.error("无忧支付回调订单不存在, 参数: {}", JSONObject.toJSONString(notifyDto));
            return "订单不存在";
        }

        if (order.getStatus() != 0) {
            log.error("无忧支付回调订单已支付, 参数: {}", JSONObject.toJSONString(notifyDto));
            return "订单已支付";
        }

        String format = sdf.format(new Date());
        payDetailsDao.updateState(payDetails.getId(), 1, format, notifyDto.getOut_trade_no());

        order.setPayWay(9);
        order.setStatus(1);
        order.setPayTime(DateUtils.format(new Date()));

        UserEntity user = userService.selectUserById(order.getUserId());
        UserEntity byUser = userService.queryByInvitationCode(user.getInviterCode());
        Map<String, Object> map = inviteService.updateInvite(byUser, format, user.getUserId(), order.getPayMoney());
        Object oneUserId = map.get("oneUserId");
        if (oneUserId != null) {
            order.setOneUserId(Long.parseLong(String.valueOf(oneUserId)));
            order.setOneMoney(new BigDecimal(String.valueOf(map.get("oneMoney"))));
        }
        Object twoUserId = map.get("twoUserId");
        if (twoUserId != null) {
            order.setTwoUserId(Long.parseLong(String.valueOf(twoUserId)));
            order.setTwoMoney(new BigDecimal(String.valueOf(map.get("twoMoney"))));
        }
        Object sysUserId = map.get("sysUserId");
        if (sysUserId != null) {
            order.setSysUserId(Long.parseLong(String.valueOf(sysUserId)));
            order.setQdMoney(new BigDecimal(String.valueOf(map.get("qdMoney"))));
        }
        ordersService.updateById(order);
        ordersService.insertOrders(order);
        CompletableFuture.runAsync(() -> {
            activities(user, byUser);
        });
        return "success";
    }

    public void activities(UserEntity user, UserEntity sourceUser) {
        //分享达标
        if (sourceUser != null && sourceUser.getUserId() != 1) {
            QueryWrapper<UserMoneyDetails> queryWrapper = new QueryWrapper<>();
            queryWrapper.eq("classify", 7);
            queryWrapper.eq("user_id", sourceUser.getUserId());
            queryWrapper.eq("by_user_id", user.getUserId());
            int count = userMoneyDetailsService.count(queryWrapper);
            if (count == 0) {
                //满3笔
                Integer sumOrderNum = ordersService.countOrderNum(user.getUserId(), null);
                if (sumOrderNum > Integer.parseInt(commonRepository.findOne(913).getValue())) {
                    String amount = commonRepository.findOne(912).getValue();
                    UserMoneyDetails userMoneyDetails = new UserMoneyDetails();
                    userMoneyDetails.setClassify(7);
                    userMoneyDetails.setMoney(new BigDecimal(amount));
                    userMoneyDetails.setUserId(sourceUser.getUserId());
                    userMoneyDetails.setByUserId(user.getUserId());
                    userMoneyDetails.setCreateTime(DateUtil.now());
                    userMoneyDetails.setContent("分享达标奖励" + amount + "元");
                    userMoneyDetails.setTitle("分享达标奖励");
                    userMoneyDetails.setState(2);
                    userMoneyDetails.setType(1);
                    userMoneyDetailsService.save(userMoneyDetails);
                    //存入余额 钱
                    userMoneyService.updateAmount(1, sourceUser.getUserId(), Double.parseDouble(amount));
                }
            }
        }
    }
}
