package com.izouma.jiashanxia.service;

import cn.hutool.core.util.StrUtil;
import com.izouma.jiashanxia.domain.CommissionRecord;
import com.izouma.jiashanxia.domain.OrderInfo;
import com.izouma.jiashanxia.domain.User;
import com.izouma.jiashanxia.domain.Withdraw;
import com.izouma.jiashanxia.dto.PageQuery;
import com.izouma.jiashanxia.enums.PayMethod;
import com.izouma.jiashanxia.enums.TransactionType;
import com.izouma.jiashanxia.enums.WithdrawStatus;
import com.izouma.jiashanxia.exception.BusinessException;
import com.izouma.jiashanxia.repo.CommissionRecordRepo;
import com.izouma.jiashanxia.repo.UserRepo;
import com.izouma.jiashanxia.repo.WithdrawRepo;
import com.izouma.jiashanxia.utils.JpaUtils;
import lombok.AllArgsConstructor;
import org.springframework.data.domain.Page;
import org.springframework.stereotype.Service;

import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;

@Service
@AllArgsConstructor
public class WithdrawService {

    private WithdrawRepo         withdrawRepo;
    private UserRepo             userRepo;
    private CommissionRecordRepo commissionRecordRepo;

    public Page<Withdraw> all(PageQuery pageQuery) {
        pageQuery.setSort("createdAt,desc");
        return withdrawRepo.findAll(JpaUtils.toSpecification(pageQuery, Withdraw.class), JpaUtils.toPageRequest(pageQuery));
    }

    /*
    后台列表
     */
    public Page<Withdraw> backAll(PageQuery pageQuery) {
        return withdrawRepo.findAll(((root, criteriaQuery, criteriaBuilder) -> {
            List<Predicate> and = JpaUtils.toPredicates(pageQuery, Withdraw.class, root, criteriaQuery, criteriaBuilder);
            if (StrUtil.isNotEmpty(pageQuery.getSearch())) {
                this.getNickname(pageQuery.getSearch(), and, root, criteriaBuilder);
            }
            return criteriaBuilder.and(and.toArray(new Predicate[0]));
        }), JpaUtils.toPageRequest(pageQuery));
    }

    /*
    搜索用户昵称
     */
    public void getNickname(String search, List<Predicate> and, Root<?> root, CriteriaBuilder criteriaBuilder) {
        List<Predicate> or = new ArrayList<>();
        or.add(and.get(and.size() - 1));
        and.remove(and.get(and.size() - 1));
        or.add(criteriaBuilder.like(root.join("user").get("nickname"), "%" + search + "%"));
        and.add(criteriaBuilder.or(or.toArray(new Predicate[0])));
    }


    /*
    提现申请
     */
    public Withdraw apply(Long userId, BigDecimal amount, PayMethod payMethod, String realName, String account) {
        if (BigDecimal.ZERO.compareTo(amount) >= 0) {
            throw new BusinessException("提现金额小于等于零");
        }
        User user = userRepo.findById(userId).orElseThrow(new BusinessException("无用户"));
        if (amount.compareTo(user.getAmount()) > 0) {
            throw new BusinessException("提现金额大于余额");
        }
        // 先扣款
        BigDecimal subtract = user.getAmount().subtract(amount);
        user.setAmount(subtract);
        userRepo.save(user);

        // 提现申请
        return withdrawRepo.save(
                Withdraw.builder()
                        .userId(userId)
                        .realName(realName)
                        .account(account)
                        .amount(amount)
                        .balance(subtract)
                        .status(WithdrawStatus.PENDING)
                        .payMethod(payMethod)
                        .build());

    }

    /*
    审核
     */
    public void audit(Long withdrawId, Boolean pass) {
        Withdraw withdraw = withdrawRepo.findById(withdrawId).orElseThrow(new BusinessException("无提现记录"));
        LocalDateTime now = LocalDateTime.now();
        if (pass) {
            withdraw.setStatus(WithdrawStatus.SUCCESS);
            withdraw.setAuditTime(now);
            // 个人佣金流水
            commissionRecordRepo.save(CommissionRecord.builder()
                    .userId(withdraw.getUserId())
                    .amount(withdraw.getAmount())
                    .payMethod(PayMethod.YUE)
                    .transactionType(TransactionType.WITHDRAW)
                    .transactionId(withdrawId.toString())
                    .build());
            withdrawRepo.save(withdraw);
            return;
        }
        withdraw.setStatus(WithdrawStatus.FAIL);
        withdraw.setAuditTime(now);
        // 拒绝后加上余额
        User user = userRepo.findById(withdraw.getUserId()).orElseThrow(new BusinessException("无用户"));
        user.setAmount(user.getAmount().add(withdraw.getAmount()));
        userRepo.save(user);
        withdrawRepo.save(withdraw);
    }


}
