package com.jxy.order.service.impl;

import com.alibaba.fastjson.JSON;
import com.jxy.common.core.RedisTransKey;
import com.jxy.common.core.Result.R;
import com.jxy.common.core.utils.DateUtils;
import com.jxy.common.core.utils.StringUtils;
import com.jxy.common.core.web.Result.AjaxResult;
import com.jxy.common.redis.service.RedisService;
import com.jxy.common.security.utils.SecurityUtils;
import com.jxy.order.dto.*;
import com.jxy.order.entity.UserBalance;
import com.jxy.order.mapper.OrderMapper;
import com.jxy.order.mapper.WithdrawMapper;
import com.jxy.order.service.OrderService;
import com.jxy.order.service.WithdrawService;
import com.jxy.order.vo.*;
import com.jxy.system.api.RemoteMailService;
import com.jxy.system.api.RemoteUserService;
import com.jxy.system.api.entity.EmailCodeEntity;
import com.jxy.system.api.entity.EmailEntity;
import com.jxy.system.api.entity.GetEmailCodeEntity;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

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

/**
 * @Description 提现服务业务层
 * @Date 2023/5/31 15:22
 * @Author 杜懿
 */
@Service
public class WithdrawServiceImpl implements WithdrawService {

    @Autowired
    private RemoteUserService remoteUserService;

    @Autowired
    private RemoteMailService remoteMailService;

    @Autowired
    private RedisService redisService;

    @Autowired
    private WithdrawMapper withdrawMapper;

    @Autowired
    private OrderMapper orderMapper;

    @Autowired
    private OrderService orderService;


    @Override
    public AjaxResult apply(WithdrawApplyVo vo) {
        //先验证emailCode
        String email = SecurityUtils.getLoginUser().getSysUser().getEmail();
        if(redisService.hasKey(RedisTransKey.getAddCreditEmailKey(email))){
            Object o = redisService.getCacheObject(RedisTransKey.getAddCreditEmailKey(email));//user:emailCode:username

            EmailCodeEntity emailCodeEntity1 = JSON.parseObject(JSON.toJSONString(o), EmailCodeEntity.class);
            System.out.println(emailCodeEntity1);

            //JSONObject.parseObject()
            EmailCodeEntity emailCodeEntity = JSON.parseObject(JSON.toJSONString(o), EmailCodeEntity.class);
            //验证验证码
            if(!vo.getEmailCode().equals(emailCodeEntity.getEmailCode())){
                return AjaxResult.error("邮箱验证码错误");
            }
        }else {
            return AjaxResult.error("验证码未获取或已过期，请重新获取验证码");
        }
        //生成提现订单
        UserAccountDto userAccount = orderMapper.getUserAccountByUserId(SecurityUtils.getUserId());
        UserAccountDto newAccount = new UserAccountDto();
        BeanUtils.copyProperties(userAccount,newAccount);
        if("USDT".equals(vo.getCoin())){
            if(userAccount.getUsdt().compareTo(vo.getAmount()) < 0){
                //余额不足
                return AjaxResult.error("余额不足,当前USDT余额为"+userAccount.getUsdt());
            }else {
                newAccount.setUsdt(newAccount.getUsdt().subtract(vo.getAmount()));
            }
        }

        if("USDC".equals((vo.getCoin()))){
            if(userAccount.getUsdc().compareTo(vo.getAmount()) < 0){
                //余额不足
                return AjaxResult.error("余额不足,当前USDC余额为"+userAccount.getUsdc());
            }else {
                newAccount.setUsdc(newAccount.getUsdc().subtract(vo.getAmount()));
            }
        }

        if("BUSD".equals((vo.getCoin()))){
            if(userAccount.getBusd().compareTo(vo.getAmount()) < 0){
                return AjaxResult.error("余额不足,当前BUSD余额为"+userAccount.getBusd());
            }
            else {
                newAccount.setBusd(newAccount.getBusd().subtract(vo.getAmount()));
            }
        }

        //余额充足 生成提现订单
        vo.setUserId(SecurityUtils.getUserId());
        if(withdrawMapper.insertWithdraw(vo)){
            //扣除余额
            if(orderMapper.updateUserAccount(newAccount,userAccount.getUsdt(),userAccount.getUsdc(),userAccount.getBusd())){
                //记录此时用户的账户余额
                return AjaxResult.success("提现申请已提交，稍后可在提现申请记录查询提现订单处理结果");
            }else {
                return AjaxResult.error("提现申请处理期间余额有变动,提现申请失败，请稍后再试。");
            }
        }else {
            return AjaxResult.error("服务器繁忙，请稍后重试");
        }
    }

    @Override
    public AjaxResult getDetail(Long id) {

        WithdrawDetailDto detail = withdrawMapper.getWithdrawDetailById(id);

        if(StringUtils.isNull(detail)){
            return AjaxResult.error("未查询到对应订单,请检查传参，并稍后再试");
        }

        detail.setAppliedTime(DateUtils.addHours(detail.getAppliedTime(),16));

        UserAccountDto account = orderMapper.getUserAccountByUserId(detail.getUserId());
        if("USDT".equals(detail.getCoin().toUpperCase())){
            detail.setBalance(account.getUsdt());
        }else if("USDC".equals(detail.getCoin().toUpperCase())){
            detail.setBalance(account.getUsdc());
        }else if("BUSD".equals(detail.getCoin().toUpperCase())){
            detail.setBalance(account.getBusd());
        }

        return AjaxResult.success(detail);

    }

    @Override
    public AjaxResult handle(WithdrawHandleVo vo) {

        WithdrawDetailDto dto = withdrawMapper.getWithdrawDetailById(vo.getId());

        if(vo.getOper() == 1){
            //通过 需要填入实退时间、实退金额、实退txid
            if(StringUtils.isBlank(vo.getRefundTxid())){
                return AjaxResult.error("通过提现申请需要提供实退txid");
            }
            if(StringUtils.isBlank(vo.getRefundAddress())){
                return AjaxResult.error("通过提现申请需要提供退款发起地址");
            }
            if(withdrawMapper.updateWithdraw(vo)){
                //更新成功 余额表记录信息
                UserBalance ub= new UserBalance();
                ub.setCoin(dto.getCoin());
                ub.setChain(dto.getChain());
                ub.setUserId(dto.getUserId());
                ub.setTxid(dto.getRefundTxid());

                if("USDT".equals(dto.getCoin().toUpperCase())){
                    ub.setBalanceUSDT(dto.getAmount());
                }
                if("USDC".equals(dto.getCoin().toUpperCase())){
                    ub.setBalanceUSDC(dto.getAmount());
                }
                if("BUSD".equals(dto.getCoin().toUpperCase())){
                    ub.setBalanceBUSD(dto.getAmount());
                }
                ub.setNotes(2);
                ub.setMessage("用户提现通过，提现金额:"+dto.getAmount());
                if(orderMapper.insertUserBalance(ub)){
                    ////插入成功 发送邮件通知用户
                    EmailEntity entity = new EmailEntity();
                    entity.setEmail(SecurityUtils.getLoginUser().getSysUser().getEmail());
                    entity.setSubject("账户提现结果返回");
                    entity.setText("提现成功,可在网站查看提现详情!");
                    remoteMailService.sendTextMail(entity);
                }else {
                    //修改失败
                }
                return AjaxResult.success("提现申请已通过");
            }else{
                return AjaxResult.error("服务器忙，请稍后再试");
            }
        }else if(vo.getOper() == 0) {
            //拒绝 需要填写msg
            if(StringUtils.isBlank(vo.getMsg())){
                return AjaxResult.error("拒绝请写备注信息,后台此时未收到备注信息");
            }

            //WithdrawDetailDto dto = withdrawMapper.getWithdrawDetailById(vo.getId());
            if(withdrawMapper.updateWithdraw(vo)){
                //todo rabbitMQ通知提现结果
                //加回用户余额
                orderService.updateUserAccountAfterRefuseWithdraw(dto.getUserId(), dto.getCoin(), dto.getAmount());
                return AjaxResult.success("提现申请已拒绝");
            }else{
                return AjaxResult.error("数据库修改失败，请稍后再试");
            }

        }else {
            return AjaxResult.error("操作传参有误，请检查传参");
        }


    }

    @Override
    public List<WithdrawPraviteDto> privateWithdraw(OrderStatusVo vo) {

        List<WithdrawPraviteDto> list = withdrawMapper.getWithdrawByUserId(SecurityUtils.getUserId(),vo.getStatus());
        //list.stream().forEach(e ->{
        //    e.setAppliedTime(DateUtils.addHours(e.getAppliedTime(),16));
        //});
        return list;
    }

    @Override
    public List<WithdrawDto> getAllWithdraw(OrderStatusVo vo) {

        if(StringUtils.isNotBlank(vo.getAddress())){
            //address有传参需要格式验证
            String em = "^[a-zA-Z0-9][\\w\\.-]*[a-zA-Z0-9]@[a-zA-Z0-9][\\w\\.-]*[a-zA-Z0-9]\\.[a-zA-Z][a-zA-Z\\.]*[a-zA-Z]$";
            if(!vo.getAddress().matches(em)){
                //address接收到的不是邮箱 则返回空list
                return  new ArrayList<>();
            }
        }
        List<WithdrawDto> list = withdrawMapper.getWithdrawByStatus(vo.getStatus(),vo.getAddress());
        //list.stream().forEach(e ->{
        //    e.setAppliedTime(DateUtils.addHours(e.getAppliedTime(),16));
        //});
        return list;
    }

    @Override
    public AjaxResult sendAddCreditEmail() {
        GetEmailCodeEntity entity = new GetEmailCodeEntity();
        entity.setEmail(SecurityUtils.getLoginUser().getSysUser().getEmail());
        entity.setUserName( SecurityUtils.getUsername());
        R<?> result = remoteMailService.sendAddCreditEmailCode(entity);
        System.out.println(result);
        if (result.getCode() == 200){
            return AjaxResult.success("邮箱发送成功，有效期十分钟，请注意查收。");
        }else {
            return AjaxResult.error("邮箱发送成功，有效期十分钟，请注意查收！");
        }
    }
}
