package com.izouma.dingdong.service.merchant;

import cn.hutool.core.util.ObjectUtil;
import com.izouma.dingdong.config.Constants;
import com.izouma.dingdong.converter.LongArrayConverter;
import com.izouma.dingdong.converter.StringArrayConverter;
import com.izouma.dingdong.domain.OrderGoodsSpec;
import com.izouma.dingdong.domain.backstage.Email;
import com.izouma.dingdong.domain.merchant.*;
import com.izouma.dingdong.domain.user.ShoppingCart;
import com.izouma.dingdong.dto.AppraisalMerDTO;
import com.izouma.dingdong.dto.MerchantDTO;
import com.izouma.dingdong.enums.ApplyStatus;
import com.izouma.dingdong.enums.GoodType;
import com.izouma.dingdong.exception.BusinessException;
import com.izouma.dingdong.repo.OrderGoodsSpecRepo;
import com.izouma.dingdong.repo.backstage.EmailRepo;
import com.izouma.dingdong.repo.merchant.*;
import com.izouma.dingdong.repo.user.ShoppingCartRepo;
import com.izouma.dingdong.service.AppraisalService;
import com.izouma.dingdong.service.user.ShoppingCartService;
import com.izouma.dingdong.utils.ObjUtils;
import lombok.AllArgsConstructor;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;


@Service
@AllArgsConstructor
public class GoodsService {

    private GoodsRepo                     goodsRepo;
    private MerchantSettingsRepo          merchantSettingsRepo;
    private MerchantClassificationRepo    merchantClassificationRepo;
    private MerchantClassificationService merchantClassificationService;
    private EmailRepo                     emailRepo;
    private MerchantRepo                  merchantRepo;
    private AppraisalService              appraisalService;
    private GoodsSpecificationRepo        goodsSpecificationRepo;
    private MerchantService               merchantService;
    private ShoppingCartService           shoppingCartService;
    private OrderGoodsSpecRepo            orderGoodsSpecRepo;
    private ShoppingCartRepo              shoppingCartRepo;
//    private SalesRepo                     salesRepo;

    /**
     * 添加修改商品
     *
     * @param goods 商品
     * @return 商品
     */
    public Goods save(Goods goods) {
        if (ObjectUtil.isNull(goods.getMerchantId())) {
            throw new BusinessException("缺少商家");
        }
        MerchantSettings merchantSettings = merchantSettingsRepo.findByMerchantId(goods.getMerchantId())
                .orElseThrow(new BusinessException("商家不存在"));
        if (ObjectUtil.isNull(goods.getInventory()) || goods.getInventory() < 1) {
            throw new BusinessException("商品供应数量不足");
        }
        if (BigDecimal.ZERO.compareTo(goods.getAmount()) >= 0) {
            throw new BusinessException("价格不得小于等于0");
        }

        if (ObjectUtil.isNull(goods.getDiscountAmount())) {
            goods.setDiscountAmount(goods.getAmount());
        }

        if (BigDecimal.ZERO.compareTo(goods.getDiscountAmount()) >= 0) {
            throw new BusinessException("折扣价不得小于等于0");
        }

        int i = goods.getAmount().compareTo(goods.getDiscountAmount());
        if (i < 0) {
            throw new BusinessException("折扣价不得大于原价");
        }

        if (goods.getStartTime().isBefore(merchantSettings.getStartTime()) || goods.getEndTime()
                .isAfter(merchantSettings.getEndTime())) {
            throw new BusinessException("商品销售时间不得早于/晚于营业时间");
        }

        List<Goods> goodsList = goodsRepo.findAllByMerchantId(goods.getMerchantId());
        Set<Goods> signboard = goodsList.stream().filter(Goods::getSignboard).collect(Collectors.toSet());
        if (signboard.size() > 10) {
            throw new BusinessException("招牌商品大于10");
        } else {
            if (signboard.size() > goodsList.size() / 3) {
                throw new BusinessException("招牌商品大于所有商品1/3");
            }
        }

        if (containsWeek(goods.getWeek(), merchantSettings.getWeek())) {
            throw new BusinessException("商品销售日期不在营业日期内");
        }

        if (goods.getId() == null) {
            goods.setLikes(0);
            goods.setBad(0);
            goods.setTotalSales(0);
            goods.setTakeOff(false);
            goods.setSignboard(false);
            goods.setEnabled(true);
            //审核
//            goods.setIsPass(false);
            //优先级
            goods.setPriority(1);
            //好评
            goods.setPopularity(false);
            //人气
            goods.setPraise(false);
            goods.setStatus(ApplyStatus.PENDING);
        }

        MerchantClassification classification = merchantClassificationRepo.findByMerchantIdAndName(goods.getMerchantId(), Constants.CLASSIFICATION_NAME2);

        //折扣价不参与满减
        if (i == 0) {
            goods.setIsFullReduction(true);

            //移除折扣商品
            if (goods.getId() != null) {
                LongArrayConverter converter = new LongArrayConverter();
                String goodsIds = classification.getGoodsIds();
                List<Long> list = converter.convertToEntityAttribute(goodsIds);
                list.remove(goods.getId());
            }

        } else {
            goods.setIsFullReduction(false);
        }

        goods = goodsRepo.save(goods);

        if (i > 0) {
            //如果有折扣价，自动加入折扣分类
            //MerchantClassification classification = merchantClassificationRepo.findByMerchantIdAndName(goods.getMerchantId(), Constants.CLASSIFICATION_NAME2);
            if (!classification.getIsShow() || ObjectUtil.isNull(classification.getIsShow())) {
                classification.setIsShow(true);
                merchantClassificationRepo.save(classification);
            }
            merchantClassificationService.saveOneGoods(classification.getId(), goods.getId());
        }

        return goods;
    }


    /**
     * 购买时销量是否充足
     *
     * @param goodsId 商品ID
     * @param num     商品数量
     * @return 商品
     */
    public Goods buy(Long goodsId, Integer num) {
        Goods goods = goodsRepo.findById(goodsId).orElseThrow(new BusinessException("无商品"));

        //库存
        Integer inventory = goods.getInventory();
        if (inventory <= 0) {
            throw new BusinessException("已售馨");
        }
        if (inventory - num < 0) {
            throw new BusinessException("库存不足");
        }
        return goods;
    }


    /**
     * 商品上下架
     *
     * @param goodsId 商品ID
     */
    public void take(Long goodsId) {
        Goods goods = goodsRepo.findById(goodsId).orElseThrow(new BusinessException("无商品"));
        Boolean takeOff = goods.getTakeOff();
        if (takeOff) {
            goods.setTakeOff(false);
        } else {
            goods.setTakeOff(true);
        }
        goodsRepo.save(goods);
    }

    /**
     * 审核
     *
     * @param goodsId 商品ID
     * @param pass    是否通过
     */
    public Goods audit(Long goodsId, Boolean pass, String reason) {
        Goods goods = goodsRepo.findById(goodsId).orElseThrow(new BusinessException("无商品"));
        Long userId = merchantRepo.findUserIdById(goods.getMerchantId());

        Email email;

        if (pass) {
//            goods.setIsPass(true);
            goods.setStatus(ApplyStatus.PASS);
            //发送邮件
            email = Email.builder()
                    .sendTime(LocalDate.now())
                    .title("提交商品审核通过")
                    .content(goods.getName() + "：恭喜你所提交的商品已审核通过！")
                    .receiveUserId(userId)
                    .build();

        } else {
//            goods.setIsPass(false);
            goods.setStatus(ApplyStatus.DENY);
            //发送邮件
            email = Email.builder()
                    .sendTime(LocalDate.now())
                    .title("提交商品审核未通过")
                    .content(goods.getName() + "：" + reason)
                    .receiveUserId(userId)
                    .build();
        }
        emailRepo.save(email);
        return goodsRepo.save(goods);
    }


    /*
       周几
    */
    public Boolean containsWeek(String goodsWeek, String merWeek) {
        StringArrayConverter converter = new StringArrayConverter();
        List<String> merWeeks = converter.convertToEntityAttribute(merWeek);
        List<String> goodsWeeks = converter.convertToEntityAttribute(goodsWeek);

        for (String g : goodsWeeks) {
            if (!merWeeks.contains(g)) {
                return false;
            }
        }
        return true;
    }

    /*
    显示商品所有信息
     */
    public Map<String, Object> goodsAllInfo(Long goodsId) {
        HashMap<String, Object> map = new HashMap<>();
        Goods goods = goodsRepo.findById(goodsId).orElseThrow(new BusinessException("无记录"));
        map.put("goods", goods);

        List<AppraisalMerDTO> appraisals = appraisalService.goodsAppraisals(goodsId);
        map.put("appraisal", appraisals);

        List<GoodsSpecification> specifications = goodsSpecificationRepo.findAllByGoodsId(goodsId);
        map.put("specification", specifications);

        return map;
    }

    /*
    商品列表
     */
    public List<Goods> showAll(GoodType type, Double longitude, Double latitude, Double range) {

        //3km以内的商户
        Set<Merchant> merchantSet = new HashSet<>(merchantRepo.findAll());
        List<MerchantDTO> dtos = merchantService.withDistance(merchantSet, longitude, latitude, range);

        //用户3km以内的商品
        List<Goods> goodsList = new ArrayList<>();
        for (MerchantDTO d : dtos) {
            goodsList.addAll(goodsRepo.findAllByMerchantIdAndStatus(d.getMid(), ApplyStatus.PASS));
        }

        //过滤掉不是本日营业的商品
        String dayOfWeek = LocalDateTime.now().getDayOfWeek().toString();
        List<Goods> list = goodsList.stream()
                .filter(g -> g.getWeek().contains(dayOfWeek))
                .collect(Collectors.toList());

        List<Goods> all = new ArrayList<>();
        switch (type) {
            case PRAISE_FOOD://好评美食
                all.addAll(list.stream().filter(Goods::getPraise).collect(Collectors.toList()));
                break;
            case POPULAR_FOOD://人气美食
                all.addAll(list.stream().filter(Goods::getPopularity).collect(Collectors.toList()));
                break;
            case SIGNBOARD_FOOD://招牌美食
                all.addAll(list.stream().filter(Goods::getSignboard)
                        .sorted((a, b) -> b.getPriority().compareTo(a.getPriority())).collect(Collectors.toList()));
                break;
        }

        //排序
        all.sort((a, b) -> {
            //从大到小
//            int i = b.getPriority().compareTo(a.getPriority());
//            if (i == 0) {

            MerchantDTO dtoA = dtos.stream()
                    .filter(d -> d.getMid().equals(a.getMerchantId()))
                    .findFirst()
                    .orElseThrow(new BusinessException("无商家"));
            MerchantDTO dtoB = dtos.stream()
                    .filter(d -> d.getMid().equals(b.getMerchantId()))
                    .findFirst()
                    .orElseThrow(new BusinessException("无商家"));
            Integer monthSalesA = dtoA.getMonthSales();
            if (monthSalesA > 10000) {
                monthSalesA = 10000;
            }
            Integer monthSalesB = dtoB.getMonthSales();
            if (monthSalesB > 10000) {
                monthSalesB = 10000;
            }

            //(1000-距离)/1000*0.5 + 月销/10000*0.5 (月销大于10000按照10000计算)
            double scoreA = (1000.0 - dtoA.getDistance()) / 1000.0 * 0.5 + monthSalesA / 10000.0 * 0.5;
            double scoreB = (1000.0 - dtoB.getDistance()) / 1000.0 * 0.5 + monthSalesB / 10000.0 * 0.5;
            if (scoreB > scoreA) {
                return 1;
            } else if (scoreB == scoreA) {
                return 0;
            }
            return -1;
//            }
//            return i;
        });

        return all;
    }

    /*
    修改商品
     */
    public Goods change(Goods record) {
        Goods orig = goodsRepo.findById(record.getId()).orElseThrow(new BusinessException("无记录"));
        //如果修改商品名称和图片就重新审核
        if (record.getName() != null || record.getImg() != null) {
            record.setStatus(ApplyStatus.PENDING);
//            record.setIsPass(false);
        }
        ObjUtils.merge(orig, record);
        Goods save = this.save(orig);
        //如果修改价格，购物车内的商品就要重新计算
        if (record.getAmount() != null || record.getDiscountAmount() != null) {
            //所有包含此商品的订单规格
            List<OrderGoodsSpec> goodsSpec = orderGoodsSpecRepo.findAllByGoodsId(record.getId());

            Set<Long> cartId = new HashSet<>();
            goodsSpec.forEach(g -> {
                cartId.add(g.getShoppingCartId());
                if (ApplyStatus.PENDING.equals(save.getStatus())) {
                    //商品状态变为待审核，购物车里就删除
                    orderGoodsSpecRepo.deleteById(g.getId());
                }
            });
            cartId.forEach(c -> {
                //查找购物车
                ShoppingCart shoppingCart = shoppingCartRepo.findById(c).orElse(null);
                if (ObjectUtil.isNotNull(shoppingCart)) {
                    //改价格
                    shoppingCartService.calculatePrice(c, orig.getMerchantId());
                }
            });
        }

        //修改商品
        return save;
    }
}
