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

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.date.DateUtil;
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.manager.bean.admin.AdminUserCom;
import com.gree.mall.manager.bean.es.ESGoodsBean;
import com.gree.mall.manager.bean.es.ESGoodsVO;
import com.gree.mall.manager.bean.es.EsGoodsMessageVO;
import com.gree.mall.manager.commonmapper.CommonMapper;
import com.gree.mall.manager.enums.base.BaseEnum;
import com.gree.mall.manager.enums.es.CarouselMapPortEnum;
import com.gree.mall.manager.enums.es.ESGoodsStatusEnum;
import com.gree.mall.manager.exception.RemoteServiceException;
import com.gree.mall.manager.logic.common.CommonLogic;
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 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 java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.function.Function;
import java.util.stream.Collectors;

@Slf4j
@Service
@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 EsGoodsOperateRecordService esGoodsOperateRecordService;
    private final EsOrderInfoService esOrderInfoService;
    private final CarouselMapService carouselMapService;


    public IPage<ESGoodsVO> list(ZfireParamBean zfireParamBean) {
        AdminUserCom adminUser = commonLogic.getAdminUser();
        FieldUtils.supplyParam(zfireParamBean, ESGoodsVO.class, adminUser);
        IPage<ESGoodsVO> page = commonMapper.esGoodsList(new Page(zfireParamBean.getPageNum(), zfireParamBean.getPageSize()), zfireParamBean);
        if (CollectionUtil.isNotEmpty(page.getRecords())) {
            final List<EsGoodsImg> goodsImgs = esGoodsImgService.lambdaQuery()
                    .in(EsGoodsImg::getEsGoodsId, page.getRecords().stream()
                            .map(ESGoodsVO::getId)
                            .collect(Collectors.toList()))
                    .groupBy(EsGoodsImg::getEsGoodsId)
                    .list();
            final Map<String, EsGoodsImg> goodsImgMap = goodsImgs.stream()
                    .collect(Collectors.toMap(EsGoodsImg::getEsGoodsId, Function.identity()));

            for (ESGoodsVO record : page.getRecords()) {
                final EsGoodsImg img = goodsImgMap.get(record.getId());
                if (Objects.isNull(img)) {
                    continue;
                }
                record.setImgUrl(img.getImgUrl());
            }
        }
        return page;
    }

    public ESGoodsBean detail(String id) {
        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);
        List<EsGoodsMessageVO> messageList = commonMapper.esGoodsMessageList(id);
        bean.setMessageList(messageList);
        final List<EsGoodsOperateRecord> recordList = esGoodsOperateRecordService.lambdaQuery()
                .eq(EsGoodsOperateRecord::getEsGoodsId, id)
                .list();
        bean.setOperateRecordList(recordList);

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


        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;
    }

    @Transactional
    public void update(ESGoodsBean bean) {
        AdminUserCom adminUser = commonLogic.getAdminUser();
        EsGoods oldGoods = esGoodsService.getById(bean.getId());
        if (Objects.isNull(oldGoods)) {
            throw new RemoteServiceException("商品不存在");
        }
        if (oldGoods.getStatus().equals(ESGoodsStatusEnum.SALE.getKey())) {
            throw new RemoteServiceException("已卖出商品不能再编辑");
        }
        this.compareByParams(bean, oldGoods);

        oldGoods.updateById();
    }

    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();
        }

    }

    @Transactional
    public void batchUpdateStatus(List<String> ids, ESGoodsStatusEnum status) {
        AdminUserCom adminUser = commonLogic.getAdminUser();
        if (CollectionUtil.isEmpty(ids)) {
            throw new RemoteServiceException("更新集合不能为空");
        }

        List<EsGoods> goodsList = esGoodsService.lambdaQuery()
                .in(EsGoods::getId, ids)
                .list();

        List<EsGoodsOperateRecord> recordList = new ArrayList<>();

        if (status.getKey().equals(ESGoodsStatusEnum.OFF.getKey())
                || status.getKey().equals(ESGoodsStatusEnum.ON.getKey())) {
            for (EsGoods goods : goodsList) {
                if (goods.getStatus().equals(ESGoodsStatusEnum.OFF.getKey()) || goods.getStatus().equals(ESGoodsStatusEnum.ON.getKey())) {
                    EsGoodsOperateRecord record = new EsGoodsOperateRecord();
                    record.setEsGoodsId(goods.getId())
                            .setOperateType("更改状态")
                            .setContent(status.getRemark());
                    recordList.add(record);
                }
            }
        }

//        if (status.getKey().equals(ESGoodsStatusEnum.SALE.getKey())) {
//            // TODO 生成新的线下销售单待填写
//        }

        if (CollectionUtil.isNotEmpty(recordList)) {
            esGoodsOperateRecordService.saveBatch(recordList);
        }

        esGoodsService.lambdaUpdate()
                .set(EsGoods::getStatus, status.getKey())
                .set(EsGoods::getUpdateBy, adminUser.getNickName())
                .set(EsGoods::getUpdateTime, DateUtil.date())
                .eq(EsGoods::getCompanyWechatId, adminUser.getAdminCompanyWechat().getCompanyWechatId())
                .in(EsGoods::getId, ids)
                .update();

        if (status.getKey().equals(ESGoodsStatusEnum.SALE.getKey())
                || status.getKey().equals(ESGoodsStatusEnum.OFF.getKey())) {
            carouselMapService.lambdaUpdate()
                    .set(CarouselMap::getState, false)
                    .eq(CarouselMap::getCompanyWechatId, adminUser.getAdminCompanyWechat().getCompanyWechatId())
                    .eq(CarouselMap::getPort, CarouselMapPortEnum.ESHOP.getKey())
                    .in(CarouselMap::getGoodsId, ids)
                    .update();
        }
    }

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

    @Transactional
    public String copy(String id) {
        EsGoods oldGoods = esGoodsService.getById(id);
        List<EsGoodsImg> imgList = esGoodsImgService.lambdaQuery()
                .eq(EsGoodsImg::getEsGoodsId, id)
                .list();
        EsGoods goods = new EsGoods();
        BeanUtils.copyProperties(oldGoods, goods);
        goods.setId(null)
                .setStatus(ESGoodsStatusEnum.ON.getKey())
                .setCreateBy(null)
                .setCreateTime(null)
                .setIsTop(false)
                .setTopTime(null)
                .setLikeCount(0)
                .setQueryCount(0)
                .setTopTime(null)
                .insert();
        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 reply(String id, String messageId, String content) {
        if (StringUtils.isBlank(content)) {
            throw new RemoteServiceException("回复内容不能为空");
        }
        AdminUserCom adminUser = commonLogic.getAdminUser();
        EsGoodsMessageReply reply = new EsGoodsMessageReply();
        reply.setEsGoodsId(id)
                .setEsGoodsMessageId(messageId)
                .setContent(content)
                .setReplyBy(adminUser.getNickName())
                .setReplyTime(DateUtil.date())
                .insert();
    }

    public void top(String id, Boolean isTop) {
        AdminUserCom adminUser = commonLogic.getAdminUser();
        esGoodsService.lambdaUpdate()
                .set(EsGoods::getIsTop, isTop)
                .set(EsGoods::getTopTime, isTop ? DateUtil.date() : null)
                .set(isTop, EsGoods::getSort, -999)
                .set(!isTop, EsGoods::getSort, 0)
                .set(EsGoods::getUpdateBy, adminUser.getNickName())
                .set(EsGoods::getUpdateTime, DateUtil.date())
                .eq(EsGoods::getId, id)
                .update();
    }

    public List<EsGoodsOperateRecord> operateList(String id) {
        final List<EsGoodsOperateRecord> records = esGoodsOperateRecordService.lambdaQuery()
                .eq(EsGoodsOperateRecord::getEsGoodsId, id)
                .list();
        return records;
    }
}
