package co.yixiang.yshop.module.distributor.service.distributorwages;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.StrUtil;
import co.yixiang.yshop.framework.common.pojo.PageResult;
import co.yixiang.yshop.module.distributor.controller.admin.distributorwageslog.vo.DistributorWagesLogCreateReqVO;
import co.yixiang.yshop.module.distributor.controller.admin.distributorwageslog.vo.DistributorWagesLogExportReqVO;
import co.yixiang.yshop.module.distributor.controller.admin.distributorwageslog.vo.DistributorWagesLogPageReqVO;
import co.yixiang.yshop.module.distributor.controller.admin.distributorwageslog.vo.DistributorWagesLogUpdateReqVO;
import co.yixiang.yshop.module.distributor.controller.admin.distributorwithdrawalmethod.vo.DistributorWithdrawalMethodExportReqVO;
import co.yixiang.yshop.module.distributor.controller.admin.distributorwithdrawalmethod.vo.DistributorWithdrawalMethodRespVO;
import co.yixiang.yshop.module.distributor.controller.admin.distributorwithdrawalmethod.vo.DistributorWithdrawalMethodUpdateReqVO;
import co.yixiang.yshop.module.distributor.controller.app.distributorproduct.vo.AppDistributorProductRespVO;
import co.yixiang.yshop.module.distributor.controller.app.distributorwages.vo.AppDistributorWagesPageReqVO;
import co.yixiang.yshop.module.distributor.controller.app.distributorwages.vo.AppDistributorWagesPageRespVO;
import co.yixiang.yshop.module.distributor.controller.app.distributorwages.vo.AppDistributorWagesWithdrawReqVO;
import co.yixiang.yshop.module.distributor.convert.distributorwithdrawalmethod.DistributorWithdrawalMethodConvert;
import co.yixiang.yshop.module.distributor.dal.dataobject.distributor.DistributorDO;
import co.yixiang.yshop.module.distributor.dal.dataobject.distributororder.DistributorOrderDO;
import co.yixiang.yshop.module.distributor.dal.dataobject.distributorwages.DistributorWagesDO;
import co.yixiang.yshop.module.distributor.dal.dataobject.distributorwageslog.DistributorWagesLogDO;
import co.yixiang.yshop.module.distributor.dal.dataobject.distributorwithdrawalmethod.DistributorWithdrawalMethodDO;
import co.yixiang.yshop.module.distributor.enums.DistributorWagesLogTypeEnum;
import co.yixiang.yshop.module.distributor.enums.DistributorWithdrawalMethodTypeEnum;
import co.yixiang.yshop.module.distributor.service.distributor.DistributorService;
import co.yixiang.yshop.module.distributor.service.distributorlevel.DistributorLevelFacade;
import co.yixiang.yshop.module.distributor.service.distributorwageslog.DistributorWagesLogService;
import co.yixiang.yshop.module.distributor.service.distributorwithdrawalmethod.DistributorWithdrawalMethodService;
import co.yixiang.yshop.module.system.api.logger.dto.OperateLogCreateReqDTO;
import org.springframework.stereotype.Service;
import org.springframework.validation.annotation.Validated;

import javax.annotation.Resource;
import java.time.LocalDateTime;
import java.util.List;

import static co.yixiang.yshop.framework.common.exception.util.ServiceExceptionUtil.exception;
import static co.yixiang.yshop.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId;
import static co.yixiang.yshop.module.distributor.enums.ErrorCodeConstants.*;

@Service
@Validated
public class DistributorWagesFacadeImpl implements DistributorWagesFacade {

    @Resource
    private DistributorService distributorService;

    @Resource
    private DistributorWagesLogService distributorWagesLogService;

    @Resource
    private DistributorWithdrawalMethodService distributorWithdrawalMethodService;

    @Resource
    private DistributorWagesService distributorWagesService;

    @Resource
    private DistributorLevelFacade distributorLevelFacade;

    /**
     * 我的佣金总计
     *
     * @param createTime 时间
     * @return 佣金
     */
    @Override
    public AppDistributorWagesPageRespVO getWages(LocalDateTime[] createTime) {
        AppDistributorWagesPageRespVO respVO = new AppDistributorWagesPageRespVO();

        // 获取分销商
        Long userId = getLoginUserId();
        DistributorDO distributorDO = distributorService.getDistributorByUserId(userId);
        DistributorWagesLogExportReqVO wagesLogExportReqVO = new DistributorWagesLogExportReqVO();
        wagesLogExportReqVO.setDistributorId(distributorDO.getId());
        wagesLogExportReqVO.setType(DistributorWagesLogTypeEnum.COMPLETE.getType());
        wagesLogExportReqVO.setCreateTime(createTime);
        // 收入 只有已入账
        DistributorWagesLogDO incomeSum = distributorWagesLogService.sumAmount(wagesLogExportReqVO);
        if (incomeSum != null) {
            respVO.setIncome(incomeSum.getAmount());
        }
        wagesLogExportReqVO.setType(DistributorWagesLogTypeEnum.WITHDRAW_COMPLETE.getType());
        // 支出 只有已提现

        DistributorWagesLogDO expensesSum = distributorWagesLogService.sumAmount(wagesLogExportReqVO);
        if (expensesSum != null) {
            respVO.setExpenses(expensesSum.getAmount());
        }

        return respVO;
    }

    @Override
    public PageResult<DistributorWagesLogDO> getWagesPage(AppDistributorWagesPageReqVO reqVO) {
        // 获取分销商
        Long userId = getLoginUserId();
        DistributorDO distributorDO = distributorService.getDistributorByUserId(userId);

        DistributorWagesLogPageReqVO pageReqVO = BeanUtil.copyProperties(reqVO, DistributorWagesLogPageReqVO.class);
        pageReqVO.setDistributorId(distributorDO.getId());
        return distributorWagesLogService.getWagesLogPage(pageReqVO);
    }

    @Override
    public void withdraw(AppDistributorWagesWithdrawReqVO reqVO) {
        Long userId = getLoginUserId();
        DistributorDO distributorDO = distributorService.getDistributorByUserId(userId);
        DistributorWithdrawalMethodDO withdrawalMethod = distributorWithdrawalMethodService.getWithdrawalMethod(reqVO.getId());
        // 匹配提现方式与用户
        if (!withdrawalMethod.getDistributorId().equals(distributorDO.getId())) {
            throw exception(WITHDRAWAL_METHOD_EXISTS_USER);
        }
        // 获取用户佣金余额
        DistributorWagesDO distributorWagesDO = distributorWagesService.getWagesByDistributorId(distributorDO.getId());
        // 判断佣金小于提现金额
        if (distributorWagesDO.getAmount().compareTo(reqVO.getAmount()) < 0) {
            throw exception(WITHDRAWAL_AMOUNT_INSUFFICIENT);
        }

        if (withdrawalMethod.getType().equals(DistributorWithdrawalMethodTypeEnum.AIL_PAY.getType()) && StrUtil.isEmpty(withdrawalMethod.getAccountNum())) {
            throw exception(WITHDRAWAL_ALI_NOT_EXISTS);
        }

        if (!distributorWagesService.reduceAmount(distributorDO.getId(), reqVO.getAmount())) {
            throw exception(WITHDRAWAL_AMOUNT_INSUFFICIENT);
        }

        // 保存记录
        DistributorWagesLogCreateReqVO distributorWagesLogCreateReqVO = new DistributorWagesLogCreateReqVO();
        distributorWagesLogCreateReqVO.setWagesId(distributorWagesDO.getId());
        distributorWagesLogCreateReqVO.setUserId(userId);

        distributorWagesLogCreateReqVO.setType(DistributorWagesLogTypeEnum.WITHDRAW_WAIT.getType());
        distributorWagesLogCreateReqVO.setAmount(reqVO.getAmount());
        distributorWagesLogCreateReqVO.setDistributorId(distributorDO.getId());
        distributorWagesLogCreateReqVO.setDistributorName(distributorDO.getRealName());
        distributorWagesLogCreateReqVO.setMethodType(withdrawalMethod.getType());
        distributorWagesLogService.createWagesLog(distributorWagesLogCreateReqVO);

    }

    @Override
    public void updateWithdrawalMethod(DistributorWithdrawalMethodUpdateReqVO updateReqVO) {
        Long userId = getLoginUserId();
        DistributorDO distributorDO = distributorService.getDistributorByUserId(userId);
        DistributorWithdrawalMethodDO withdrawalMethod = distributorWithdrawalMethodService.getWithdrawalMethod(updateReqVO.getId());
        // 匹配提现方式与用户
        if (!withdrawalMethod.getDistributorId().equals(distributorDO.getId())) {
            throw exception(WITHDRAWAL_METHOD_EXISTS_USER);
        }
        distributorWithdrawalMethodService.updateWithdrawalMethod(updateReqVO);
    }

    @Override
    public List<DistributorWithdrawalMethodRespVO> getWithdrawalMethodList() {
        Long userId = getLoginUserId();
        DistributorDO distributorDO = distributorService.getDistributorByUserId(userId);
        return DistributorWithdrawalMethodConvert.INSTANCE.convertList(distributorWithdrawalMethodService.getWithdrawalMethodList(new DistributorWithdrawalMethodExportReqVO().setDistributorId(distributorDO.getId())));
    }

    @Override
    public void saveWages(DistributorOrderDO x) {
        if (x.getSuperiorIdP1() != null) {
            DistributorWagesDO distributorWages = distributorWagesService.getWagesByDistributorId(x.getSuperiorIdP1());
            distributorWagesService.increaseRefuseAmount(x.getSuperiorIdP1(), x.getFirstAmount());
            DistributorWagesLogCreateReqVO createReqVO = new DistributorWagesLogCreateReqVO();
            createReqVO.setWagesId(distributorWages.getId());
            createReqVO.setUserId(x.getUserId());
            createReqVO.setUserName(x.getUserName());
            createReqVO.setType(DistributorWagesLogTypeEnum.WAIT.getType());
            createReqVO.setAmount(x.getFirstAmount());
            createReqVO.setDistributorId(x.getSuperiorIdP1());
            createReqVO.setDistributorName(x.getSuperiorNameP1());
            createReqVO.setDistributorOrderId(x.getId());
            createReqVO.setOrderId(x.getOrderId());
            distributorWagesLogService.createWagesLog(createReqVO);
        }
        if (x.getSuperiorIdP2() != null) {
            DistributorWagesDO distributorWages = distributorWagesService.getWagesByDistributorId(x.getSuperiorIdP2());
            distributorWagesService.increaseRefuseAmount(x.getSuperiorIdP2(), x.getSecondAmount());
            DistributorWagesLogCreateReqVO createReqVO = new DistributorWagesLogCreateReqVO();
            createReqVO.setWagesId(distributorWages.getId());
            createReqVO.setUserId(x.getUserId());
            createReqVO.setUserName(x.getUserName());
            createReqVO.setType(DistributorWagesLogTypeEnum.WAIT.getType());
            createReqVO.setAmount(x.getSecondAmount());
            createReqVO.setDistributorId(x.getSuperiorIdP2());
            createReqVO.setDistributorName(x.getSuperiorNameP2());
            createReqVO.setDistributorOrderId(x.getId());
            createReqVO.setOrderId(x.getOrderId());
            distributorWagesLogService.createWagesLog(createReqVO);
        }


    }

    @Override
    public void settlementWages(DistributorOrderDO x) {
        if (x.getSuperiorIdP1() != null) {
            distributorWagesService.settlementAmount(x.getSuperiorIdP1(), x.getFirstAmount());
            distributorWagesLogService.updateWagesLogType(x.getSuperiorIdP1(), x.getId(), DistributorWagesLogTypeEnum.COMPLETE.getType());
            distributorService.addAmount(x.getSuperiorIdP1(), x.getProductPrice(), x.getFirstAmount());
            distributorLevelFacade.levelUp(x.getSuperiorIdP1());

        }
        if (x.getSuperiorIdP2() != null) {
            distributorWagesService.settlementAmount(x.getSuperiorIdP2(), x.getSecondAmount());
            distributorWagesLogService.updateWagesLogType(x.getSuperiorIdP2(), x.getId(), DistributorWagesLogTypeEnum.COMPLETE.getType());
            distributorService.addAmount(x.getSuperiorIdP2(), x.getProductPrice(), x.getSecondAmount());
            distributorLevelFacade.levelUp(x.getSuperiorIdP2());
        }
    }

    @Override
    public void cancelWages(List<Long> distributorOrderIds) {
        List<DistributorWagesLogDO> distributorWagesLogDOS = distributorWagesLogService.getWagesLogList(new DistributorWagesLogExportReqVO().setDistributorOrderIds(distributorOrderIds));
        for (DistributorWagesLogDO distributorWagesLogDO : distributorWagesLogDOS) {
            // 判断是待入账状态
            if (distributorWagesLogDO.getType().equals(DistributorWagesLogTypeEnum.WAIT.getType())) {
                DistributorWagesLogUpdateReqVO distributorWagesLogUpdateReqVO = new DistributorWagesLogUpdateReqVO();
                distributorWagesLogUpdateReqVO.setId(distributorWagesLogDO.getId()).setType(DistributorWagesLogTypeEnum.CANCEL.getType());
                // 更新记录为取消
                distributorWagesLogService.updateWagesLog(distributorWagesLogUpdateReqVO);
                // 退款佣金
                distributorWagesService.reduceRefuseAmount(distributorWagesLogDO.getDistributorId(), distributorWagesLogDO.getAmount());
            }
        }
    }

}
