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

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.NumberUtil;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.gree.mall.miniapp.bean.es.ESGoodsBean;
import com.gree.mall.miniapp.bean.es.ESGoodsOtherCountBean;
import com.gree.mall.miniapp.bean.es.EsGoodsMessageBean;
import com.gree.mall.miniapp.bean.es.GuessBean;
import com.gree.mall.miniapp.bean.user.CurrentCompanyWechat;
import com.gree.mall.miniapp.commonmapper.CommonMapper;
import com.gree.mall.miniapp.enums.PayTypeEnum;
import com.gree.mall.miniapp.enums.UserTypeEnum;
import com.gree.mall.miniapp.enums.base.BaseEnum;
import com.gree.mall.miniapp.enums.es.ESGoodsStatusEnum;
import com.gree.mall.miniapp.exception.RemoteServiceException;
import com.gree.mall.miniapp.logic.common.CommonLogic;
import com.gree.mall.miniapp.plus.entity.*;
import com.gree.mall.miniapp.plus.service.*;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import javax.servlet.http.HttpServletRequest;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;

@Service
@Slf4j
@RequiredArgsConstructor
public class ESGoodsLogic {

    private final CommonLogic commonLogic;
    private final CommonMapper commonMapper;
    private final EsGoodsService esGoodsService;
    private final EsGoodsImgService esGoodsImgService;
    private final EsGoodsMessageService esGoodsMessageService;
    private final EsGoodsMessageReplyService esGoodsMessageReplyService;
    private final EsGoodsPraiseService esGoodsPraiseService;
    private final UserService userService;
    private final EsOrderInfoService esOrderInfoService;
    private final CarouselMapService carouselMapService;

    public IPage<ESGoodsBean> list(Integer pageNum, Integer pageSize, String sortType, String goodsName, String categoryId,
                                   String userId, String brand, String power, String mark, List<String> status) {
        final CurrentCompanyWechat wechat = commonLogic.getCurrentCompanyWechat();
        IPage<ESGoodsBean> list = commonMapper.esGoodsList(new Page<>(pageNum, pageSize),
                wechat.getUser().getCompanyWechatId(), sortType, goodsName, categoryId, userId, brand,
                power, mark, status);
        if (CollectionUtil.isNotEmpty(list.getRecords())) {
            this.addImgList(list.getRecords());
            this.addMessageList(list.getRecords());
            this.queryIsPraise(list.getRecords(), wechat);
            this.queryOrderInfo(list.getRecords(), wechat);
        }
        return list;
    }

    private void queryOrderInfo(List<ESGoodsBean> records, CurrentCompanyWechat wechat) {
        List<String> collect = records.stream().filter(item -> item.getStatus().equals(ESGoodsStatusEnum.SALE.getKey())).map(ESGoodsBean::getId).collect(Collectors.toList());
        if (CollectionUtils.isEmpty(collect))
            return;

        List<EsOrderInfo> esOrderInfos = esOrderInfoService.lambdaQuery()
                .in(EsOrderInfo::getEsGoodsId, collect)
                .eq(EsOrderInfo::getPayStatus, "PAID")
                .list();


        for (ESGoodsBean record : records) {
            List<EsOrderInfo> esOrderInfoList = esOrderInfos.stream().filter(item -> item.getEsGoodsId().equals(record.getId())).collect(Collectors.toList());

            if (CollectionUtils.isEmpty(esOrderInfoList))
                continue;
            record.setEsOrderInfo(esOrderInfoList.get(0));
        }

    }

    private void queryIsPraise(List<ESGoodsBean> records, CurrentCompanyWechat wechat) {
        for (ESGoodsBean record : records) {
            final Integer count = esGoodsPraiseService.lambdaQuery()
                    .eq(EsGoodsPraise::getEsGoodsId, record.getId())
                    .eq(EsGoodsPraise::getUserId, wechat.getUser().getUserId())
                    .count();
            record.setIsPraise(count > 0);
        }
    }

    private void addImgList(List<ESGoodsBean> records) {
        for (ESGoodsBean record : records) {
            final List<EsGoodsImg> imgList = esGoodsImgService.lambdaQuery()
                    .eq(EsGoodsImg::getEsGoodsId, record.getId())
                    .list();
            record.setImgList(imgList);
        }
    }

    private void addMessageList(List<ESGoodsBean> records) {
        for (ESGoodsBean record : records) {
            final List<EsGoodsMessage> messages = esGoodsMessageService.lambdaQuery()
                    .eq(EsGoodsMessage::getEsGoodsId, record.getId())
                    .orderByDesc(EsGoodsMessage::getCreateTime)
                    .list();
            List<EsGoodsMessageBean> messageBeanList = BeanUtil.copyToList(messages, EsGoodsMessageBean.class);
            record.setMessageAndReplyList(messageBeanList);
            record.setMessageCount(messages.size());
        }
    }

    public List<ESGoodsBean> topList() {
        final CurrentCompanyWechat wechat = commonLogic.getCurrentCompanyWechat();
        List<ESGoodsBean> list = commonMapper.esGoodsTopList(wechat.getUser().getCompanyWechatId());
        if (CollectionUtil.isNotEmpty(list)) {
            this.addImgList(list);
            this.addMessageList(list);
            this.queryIsPraise(list, wechat);
        }
        return list;
    }

    public GuessBean guessList() {
        final CurrentCompanyWechat wechat = commonLogic.getCurrentCompanyWechat();
        GuessBean bean = new GuessBean();
        List<String> brandList = commonMapper.guessList(wechat.getUser().getCompanyWechatId(), "brand");
        List<String> powerList = commonMapper.guessList(wechat.getUser().getCompanyWechatId(), "power");
        List<String> markList = commonMapper.guessList(wechat.getUser().getCompanyWechatId(), "mark");
        bean.setBrandList(brandList);
        bean.setPowerList(powerList);
        bean.setMarkList(markList);
        return bean;
    }

    public ESGoodsBean detail(String id) {
        final CurrentCompanyWechat wechat = commonLogic.getCurrentCompanyWechat();
        ESGoodsBean bean = new ESGoodsBean();
        final EsGoods goods = esGoodsService.getById(id);
        BeanUtils.copyProperties(goods, bean);
        final List<EsGoodsImg> imgList = esGoodsImgService.lambdaQuery()
                .eq(EsGoodsImg::getEsGoodsId, id)
                .list();
        bean.setImgList(imgList);

        // 获取留言与回复
        this.addMessageList(new ArrayList<ESGoodsBean>() {{ this.add(bean); }});

        if (CollectionUtil.isNotEmpty(bean.getMessageAndReplyList())) {
            List<EsGoodsMessageReply> replyList = esGoodsMessageReplyService.lambdaQuery()
                    .eq(EsGoodsMessageReply::getEsGoodsId, id)
                    .in(EsGoodsMessageReply::getEsGoodsMessageId, bean.getMessageAndReplyList().stream()
                            .map(EsGoodsMessage::getId)
                            .collect(Collectors.toList()))
                    .list();
            Map<String, List<EsGoodsMessageReply>> groupMap = replyList.stream().collect(Collectors.groupingBy(EsGoodsMessageReply::getEsGoodsMessageId));

            for (EsGoodsMessageBean messageBean : bean.getMessageAndReplyList()) {
                if (groupMap.containsKey(messageBean.getId())) {
                    messageBean.setMessageReplyList(groupMap.get(messageBean.getId()));
                }
            }
        }

        // 是否点赞
        final Integer count = esGoodsPraiseService.lambdaQuery()
                .eq(EsGoodsPraise::getEsGoodsId, id)
                .eq(EsGoodsPraise::getUserId, wechat.getUser().getUserId())
                .count();
        bean.setIsPraise(count > 0);

        // 随机加访问数量
        int addNum;

        if (goods.getStatus().equals(ESGoodsStatusEnum.SALE.getKey()) || goods.getQueryCount() < 1000) {
            addNum = 1;
        } else {
            addNum = NumberUtil.generateRandomNumber(1, 9, 1)[0];
        }

        esGoodsService.lambdaUpdate()
                .set(EsGoods::getQueryCount, goods.getQueryCount() + addNum)
                .eq(EsGoods::getId, id)
                .update();



        List<EsOrderInfo> esOrderInfos = esOrderInfoService.lambdaQuery()
                .in(EsOrderInfo::getEsGoodsId, goods.getId())
                .notIn(EsOrderInfo::getStatus, "SAVE", "TIME_OUT").list();


        List<EsOrderInfo> esOrderInfoLists = esOrderInfoService.lambdaQuery()
                .in(EsOrderInfo::getEsGoodsId, goods.getId())
                .eq(EsOrderInfo::getPayType, PayTypeEnum.CASH.getKey())
                .eq(EsOrderInfo::getStatus, "SAVE").list();

        List<EsOrderInfo> esOrderInfoListRefund = esOrderInfoService.lambdaQuery()
                .in(EsOrderInfo::getEsGoodsId, goods.getId())
                .eq(EsOrderInfo::getPayStatus, "PAID")
                .eq(EsOrderInfo::getStatus, "CANCEL").list();

        esOrderInfos.addAll(esOrderInfoLists);
        esOrderInfos.addAll(esOrderInfoListRefund);


        List<EsOrderInfo> esOrderInfoList = esOrderInfos.stream().filter(item -> item.getEsGoodsId().equals(goods.getId())).collect(Collectors.toList());
        if (!CollectionUtils.isEmpty(esOrderInfoList)){
            bean.setEsOrderInfo(esOrderInfoList.get(0));
        }



        return bean;
    }

    public void add(HttpServletRequest request, ESGoodsBean bean) {
        final CurrentCompanyWechat wechat = commonLogic.getCurrentCompanyWechat();
        final User user = userService.getById(wechat.getUser().getUserId());
        if (!user.getIsEs()) {
            throw new RemoteServiceException("师傅没有二手商品权限");
        }
        if (StringUtils.isBlank(bean.getGoodsName())) {
            throw new RemoteServiceException("商品名称不能为空");
        }

        if (StringUtils.isBlank(bean.getGoodsNote())) {
            throw new RemoteServiceException("商品描述不能为空");
        }

        if (StringUtils.isBlank(bean.getCategoryId()) || StringUtils.isBlank(bean.getCategoryName())) {
            throw new RemoteServiceException("商品分类不能为空");
        }

        if (Objects.isNull(bean.getPrice())) {
            throw new RemoteServiceException("商品价格不能为空");
        }

        if (Objects.isNull(bean.getQty()) || bean.getQty() <= 0) {
            throw new RemoteServiceException("上架数量不能为空");
        }

        if (CollectionUtil.isEmpty(bean.getImgList())) {
            throw new RemoteServiceException("商品图片不能为空");
        }

        EsGoods goods = new EsGoods();
        BeanUtils.copyProperties(bean, goods);

        goods.setCompanyWechatId(wechat.getCompanyWechatId())
                .setCompanyWechatName(wechat.getCurrentCompanyName())
                .setUserId(wechat.getUserId())
                .setUserNickName(wechat.getUser().getNickName())
                .setStatus(ESGoodsStatusEnum.ON.getKey())
                .setLinkPhone(wechat.getUser().getMobile())
                .setUserHeadImg(wechat.getUser().getAvatar())
                .setId(null)
                .insert();

        for (EsGoodsImg img : bean.getImgList()) {
            img.setEsGoodsId(goods.getId());
        }

        esGoodsImgService.saveBatch(bean.getImgList());
    }

    public ESGoodsBean praise(String id, Boolean isPraise) {
        final CurrentCompanyWechat wechat = commonLogic.getCurrentCompanyWechat();
        final EsGoods goods = esGoodsService.getById(id);
        if (Objects.isNull(goods)) {
            throw new RemoteServiceException("商品信息不存在");
        }
        ESGoodsBean bean = new ESGoodsBean();
        BeanUtil.copyProperties(goods, bean);
        if (isPraise) {
            int addNum =  NumberUtil.generateRandomNumber(1, 9, 1)[0];
            EsGoodsPraise praise = new EsGoodsPraise();
            praise.setEsGoodsId(id)
                    .setUserId(wechat.getUser().getUserId())
                    .insert();
            esGoodsService.lambdaUpdate()
                    .set(EsGoods::getLikeCount, goods.getLikeCount() + addNum)
                    .eq(EsGoods::getId, id)
                    .update();

            bean.setLikeCount(goods.getLikeCount() + addNum);
            bean.setIsPraise(true);
        } else {
            bean.setIsPraise(false);
            if (goods.getLikeCount() <= 0) {
                bean.setLikeCount(0);
                return bean;
            }
            esGoodsService.lambdaUpdate()
                    .set(EsGoods::getLikeCount, goods.getLikeCount() - 1)
                    .eq(EsGoods::getId, id)
                    .update();
            esGoodsPraiseService.lambdaUpdate()
                    .eq(EsGoodsPraise::getEsGoodsId, id)
                    .eq(EsGoodsPraise::getUserId, wechat.getUser().getUserId())
                    .remove();

            bean.setLikeCount(goods.getLikeCount() - 1);
        }
        return bean;
    }

    public void message(String id, String messageId, String content) {
        final CurrentCompanyWechat wechat = commonLogic.getCurrentCompanyWechat();

        final User user = userService.getById(wechat.getUser().getUserId());
        boolean isReply = StringUtils.isNoneBlank(messageId);

        if (isReply) {
            // 回复
            if (user.getType().equals(UserTypeEnum.WORKER.getKey())
                    && !user.getIsEs()) {
                throw new RemoteServiceException("师傅没有二手商品权限");
            }

            EsGoodsMessageReply reply = new EsGoodsMessageReply();
            reply.setEsGoodsId(id)
                    .setEsGoodsMessageId(messageId)
                    .setContent(content)
                    .setReplyBy(wechat.getUser().getNickName())
                    .setReplyTime(DateUtil.date())
                    .setUserHeadImg(wechat.getUser().getAvatar())
                    .insert();
        } else {
            // 留言
            EsGoodsMessage message = new EsGoodsMessage();
            message.setEsGoodsId(id)
                    .setContent(content)
                    .setUserHeadImg(wechat.getUser().getAvatar())
                    .setUserNickName(wechat.getUser().getNickName())
                    .insert();
        }
    }

    @Transactional
    public void updateStatus(String id, ESGoodsStatusEnum status) {
        final CurrentCompanyWechat wechat = commonLogic.getCurrentCompanyWechat();
        final User user = userService.getById(wechat.getUser().getUserId());
        if (!user.getIsEs()) {
            throw new RemoteServiceException("师傅没有二手商品权限");
        }
        final EsGoods goods = esGoodsService.getById(id);
        if (status.getKey().equals(ESGoodsStatusEnum.ON.getKey())
                && goods.getStatus().equals(ESGoodsStatusEnum.SALE.getKey())) {
            throw new RemoteServiceException("二手商品已售出不能重新上架");
        }

        EsGoodsOperateRecord record = new EsGoodsOperateRecord();
        record.setEsGoodsId(goods.getId())
                .setOperateType("更改状态")
                .setContent("小程序端变更 " + status.getRemark())
                .insert();

        esGoodsService.lambdaUpdate()
                .set(EsGoods::getStatus, status.getKey())
                .set(EsGoods::getUpdateBy, wechat.getUser().getNickName())
                .set(EsGoods::getUpdateTime, DateUtil.date())
                .eq(EsGoods::getId, id)
                .update();

        if (status.getKey().equals(ESGoodsStatusEnum.SALE.getKey())
                || status.getKey().equals(ESGoodsStatusEnum.OFF.getKey())) {
            carouselMapService.lambdaUpdate()
                    .set(CarouselMap::getState, false)
                    .eq(CarouselMap::getCompanyWechatId, user.getCompanyWechatId())
                    .eq(CarouselMap::getPort, "ESHOP")
                    .eq(CarouselMap::getGoodsId, goods.getId())
                    .update();
        }
    }

    public ESGoodsOtherCountBean otherCount(String id) {
        ESGoodsOtherCountBean bean = new ESGoodsOtherCountBean();
        final EsGoods goods = esGoodsService.getById(id);
        bean.setQueryCount(goods.getQueryCount());
        bean.setPraiseCount(goods.getLikeCount());
        final Integer count = esGoodsMessageService.lambdaQuery()
                .eq(EsGoodsMessage::getEsGoodsId, id)
                .count();
        bean.setMessageCount(count);
        return bean;
    }

    public void update(HttpServletRequest request, ESGoodsBean bean) {
        final CurrentCompanyWechat wechat = commonLogic.getCurrentCompanyWechat();
        final User user = userService.getById(wechat.getUser().getUserId());
        if (!user.getIsEs()) {
            throw new RemoteServiceException("师傅没有二手商品权限");
        }
        if (StringUtils.isBlank(bean.getGoodsName())) {
            throw new RemoteServiceException("商品名称不能为空");
        }

        if (StringUtils.isBlank(bean.getGoodsNote())) {
            throw new RemoteServiceException("商品描述不能为空");
        }

        if (StringUtils.isBlank(bean.getCategoryId()) || StringUtils.isBlank(bean.getCategoryName())) {
            throw new RemoteServiceException("商品分类不能为空");
        }

        if (Objects.isNull(bean.getPrice())) {
            throw new RemoteServiceException("商品价格不能为空");
        }

        if (Objects.isNull(bean.getQty()) || bean.getQty() <= 0) {
            throw new RemoteServiceException("上架数量不能为空");
        }

        if (CollectionUtil.isEmpty(bean.getImgList())) {
            throw new RemoteServiceException("商品图片不能为空");
        }

        EsGoods oldGoods = esGoodsService.getById(bean.getId());

        this.compareByParams(bean, oldGoods);

        EsGoods goods = new EsGoods();
        BeanUtils.copyProperties(bean, goods);

        goods.updateById();

        for (EsGoodsImg img : bean.getImgList()) {
            img.setEsGoodsId(goods.getId());
        }

        esGoodsImgService.lambdaUpdate()
                .eq(EsGoodsImg::getEsGoodsId, goods.getId())
                .remove();
        esGoodsImgService.saveBatch(bean.getImgList());
    }

    public String copy(String id) {
        final CurrentCompanyWechat wechat = commonLogic.getCurrentCompanyWechat();
        final User user = userService.getById(wechat.getUser().getUserId());
        if (!user.getIsEs()) {
            throw new RemoteServiceException("师傅没有二手商品权限");
        }
        final EsGoods oldGoods = esGoodsService.getById(id);
        EsGoods goods = new EsGoods();
        BeanUtils.copyProperties(oldGoods, goods);
        goods.setId(null)
                .setStatus(ESGoodsStatusEnum.ON.getKey())
                .setIsTop(false)
                .setTopTime(null)
                .setLikeCount(0)
                .setQueryCount(0)
                .setTopTime(null)
                .insert();

        final List<EsGoodsImg> imgList = esGoodsImgService.lambdaQuery()
                .eq(EsGoodsImg::getEsGoodsId, id)
                .list();

        for (EsGoodsImg img : imgList) {
            img.setId(null)
                    .setEsGoodsId(goods.getId());
        }
        // 创建人改为原商品创建人
        esGoodsService.lambdaUpdate()
                .set(EsGoods::getCreateBy, oldGoods.getCreateBy())
                .eq(EsGoods::getId, goods.getId())
                .update();
        esGoodsImgService.saveBatch(imgList);
        return goods.getId();
    }

    public void del(String id) {
        final EsGoods goods = esGoodsService.getById(id);
        if (!goods.getStatus().equals(ESGoodsStatusEnum.OFF.getKey())) {
            throw new RemoteServiceException("商品非”下架“状态，删除失败");
        }
        goods.deleteById();
    }

    private void compareByParams(ESGoodsBean bean, EsGoods oldGoods) {
        StringBuilder sb = new StringBuilder();

        if (ObjectUtil.notEqual(bean.getCategoryId(), oldGoods.getCategoryId())) {
            sb.append("原商品分类: ")
                    .append(bean.getCategoryName())
                    .append(" 变更为: ")
                    .append(oldGoods.getCategoryName())
                    .append(", ");

            oldGoods.setCategoryId(bean.getCategoryId())
                    .setCategoryName(bean.getCategoryName());
        }

        if (ObjectUtil.notEqual(bean.getStatus(), oldGoods.getStatus())) {
            sb.append("发布状态: ")
                    .append(BaseEnum.keyToEnumNotNull(ESGoodsStatusEnum.class, oldGoods.getStatus()).getRemark())
                    .append(" 变更为: ")
                    .append(BaseEnum.keyToEnumNotNull(ESGoodsStatusEnum.class, bean.getStatus()).getRemark())
                    .append(", ");

            oldGoods.setStatus(bean.getStatus());
        }

        if (ObjectUtil.notEqual(bean.getGoodsName(), oldGoods.getGoodsName())) {
            sb.append("商品名称: ")
                    .append(oldGoods.getGoodsName())
                    .append(" 变更为: ")
                    .append(bean.getGoodsName())
                    .append(", ");

            oldGoods.setGoodsName(bean.getGoodsName());
        }

        if (ObjectUtil.notEqual(bean.getGoodsNote(), oldGoods.getGoodsNote())) {
            sb.append("商品描述: ")
                    .append(oldGoods.getGoodsNote())
                    .append(" 变更为: ")
                    .append(bean.getGoodsNote())
                    .append(", ");

            oldGoods.setGoodsNote(bean.getGoodsNote());
        }

        if (ObjectUtil.notEqual(bean.getPrice(), oldGoods.getPrice())) {
            sb.append("商品价格: ")
                    .append(oldGoods.getPrice())
                    .append(" 变更为: ")
                    .append(bean.getPrice())
                    .append(", ");

            oldGoods.setPrice(bean.getPrice());
        }

        if (ObjectUtil.notEqual(bean.getQty(), oldGoods.getQty())) {
            sb.append("上架数量: ")
                    .append(oldGoods.getQty())
                    .append(" 变更为: ")
                    .append(bean.getQty())
                    .append(", ");

            oldGoods.setQty(bean.getQty());
        }

        if (ObjectUtil.notEqual(bean.getBrand(), oldGoods.getBrand())) {
            sb.append("商品品牌: ")
                    .append(oldGoods.getBrand())
                    .append(" 变更为: ")
                    .append(bean.getBrand())
                    .append(", ");

            oldGoods.setBrand(bean.getBrand());
        }

        if (ObjectUtil.notEqual(bean.getPower(), oldGoods.getPower())) {
            sb.append("功率: ")
                    .append(oldGoods.getPower())
                    .append(" 变更为: ")
                    .append(bean.getPower())
                    .append(", ");

            oldGoods.setPower(bean.getPower());
        }

        if (ObjectUtil.notEqual(bean.getMakeDate(), oldGoods.getMakeDate())) {
            sb.append("制造日期: ")
                    .append(oldGoods.getMakeDate())
                    .append(" 变更为: ")
                    .append(bean.getMakeDate())
                    .append(", ");

            oldGoods.setMakeDate(bean.getMakeDate());
        }

        if (ObjectUtil.notEqual(bean.getLinkPhone(), oldGoods.getLinkPhone())) {
            sb.append("联系电话: ")
                    .append(oldGoods.getLinkPhone())
                    .append(" 变更为: ")
                    .append(bean.getLinkPhone())
                    .append(", ");

            oldGoods.setLinkPhone(bean.getLinkPhone());
        }

        if (ObjectUtil.notEqual(bean.getMark(), oldGoods.getMark())) {
            sb.append("能效标识: ")
                    .append(oldGoods.getMark())
                    .append(" 变更为: ")
                    .append(bean.getMark())
                    .append(", ");

            oldGoods.setMark(bean.getMark());
        }

        if (sb.length() > 0) {
            String updStr = sb.deleteCharAt(sb.lastIndexOf(", ")).toString();
            EsGoodsOperateRecord operatorLog = new EsGoodsOperateRecord();
            operatorLog.setEsGoodsId(oldGoods.getId())
                    .setOperateType("变更内容")
                    .setContent("小程序端变更 " + updStr)
                    .insert();
        }

    }
}
