package com.gree.mall.miniapp.logic.workorder;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.convert.Convert;
import cn.hutool.core.date.DateUtil;
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.gree.mall.miniapp.bean.PayDetail;
import com.gree.mall.miniapp.bean.user.CurrentCompanyWechat;
import com.gree.mall.miniapp.bean.workorder.IncreCountVO;
import com.gree.mall.miniapp.bean.workorder.PgIncreOrderVO;
import com.gree.mall.miniapp.bean.workorder.PgIncreVO;
import com.gree.mall.miniapp.enums.OrderInfoSourceEnum;
import com.gree.mall.miniapp.enums.PayStatusEnum;
import com.gree.mall.miniapp.exception.RemoteServiceException;
import com.gree.mall.miniapp.logic.common.CommonLogic;
import com.gree.mall.miniapp.logic.common.outside.WechatLogic;
import com.gree.mall.miniapp.plus.entity.*;
import com.gree.mall.miniapp.plus.service.*;
import com.gree.mall.miniapp.utils.ApplicationContextUtils;
import com.gree.mall.miniapp.utils.CommonUtils;
import com.gree.mall.miniapp.utils.IpUtil;
import com.gree.mall.miniapp.utils.StringUtil;
import lombok.RequiredArgsConstructor;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.servlet.http.HttpServletRequest;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

@RequiredArgsConstructor
@Service
public class IncreConfigLogic {

    @Autowired
    PgIncreService pgIncreService;

    @Autowired
    PgIncreItemService pgIncreItemService;

    @Autowired
    CommonLogic commonLogic;

    @Autowired
    PgIncreOrderService pgIncreOrderService;

    @Autowired
    WechatLogic wechatLogic;

    @Autowired
    GoodsCategoryService goodsCategoryService;

    @Autowired
    BrandService brandService;

    public IPage<PgIncre> list(Integer pageNum, Integer pageSize) {
        CurrentCompanyWechat currentCompanyWechat = commonLogic.getCurrentCompanyWechat();
        Page<PgIncre> page = pgIncreService.lambdaQuery()
                .eq(PgIncre::getStatus,true)
                .eq(PgIncre::getCompanyWechatId,currentCompanyWechat.getCompanyWechatId())
                .page(new Page<>(pageNum, pageSize));

        return page;
    }

    public PgIncreVO detail(String id) {
        PgIncre pgIncre = pgIncreService.getById(id);

        PgIncreVO pgIncreVO = BeanUtil.toBean(pgIncre, PgIncreVO.class);

        List<PgIncreItem> list = pgIncreItemService.lambdaQuery()
                .eq(PgIncreItem::getIncreId, id).list();
        pgIncreVO.setPgIncreItems(list);
        return pgIncreVO;
    }

    public String buy(PgIncreOrderVO pgIncreOrderVO, String ip, HttpServletRequest request) {
        CurrentCompanyWechat currentCompanyWechat = commonLogic.getCurrentCompanyWechat();
        PgIncreItem pgIncreItem = pgIncreItemService.getById(pgIncreOrderVO.getPgIncreItemId());

        pgIncreOrderVO.setCompanyWechatId(currentCompanyWechat.getCompanyWechatId());
        pgIncreOrderVO.setCompanyWechatName(currentCompanyWechat.getCompanyName());
        pgIncreOrderVO.setWorkerId(currentCompanyWechat.getUserId());
        pgIncreOrderVO.setWorkerName(currentCompanyWechat.getUser().getNickName());
        pgIncreOrderVO.setWorkerIdcard(currentCompanyWechat.getUser().getIdCard());
        pgIncreOrderVO.setWorkerMobile(currentCompanyWechat.getUser().getMobile());

        pgIncreOrderVO.setAmount(pgIncreItem.getAmount());
        pgIncreOrderVO.setIncreContent(pgIncreItem.getContent());
        pgIncreOrderVO.setLimitNum(pgIncreItem.getLimitNum());
        pgIncreOrderVO.setResiduNum(pgIncreItem.getLimitNum());
        pgIncreOrderVO.setWorkerOpenId(currentCompanyWechat.getUser().getOpenId());



        GoodsCategory goodsCategory = goodsCategoryService.getById(pgIncreOrderVO.getMainId());


        pgIncreOrderVO.setMainImg(goodsCategory.getImgUrl());

        BigDecimal websitProceAmount = pgIncreItem.getWebsitAmount().multiply(Convert.toBigDecimal("0.006"));
        BigDecimal workerProceAmount = pgIncreItem.getWorkerAmount().multiply(Convert.toBigDecimal("0.006"));

        if (websitProceAmount.doubleValue() > 0.01) {
            websitProceAmount = websitProceAmount.setScale(2, BigDecimal.ROUND_HALF_UP);
        }else {
            websitProceAmount = Convert.toBigDecimal("0.01");
        }

        if (workerProceAmount.doubleValue() > 0.01) {
            workerProceAmount = workerProceAmount.setScale(2, BigDecimal.ROUND_HALF_UP);
        }else {
            workerProceAmount = Convert.toBigDecimal("0.01");
        }


        pgIncreOrderVO.setWorkerAmount(pgIncreItem.getWorkerAmount().subtract(workerProceAmount));

        pgIncreOrderVO.setWebsitAmount(pgIncreItem.getWebsitAmount().subtract(websitProceAmount));

        if (pgIncreOrderVO.getWorkerAmount().doubleValue() < 0)
            pgIncreOrderVO.setWorkerAmount(Convert.toBigDecimal("0"));

        if (pgIncreOrderVO.getWebsitAmount().doubleValue() < 0)
            pgIncreOrderVO.setWebsitAmount(Convert.toBigDecimal("0"));

        pgIncreOrderVO.setCommissionAmount(websitProceAmount.add(workerProceAmount));

        if (pgIncreOrderVO.getCommissionAmount().doubleValue() > pgIncreOrderVO.getAmount().doubleValue())
            pgIncreOrderVO.setCommissionAmount(pgIncreOrderVO.getAmount());

        pgIncreOrderVO.setId("YB"+IdWorker.getIdStr());
        pgIncreOrderVO.setServiceNo(pgIncreOrderVO.getId());
        pgIncreOrderVO.setInvoiceTime(pgIncreOrderVO.getInsureTime());
        pgIncreOrderVO.insert();

        return pgIncreOrderVO.getId();
    }

    public List<PgIncreItem> getIncreItem(String brand, String mainName) {

        CurrentCompanyWechat currentCompanyWechat = commonLogic.getCurrentCompanyWechat();
        List<PgIncre> list = pgIncreService.lambdaQuery()
                .eq(PgIncre::getStatus, true)
                .eq(PgIncre::getCompanyWechatId, currentCompanyWechat.getCompanyWechatId()).list();

        List<String> collect = list.stream().map(PgIncre::getId).collect(Collectors.toList());

        List<PgIncreItem> pgIncreItems = pgIncreItemService.lambdaQuery().in(PgIncreItem::getIncreId, collect)
                .eq(!StringUtil.isEmpty(brand),PgIncreItem::getBrandName, brand)
                .eq(!StringUtil.isEmpty(mainName),PgIncreItem::getMainName, mainName)
                .list();

        return pgIncreItems;
    }

    public PgIncreOrder getOrder(String id) {

        return pgIncreOrderService.getById(id);
    }

    public void cancel(String id) {
        if (pgIncreOrderService.lambdaQuery().eq(PgIncreOrder::getOrderChannel,"SELF").eq(PgIncreOrder::getId,id).count() > 0){
            throw new RemoteServiceException("线下订单，小程序不允许操作");
        }
        pgIncreOrderService.lambdaUpdate().eq(PgIncreOrder::getId,id)

                .set(PgIncreOrder::getPayStatus,"CANCEL").update();
    }

    public Boolean paid(String id, String authCode, String ip) {

        if (pgIncreOrderService.lambdaQuery().eq(PgIncreOrder::getOrderChannel,"SELF").eq(PgIncreOrder::getId,id).count() > 0){
            throw new RemoteServiceException("线下订单，小程序不允许操作");
        }

        CurrentCompanyWechat currentCompanyWechat = commonLogic.getCurrentCompanyWechat();
        PgIncreOrder pgIncreOrder = pgIncreOrderService.getById(id);

        if (!pgIncreOrder.getPayStatus().equals(PayStatusEnum.WAIT.getKey())) {
            throw new RemoteServiceException(id + "订单号非待支付");
        }
        pgIncreOrder.setSource(commonLogic.getSource().equals(OrderInfoSourceEnum.A)?OrderInfoSourceEnum.A.getRemark():OrderInfoSourceEnum.B.getRemark() );

        String transcationId = wechatLogic.paymentFkm(pgIncreOrder.getId(), pgIncreOrder.getAmount(), authCode, "Y", ip,
                currentCompanyWechat.getCompanyWechatId(),pgIncreOrder.getSource());
        pgIncreOrder.setTranscationId(transcationId);
        if (pgIncreOrder.getIncreType().equals(1)){
            pgIncreOrder.setServiceEndTime(DateUtil.offsetMonth(pgIncreOrder.getInsureTime(),pgIncreOrder.getLimitNum()*12));
        }
        pgIncreOrder.setPayTime(new Date());
        pgIncreOrder.setPayStatus(PayStatusEnum.PAID.getKey());
        pgIncreOrder.setPayNo(id);

        pgIncreOrder.setSettleStatus("ING");
        pgIncreOrder.setWorkerOpenId(currentCompanyWechat.getUser().getOpenId());
        pgIncreOrder.updateById();

        return true;
    }

    public PayDetail pay(String id, String ip,Boolean miniPay,String openId) {

        if (pgIncreOrderService.lambdaQuery().eq(PgIncreOrder::getOrderChannel,"SELF").eq(PgIncreOrder::getId,id).count() > 0){
            throw new RemoteServiceException("线下订单，小程序不允许操作");
        }

        CurrentCompanyWechat wechat = commonLogic.getCurrentCompanyWechat();
        PgIncreOrder pgIncreOrder = pgIncreOrderService.getById(id);

        if (Objects.isNull(pgIncreOrder)) {
            throw new RemoteServiceException(id + "订单号不存在，无法发起支付");
        }

        if (!pgIncreOrder.getPayStatus().equals(PayStatusEnum.WAIT.getKey())) {
            throw new RemoteServiceException(id + "订单号非待支付");
        }

        if ( miniPay != null && miniPay) {
            pgIncreOrder
                    .setSource( OrderInfoSourceEnum.A.getRemark())
                    .updateById();
        }else {
            pgIncreOrder
                    .setSource( OrderInfoSourceEnum.B.getRemark())
                    .updateById();
        }


        return wechatLogic.payment(id, pgIncreOrder.getAmount(), miniPay != null && miniPay?openId:wechat.getUser().getOpenId(), "Y", ip, wechat.getCompanyWechatId(),miniPay);

    }

    public IPage<PgIncreOrder> listIncre(String code,List<String> payStatus, Integer pageNum, Integer pageSize) {
        CurrentCompanyWechat currentCompanyWechat = commonLogic.getCurrentCompanyWechat();
        Page<PgIncreOrder> page = pgIncreOrderService.lambdaQuery()
                .in(!CollectionUtils.isEmpty(payStatus),PgIncreOrder::getPayStatus,payStatus)
                .eq(!StringUtil.isEmpty(code),PgIncreOrder::getInsideCode,code)
                .and(item -> item.eq(PgIncreOrder::getWorkerId,currentCompanyWechat.getUser().getUserId()).or()
                .eq(PgIncreOrder::getUserMobile,currentCompanyWechat.getUser().getMobile()))
                .eq(PgIncreOrder::getCompanyWechatId,currentCompanyWechat.getCompanyWechatId())

                .and(item -> item.eq(PgIncreOrder::getOrderChannel,"SELF").in(PgIncreOrder::getPayStatus,"PAID","REFUND","EXPIRE").or().eq(PgIncreOrder::getOrderChannel,"ONLINE"))

                .orderByDesc(PgIncreOrder::getCreateTime)
                .page(new Page<>(pageNum, pageSize));

        return page;

    }

    public PgIncreOrder detailIncre(String id) {

        return pgIncreOrderService.getById(id);
    }

    public IncreCountVO listIncreCount() {
        IncreCountVO increCountVO = new IncreCountVO();

        CurrentCompanyWechat currentCompanyWechat = commonLogic.getCurrentCompanyWechat();
        Integer qb = pgIncreOrderService.lambdaQuery()
                .and(item -> item.eq(PgIncreOrder::getWorkerId, currentCompanyWechat.getUser().getUserId()).or()
                        .eq(PgIncreOrder::getUserMobile, currentCompanyWechat.getUser().getMobile()))
                .and(item -> item.eq(PgIncreOrder::getOrderChannel,"SELF").eq(PgIncreOrder::getPayStatus,"PAID").or().eq(PgIncreOrder::getOrderChannel,"ONLINE"))
                .eq(PgIncreOrder::getCompanyWechatId, currentCompanyWechat.getCompanyWechatId()).count();

        Integer dzf = pgIncreOrderService.lambdaQuery()
                .in(PgIncreOrder::getPayStatus,PayStatusEnum.WAIT.getKey())
                .and(item -> item.eq(PgIncreOrder::getWorkerId, currentCompanyWechat.getUser().getUserId()).or()
                        .eq(PgIncreOrder::getUserMobile, currentCompanyWechat.getUser().getMobile()))
                .and(item -> item.eq(PgIncreOrder::getOrderChannel,"SELF").eq(PgIncreOrder::getPayStatus,"PAID").or().eq(PgIncreOrder::getOrderChannel,"ONLINE"))

                .eq(PgIncreOrder::getCompanyWechatId, currentCompanyWechat.getCompanyWechatId()).count();


        Integer yzf = pgIncreOrderService.lambdaQuery()
                .in(PgIncreOrder::getPayStatus,PayStatusEnum.PAID.getKey())
                .and(item -> item.eq(PgIncreOrder::getWorkerId, currentCompanyWechat.getUser().getUserId()).or()
                        .eq(PgIncreOrder::getUserMobile, currentCompanyWechat.getUser().getMobile()))
                .eq(PgIncreOrder::getCompanyWechatId, currentCompanyWechat.getCompanyWechatId()).count();

        Integer gqqx = pgIncreOrderService.lambdaQuery()
                .in(PgIncreOrder::getPayStatus,PayStatusEnum.CANCEL.getKey(),PayStatusEnum.EXPIRE.getKey())
                .and(item -> item.eq(PgIncreOrder::getWorkerId, currentCompanyWechat.getUser().getUserId()).or()
                        .eq(PgIncreOrder::getUserMobile, currentCompanyWechat.getUser().getMobile()))
                .and(item -> item.eq(PgIncreOrder::getOrderChannel,"SELF").in(PgIncreOrder::getPayStatus,"PAID","EXPIRE").or().eq(PgIncreOrder::getOrderChannel,"ONLINE"))
                .eq(PgIncreOrder::getCompanyWechatId, currentCompanyWechat.getCompanyWechatId()).count();

        Integer tk = pgIncreOrderService.lambdaQuery()
                .in(PgIncreOrder::getPayStatus,PayStatusEnum.REFUND.getKey())
                .and(item -> item.eq(PgIncreOrder::getWorkerId, currentCompanyWechat.getUser().getUserId()).or()
                        .eq(PgIncreOrder::getUserMobile, currentCompanyWechat.getUser().getMobile()))
                .and(item -> item.eq(PgIncreOrder::getOrderChannel,"SELF").in(PgIncreOrder::getPayStatus,"PAID","REFUND").or().eq(PgIncreOrder::getOrderChannel,"ONLINE"))
                .eq(PgIncreOrder::getCompanyWechatId, currentCompanyWechat.getCompanyWechatId()).count();

        increCountVO.setQb(qb);
        increCountVO.setDzf(dzf);
        increCountVO.setYzf(yzf);
        increCountVO.setGqqx(gqqx);
        increCountVO.setTk(tk);
        return increCountVO;

    }


    public List<GoodsCategory> getCategoryList(String brandName) {

        CurrentCompanyWechat currentCompanyWechat = commonLogic.getCurrentCompanyWechat();
        List<PgIncre> list = pgIncreService.lambdaQuery()
                .select(PgIncre::getId)
                .eq(PgIncre::getStatus, true)
                .eq(PgIncre::getCompanyWechatId, currentCompanyWechat.getCompanyWechatId()).list();

        List<String> collect = list.stream().map(PgIncre::getId).collect(Collectors.toList());

        if (CollectionUtils.isEmpty(collect))
            return new ArrayList<>();

        List<PgIncreItem> pgIncreItems = pgIncreItemService.lambdaQuery()
                .select(PgIncreItem::getMainId)
                .in(PgIncreItem::getIncreId, collect)
                .eq(!StringUtil.isEmpty(brandName),PgIncreItem::getBrandName, brandName)
                .list();
        List<String> collectCategoty = pgIncreItems.stream().map(PgIncreItem::getMainId).collect(Collectors.toList());

        if (CollectionUtils.isEmpty(collectCategoty))
            return new ArrayList<>();

        return goodsCategoryService.lambdaQuery()
                .in(GoodsCategory::getCategoryId,collectCategoty)
                .eq(GoodsCategory::getType,2)
                .eq(GoodsCategory::getDel,0)
                .eq(GoodsCategory::getLevel, 1)
                .in(GoodsCategory::getCompanyWechatId,currentCompanyWechat.getCompanyWechatId())
                .orderByAsc(GoodsCategory::getSortNum)
                .list();
    }

    public List<Brand> getBrand() {

        CurrentCompanyWechat currentCompanyWechat = commonLogic.getCurrentCompanyWechat();

        List<PgIncre> list = pgIncreService.lambdaQuery()
                .select(PgIncre::getId)
                .eq(PgIncre::getStatus, true)
                .eq(PgIncre::getCompanyWechatId, currentCompanyWechat.getCompanyWechatId()).list();

        List<String> collect = list.stream().map(PgIncre::getId).collect(Collectors.toList());

        if (CollectionUtils.isEmpty(collect))
            return new ArrayList<>();

        List<PgIncreItem> pgIncreItems = pgIncreItemService.lambdaQuery()
                .select(PgIncreItem::getBrandId)
                .in(PgIncreItem::getIncreId, collect)
                .list();
        List<String> collectCategoty = pgIncreItems.stream().map(PgIncreItem::getBrandId).collect(Collectors.toList());

        if (CollectionUtils.isEmpty(collectCategoty))
            return new ArrayList<>();

        return brandService.lambdaQuery()
                .eq(Brand::getStatus,1)
                .in(Brand::getId,collectCategoty)
                .eq(Brand::getCompanyWechatId,currentCompanyWechat.getCompanyWechatId()).orderByAsc(Brand::getSortNum).list();
    }

    public IPage<PgIncreOrder> listIncreCode(String code, List<String> payStatus, Integer pageNum, Integer pageSize) {
        CurrentCompanyWechat currentCompanyWechat = commonLogic.getCurrentCompanyWechat();
        Page<PgIncreOrder> page = pgIncreOrderService.lambdaQuery()
                .in(!CollectionUtils.isEmpty(payStatus),PgIncreOrder::getPayStatus,payStatus)
                .eq(!StringUtil.isEmpty(code),PgIncreOrder::getInsideCode,code)
                .eq(PgIncreOrder::getCompanyWechatId,currentCompanyWechat.getCompanyWechatId())
                .orderByDesc(PgIncreOrder::getCreateTime)
                .page(new Page<>(pageNum, pageSize));

        return page;
    }

    public void tax(String orderId, String orderTaxId) {
        pgIncreOrderService.lambdaUpdate()
                .set(PgIncreOrder::getTax, true)
                .set(PgIncreOrder::getOrderTaxId, orderTaxId)
                .eq(PgIncreOrder::getId, orderId).update();
    }
}
