package com.gree.mall.manager.logic.websit;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.convert.Convert;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.core.toolkit.IdWorker;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.github.binarywang.wxpay.exception.WxPayException;
import com.gree.mall.manager.bean.admin.AdminUserCom;
import com.gree.mall.manager.bean.websit.SettlementOrderDetail;
import com.gree.mall.manager.bean.websit.SettlementOrderLogicVO;
import com.gree.mall.manager.bean.websit.WorkerSettlementLineVO;
import com.gree.mall.manager.bean.websit.WorkerSettlementVO;
import com.gree.mall.manager.commonmapper.WebsitSalesRetCMapper;
import com.gree.mall.manager.enums.IsYesNoEnum;
import com.gree.mall.manager.enums.SettlementPayTypeEnum;
import com.gree.mall.manager.enums.SettlementStatusEnum;
import com.gree.mall.manager.enums.SettlementStatusNewEnum;
import com.gree.mall.manager.exception.RemoteServiceException;
import com.gree.mall.manager.logic.common.CommonLogic;
import com.gree.mall.manager.logic.common.WechatLogic;
import com.gree.mall.manager.plus.entity.*;
import com.gree.mall.manager.plus.service.*;
import com.gree.mall.manager.zfire.bean.ZfireParamBean;
import com.gree.mall.manager.zfire.util.FieldUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

@Service
public class SettlementOrderLogic {

    @Autowired
    WebsitSalesRetCMapper websitSalesRetCMapper;

    @Autowired
    CommonLogic commonLogic;

    @Autowired
    SettlementOrderService settlementOrderService;

    @Autowired
    SettlementOrderItemService settlementOrderItemService;

    @Autowired
    WithdrawalOrderItemService withdrawalOrderItemService;

    @Autowired
    WorkerSettlementService workerSettlementService;

    @Autowired
    WorkerOrderService workerOrderService;

    @Autowired
    WechatLogic wechatLogic;

    public IPage<SettlementOrderLogicVO> pageV2(ZfireParamBean zfireParamBean) {
        AdminUserCom adminUser = commonLogic.getAdminUser();
        List<String> companyWechatIds = adminUser.getCompanyWechatIds();
        List<String> websitIds = adminUser.getAdminWebsitIds();

        //1.组装查询条件
        ZfireParamBean zfireParam = FieldUtils.supplyParam(zfireParamBean, SettlementOrderLogicVO.class, adminUser);
        IPage<SettlementOrderLogicVO> settlementOrderLogicVOIPage = websitSalesRetCMapper.pageSettletV2(new Page(zfireParamBean.getPageNum(),
                        zfireParamBean.getPageSize()),
                zfireParam
                , companyWechatIds);

        return settlementOrderLogicVOIPage;
    }

    public SettlementOrderDetail detail(String id) {

        SettlementOrder settlementOrder = settlementOrderService.getById(id);

        SettlementOrderDetail settlementOrderDetail = BeanUtil.toBean(settlementOrder, SettlementOrderDetail.class);

        settlementOrderDetail.setSettlementOrderItemList(settlementOrderItemService.lambdaQuery().eq(SettlementOrderItem::getSettlementOrderId, id).list());
        return settlementOrderDetail;
    }

    @Transactional(rollbackFor = Exception.class)
    public void refund(String id) {


        SettlementOrder settlementOrder = settlementOrderService.getById(id);

        if (settlementOrder.getStatus().equals(SettlementStatusEnum.WAIT.getKey()) || settlementOrder.getStatus().equals(SettlementStatusEnum.WAIT_ING.getKey())) {
            settlementOrder.setStatus(SettlementStatusEnum.REFUND.getKey());
            settlementOrder.updateById();
        }

        if (settlementOrder.getRefundStatus().equals(IsYesNoEnum.YES.getKey()))
            throw new RemoteServiceException("订单已退");

        settlementOrder.setRefundStatus(IsYesNoEnum.YES.getKey());
        settlementOrder.updateById();

        WorkerOrder workerOrder = workerOrderService.getById(settlementOrder.getOrderId());

        workerOrder.setRefundStatus(IsYesNoEnum.YES.getKey());
        workerOrder.updateById();

        List<SettlementOrderItem> list = settlementOrderItemService.lambdaQuery().eq(SettlementOrderItem::getSettlementOrderId, id).list();
        settlementOrder.setSettlementOrderId("TK" + settlementOrder.getSettlementOrderId());
        settlementOrder.setTotalAmount(settlementOrder.getTotalAmount().multiply(Convert.toBigDecimal("-1")));
        settlementOrder.setWebsitAmount(settlementOrder.getWebsitAmount().multiply(Convert.toBigDecimal("-1")));
        settlementOrder.setWorkerAmount(settlementOrder.getWorkerAmount().multiply(Convert.toBigDecimal("-1")));
        settlementOrder.setStatus(SettlementStatusEnum.WAIT_ING.getKey());
        for (SettlementOrderItem settlementOrderItem : list) {
            settlementOrderItem.setId("T" + settlementOrderItem.getId());
            settlementOrderItem.setSettlementOrderId(settlementOrder.getSettlementOrderId());
            settlementOrderItem.setTotalAmount(settlementOrderItem.getGoodsAmount().multiply(Convert.toBigDecimal("-1")));
            settlementOrderItem.setWorkerAmount(settlementOrderItem.getWorkerAmount().multiply(Convert.toBigDecimal("-1")));
            settlementOrderItem.setWebsitAmount(settlementOrderItem.getWebsitAmount().multiply(Convert.toBigDecimal("-1")));
        }
        settlementOrder.insert();
        settlementOrderItemService.saveBatch(list);
    }

    @Transactional(rollbackFor = Exception.class)
    public void settlement(List<String> id) throws WxPayException {
        if (settlementOrderService.lambdaQuery()
                .in(SettlementOrder::getSettlementOrderId, id)
                .notIn(SettlementOrder::getStatus, SettlementStatusEnum.WAIT.getKey())
                .count() > 0) {
            throw new RemoteServiceException("存在非待结算得结算");
        }



        List<SettlementOrder> settlementOrders = settlementOrderService.lambdaQuery().in(SettlementOrder::getSettlementOrderId, id).list();


        for (SettlementOrder settlementOrder : settlementOrders) {
            if (!settlementOrder.getPayType().equals("LINE"))
             wechatLogic.shareSettlementAmount(settlementOrder);
        }



    }

    @Transactional(rollbackFor = Exception.class)
    public void over(List<String> id) {
        if (settlementOrderService.lambdaQuery()
                .in(SettlementOrder::getSettlementOrderId, id)
                .notIn(SettlementOrder::getStatus, SettlementStatusEnum.WAIT.getKey(), SettlementStatusEnum.WAIT_ING.getKey())
                .count() > 0) {
            throw new RemoteServiceException("存在正在提现，或已提现得结算");
        }
        List<SettlementOrder> settlementOrders = settlementOrderService.lambdaQuery()
                .in(SettlementOrder::getSettlementOrderId, id)
                .list();

        List<String> websitIds = settlementOrders.stream().map(SettlementOrder::getWebsitId).distinct().collect(Collectors.toList());
        List<String> workerIds = settlementOrders.stream().map(SettlementOrder::getWorkerId).distinct().collect(Collectors.toList());

        for (String workerId : workerIds) {
            //for (String websitId : websitIds) {
                List<SettlementOrder> settlementOrdersList = settlementOrderService.lambdaQuery()
                        .eq(SettlementOrder::getWorkerId, workerId)
                        //.eq(SettlementOrder::getWebsitId, websitId)
                        .in(SettlementOrder::getSettlementOrderId, id)
                        .list();

                if (CollectionUtils.isEmpty(settlementOrdersList))
                    continue;

                settlementOrderService.lambdaUpdate()
                        .eq(SettlementOrder::getWorkerId, workerId)
                        //.eq(SettlementOrder::getWebsitId, websitId)
                        .in(SettlementOrder::getSettlementOrderId, id)
                        .set(SettlementOrder::getStatus, SettlementStatusEnum.OVER.getKey())
                        .set(SettlementOrder::getSettlementTime, new Date())
                        .update();


                this.addWithdrawal(settlementOrdersList);
           // }
        }
    }

    private void addWithdrawal(List<SettlementOrder> settlementOrdersList) {
        AdminUserCom adminUser = commonLogic.getAdminUser();

        WithdrawalOrder withdrawalOrder = new WithdrawalOrder();
        withdrawalOrder.setId(IdWorker.getIdStr());
        withdrawalOrder.setStatus(1);
        withdrawalOrder.setCompanyWechatId(settlementOrdersList.get(0).getCompanyWechatId());
        withdrawalOrder.setCompanyWechatName(settlementOrdersList.get(0).getCompanyWechatName());
//        withdrawalOrder.setWebsitId(settlementOrdersList.get(0).getWebsitId());
//        withdrawalOrder.setWebsitName(settlementOrdersList.get(0).getWebsitName());
        withdrawalOrder.setWorkerId(settlementOrdersList.get(0).getWorkerId());
        withdrawalOrder.setWorkerName(settlementOrdersList.get(0).getWorkerName());
        withdrawalOrder.setWorkerMobile(settlementOrdersList.get(0).getWorkerMobile());
        withdrawalOrder.setType(1);
        withdrawalOrder.setIdcard(settlementOrdersList.get(0).getIdentity());
        withdrawalOrder.setGrantBy(adminUser.getNickName());
        withdrawalOrder.setGrantTime(new Date());

        BigDecimal amount = new BigDecimal("0");

        List<WithdrawalOrderItem> withdrawalOrderItems = new ArrayList<>();

        for (SettlementOrder settlementOrder : settlementOrdersList) {
            amount = amount.add(settlementOrder.getWorkerAmount());
            WithdrawalOrderItem withdrawalOrderItem = new WithdrawalOrderItem();
            withdrawalOrderItem.setWithdrawalOrderId(withdrawalOrder.getId());
            withdrawalOrderItem.setOrderId(settlementOrder.getSettlementOrderId());
            withdrawalOrderItem.setGoodsType(settlementOrder.getGoodsType());
            withdrawalOrderItem.setNum(settlementOrder.getNum());
            withdrawalOrderItem.setTotalPrice(settlementOrder.getTotalAmount());
            withdrawalOrderItem.setSettlementType(settlementOrder.getSettlementType());
            withdrawalOrderItem.setWorkerAmount(settlementOrder.getWorkerAmount());
            withdrawalOrderItem.setWebsitAmount(settlementOrder.getWebsitAmount());
//            withdrawalOrderItem.setWebsitId(settlementOrder.getWebsitId());
//            withdrawalOrderItem.setWebsitName(settlementOrder.getWebsitName());
            withdrawalOrderItem.setWorkerId(settlementOrder.getWorkerId());
            withdrawalOrderItem.setWorkerMobile(settlementOrder.getWorkerMobile());
            withdrawalOrderItem.setWorkerName(settlementOrder.getWorkerName());
            withdrawalOrderItems.add(withdrawalOrderItem);
        }

        if (CollectionUtils.isEmpty(withdrawalOrderItems))
            return;

        withdrawalOrder.setAmount(amount);
        withdrawalOrder.insert();

        withdrawalOrderItemService.saveBatch(withdrawalOrderItems);

    }

    public IPage<WorkerSettlementVO> workerSettlementPageV2(ZfireParamBean zfireParamBean) {

        AdminUserCom adminUser = commonLogic.getAdminUser();
        List<String> companyWechatIds = adminUser.getCompanyWechatIds();

        //1.组装查询条件
        ZfireParamBean zfireParam = FieldUtils.supplyParam(zfireParamBean, WorkerSettlementVO.class,adminUser);
        IPage<WorkerSettlementVO> settlementOrderLogicVOIPage = websitSalesRetCMapper.workerSettlementPageV2(new Page(zfireParamBean.getPageNum(),
                        zfireParamBean.getPageSize()),
                zfireParam);

        return settlementOrderLogicVOIPage;
    }

    public void lineSettlement(List<String> id) {
        if (settlementOrderService.lambdaQuery()
                .in(SettlementOrder::getSettlementOrderId, id)
                .eq(SettlementOrder::getPayType, SettlementPayTypeEnum.LINE.getKey())
                .notIn(SettlementOrder::getStatus, SettlementStatusEnum.WAIT.getKey())
                .count() > 0) {
            throw new RemoteServiceException("存在非待结算得结算");
        }
        List<SettlementOrder> list = settlementOrderService.lambdaQuery()
                .in(SettlementOrder::getSettlementOrderId, id)
                .eq(SettlementOrder::getStatus, SettlementStatusEnum.WAIT.getKey())
                .eq(SettlementOrder::getPayType, SettlementPayTypeEnum.LINE.getKey())
                .list();

        for (SettlementOrder settlementOrder : list) {
            WorkerSettlement one = workerSettlementService.lambdaQuery().eq(WorkerSettlement::getWorkerId, settlementOrder.getWorkerId())
                    .eq(WorkerSettlement::getPayType, SettlementPayTypeEnum.LINE.getKey())
                    .eq(WorkerSettlement::getType, "OTHER")
                    .last("limit 1").one();
            one.setGiveAmount(one.getGiveAmount().add(settlementOrder.getWorkerAmount()));

            one.updateById();
        }

        settlementOrderService.lambdaUpdate()
                .in(SettlementOrder::getSettlementOrderId, id)
                .eq(SettlementOrder::getStatus, SettlementStatusEnum.WAIT.getKey())
                .set(SettlementOrder::getStatus, SettlementStatusEnum.OVER.getKey()).update();
    }

    public IPage<WorkerSettlementLineVO> pageLineSettlementV2(ZfireParamBean zfireParamBean) {
        AdminUserCom adminUser = commonLogic.getAdminUser();
        List<String> companyWechatIds = adminUser.getCompanyWechatIds();

        //1.组装查询条件
        ZfireParamBean zfireParam = FieldUtils.supplyParam(zfireParamBean, WorkerSettlementLineVO.class,adminUser);
        IPage<WorkerSettlementLineVO> settlementOrderLogicVOIPage = websitSalesRetCMapper.pageLineSettlementV2(new Page(zfireParamBean.getPageNum(),
                        zfireParamBean.getPageSize()),
                zfireParam);

        return settlementOrderLogicVOIPage;
    }

    public void lineSettlementOrder(List<String> id) {

        if (settlementOrderService.lambdaQuery()
                .in(SettlementOrder::getSettlementOrderId, id)
                .notIn(SettlementOrder::getStatus, SettlementStatusNewEnum.YC.getKey())
                .count() > 0) {
            throw new RemoteServiceException("存在非异常结算得结算单");
        }

        settlementOrderService.lambdaUpdate()
                .in(SettlementOrder::getSettlementOrderId, id)
                .eq(SettlementOrder::getStatus, SettlementStatusNewEnum.YC.getKey())
                .set(SettlementOrder::getStatus, SettlementStatusNewEnum.LINE.getKey()).update();
    }
}
