package cn.com.ty.lift.quan.pay.service.impl;

import cn.com.ty.lift.common.aliservice.alipay.AlipayUtil;
import cn.com.ty.lift.quan.pay.dao.entity.PayRecord;
import cn.com.ty.lift.quan.pay.dao.entity.UserInfo;
import cn.com.ty.lift.quan.pay.dao.entity.model.PayReq;
import cn.com.ty.lift.quan.pay.dao.mapper.UserInfoMapper;
import cn.com.ty.lift.quan.pay.service.UserInfoService;
import cn.com.xwy.boot.web.dto.RestResponse;
import com.alipay.api.AlipayApiException;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.IdWorker;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.AllArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.List;
import java.util.Map;

/**
 * <p>
 * 用户表 服务实现类
 * </p>
 *
 * @author wang-hai-cheng
 * @since 2020-01-05
 */
@Service
@AllArgsConstructor
public class UserInfoServiceImpl extends ServiceImpl<UserInfoMapper, UserInfo> implements UserInfoService {

    private final PayRecordServiceImpl recordService;

    public RestResponse bind(UserInfo userInfo) {
        UserInfo byId = this.getById(userInfo.getUserId());
        if (byId != null) {
            byId.setAlipayAccount(userInfo.getAlipayAccount());
            //获取前端传过来的支付宝账号
            if (this.saveOrUpdate(byId)) {
                return RestResponse.success(null, "成功");
            }
        }
        return RestResponse.fail();
    }

    /**
     * 创建充值订单，创建提现待审核订单
     *
     * @since 2019/12/27 10:35
     */
    @Transactional
    public RestResponse pay(PayReq req) {
        if (req.getTotalAmount().compareTo(BigDecimal.ZERO) < 1) {
            return RestResponse.fail("金额必须大于0");
        }
        UserInfo byId = this.getById(req.getUserId());
        String outTradeNo = IdWorker.getIdStr();
        PayRecord record = new PayRecord();
        //设置用户id
        record.setUserId(req.getUserId());
        //设置操作金额
        record.setTotalAmount(req.getTotalAmount());
        //设置订单号
        record.setOutTradeNo(outTradeNo);
        //设置订单标题
        record.setSubject(req.getSubject());
        //设置订单备注
        record.setSubjectRemark(req.getBody());
        //设置订单创建时间
        record.setCreateDatetime(LocalDateTime.now());
        //设置订单状态
        record.setStatus(0);
        //设置支付宝订单号
        String tradeNo;
        //task 1 创建充值订单
        if (req.getTask().equals(1)) {
            //向支付宝发创建充值订单请求
            try {
                tradeNo = AlipayUtil
                        .create(byId.getAlipayAccount(), outTradeNo, req.getSubject(), req.getBody(), req.getTotalAmount());
            } catch (AlipayApiException e) {
                e.printStackTrace();
                throw new RuntimeException("支付宝创建订单失败");
            }
            if (tradeNo != null) {
                record.setType(1);
                record.setTradeNo(tradeNo);
                //保存订单信息到数据库
                if (recordService.save(record)) {
                    return RestResponse.success(outTradeNo);
                }
            }
            return RestResponse.fail();
        }

        //task 2 创建提现审核订单
        if (req.getTask().equals(2)) {
            if (req.getTotalAmount().compareTo(byId.getBalance()) > 0) {
                return RestResponse.fail("账号余额不足");
            }
            if (recordService.getOne(new QueryWrapper<PayRecord>()
                    .eq("type", 2)
                    .eq("status", 0)) != null) {
                return RestResponse.fail("已有提现订单");
            }
            int size = recordService.list(new QueryWrapper<PayRecord>()
                    .eq("user_id", req.getUserId())
                    .eq("type", 2)
                    .gt("create_datetime", LocalDate.now() + " 00:00:00")).size();
            if (size >= 3) {
                return RestResponse.fail("每天仅支持提现3次");
            }
            //创建提现订单
            byId.setFreezeBalance(req.getTotalAmount());
            byId.setBalance(byId.getBalance().subtract(req.getTotalAmount()));
            record.setType(2);
            //保存订单信息到数据库
            if (this.updateById(byId) && recordService.save(record)) {
                return RestResponse.success(record.getOutTradeNo(), "成功");
            }
        }
        return RestResponse.fail();
    }

    /**
     * 审核订单
     *
     * @param req 用户id,资金操作记录id
     * @return status 1完成 0未完成
     * @since 2019/12/27 14:50
     */
    @Transactional
    public RestResponse order(PayReq req) throws AlipayApiException {
        PayRecord recordByOutTradeNo = recordService.getOne(new QueryWrapper<PayRecord>()
                .eq(req.getOutTradeNo() != null, "out_trade_no", req.getOutTradeNo()));
        //如果已经完成的订单
        if (recordByOutTradeNo.getStatus() == 1) {
            return RestResponse.fail("订单已完成");
        }
        if (recordByOutTradeNo.getStatus() == 2) {
            return RestResponse.fail("交易已取消");
        }
        //如果记录是充值
        if (recordByOutTradeNo.getType() == 1) {
            UserInfo payById = this.getById(recordByOutTradeNo.getUserId());
            //调用支付宝订单查询接口，查询充值订单是否完成
            Map<String, Object> orderInfo = AlipayUtil.order(recordByOutTradeNo.getTradeNo());
            if ((boolean) orderInfo.get("status")) {
                //完成就设置用户在平台中的余额
                payById.setBalance(payById.getBalance()
                        .add(recordByOutTradeNo.getTotalAmount()));
                //设置订单状态为1完成，订单完成时间为当前
                if (this.updateById(payById)) {
                    recordByOutTradeNo.setStatus(1);
                    recordByOutTradeNo.setFinishDatetime(LocalDateTime.now());
                    payById.setAlipayId(orderInfo.get("alipayId").toString());
                    if (this.updateById(payById) && recordService.updateById(recordByOutTradeNo)) {
                        //全部保存成功就返回 “成功”
                        return RestResponse.success(null, "成功");
                    }
                }
            }
            //如果查询充值订单没有完成，就返回 “订单还未支付”
            return RestResponse.fail("订单还未支付");
        }
        //如果记录是提现
        if (recordByOutTradeNo.getType() == 2) {
            UserInfo byId = this.getById(recordByOutTradeNo.getUserId());
            //调用支付宝企业转账到个人 接口
            String tradeNo = AlipayUtil.withdraw(
                    byId.getAlipayId(),
                    recordByOutTradeNo.getOutTradeNo(),
                    recordByOutTradeNo.getSubject(),
                    recordByOutTradeNo.getTotalAmount());
            //如果有订单码说明转账成功
            if (tradeNo != null) {
                //设置冻结金额为0
                byId.setFreezeBalance(new BigDecimal(0));
                //设置支付宝订单id，订单状态，订单完成时间
                recordByOutTradeNo.setTradeNo(tradeNo);
                recordByOutTradeNo.setStatus(1);
                recordByOutTradeNo.setFinishDatetime(LocalDateTime.now());
                if (this.updateById(byId) && recordService.updateById(recordByOutTradeNo)) {
                    return RestResponse.success(null, "成功");
                }
            }
            return RestResponse.fail();
        }
        return RestResponse.failParam();
    }

    //充值及提现订单列表
    public RestResponse orders(PayReq req) {
        List<PayRecord> payRecords = recordService.list(
                new QueryWrapper<PayRecord>()
                        .eq("user_id", req.getUserId())
                        .eq(req.getTask() != null, "type", req.getTask())
                        .eq(req.getStatus() != null, "status", req.getStatus()));
        if (payRecords.isEmpty()) {
            return RestResponse.success();
        }
        return RestResponse.success(payRecords);
    }

    //取消订单
    public RestResponse cancel(PayReq req) throws AlipayApiException {
        PayRecord recordByOutTradeNo = recordService.getOne(new QueryWrapper<PayRecord>()
                .eq("out_trade_no", req.getOutTradeNo()));
        if (recordByOutTradeNo == null) {
            return RestResponse.fail("订单不存在");
        }

        recordByOutTradeNo.setFinishDatetime(LocalDateTime.now());

        //如果订单是充值类型
        if (recordByOutTradeNo.getStatus() == 0) {
            if (recordByOutTradeNo.getType() == 1) {
                if (AlipayUtil.cancel(recordByOutTradeNo.getTradeNo())) {
                    recordByOutTradeNo.setStatus(2);
                    if (recordService.updateById(recordByOutTradeNo)) {
                        return RestResponse.success(null, "成功");
                    }
                }
            }
            //如果订单是提现类型
            if (recordByOutTradeNo.getType() == 2) {
                UserInfo byId = this.getById(recordByOutTradeNo.getUserId());
                byId.setBalance(byId.getBalance().add(byId.getFreezeBalance()));
                byId.setFreezeBalance(BigDecimal.ZERO);
                recordByOutTradeNo.setStatus(2);
                if (this.updateById(byId) && recordService.updateById(recordByOutTradeNo)) {
                    return RestResponse.success(null, "成功");
                }
            }
        }
        return RestResponse.fail();
    }
}
