package com.izouma.dingdong.service;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.izouma.dingdong.converter.LongArrayConverter;
import com.izouma.dingdong.domain.*;
import com.izouma.dingdong.domain.merchant.Goods;
import com.izouma.dingdong.domain.rider.Rider;
import com.izouma.dingdong.dto.ApDTO;
import com.izouma.dingdong.dto.AppraisalMerDTO;
import com.izouma.dingdong.dto.AppraisalRidDTO;
import com.izouma.dingdong.dto.ShowAppRidDTO;
import com.izouma.dingdong.enums.AppraisalSort;
import com.izouma.dingdong.enums.OrderStatus;
import com.izouma.dingdong.exception.BusinessException;
import com.izouma.dingdong.repo.*;

import com.izouma.dingdong.repo.merchant.MerchantRepo;
import com.izouma.dingdong.repo.rider.RiderRepo;
import com.izouma.dingdong.service.merchant.SalesService;
import lombok.AllArgsConstructor;
import org.springframework.stereotype.Service;

import javax.transaction.Transactional;
import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;

@Service
@AllArgsConstructor
public class AppraisalService {

    private AppraisalRepo      appraisalRepo;
    private OrderInfoRepo      orderInfoRepo;
    private OrderGoodsSpecRepo orderGoodsSpecRepo;
    private SalesService       salesService;
    private MerchantRepo       merchantRepo;
    private FastAppraisalRepo  fastAppraisalRepo;
    private RiderRepo          riderRepo;

    /*
    客户评价
     */
    @Transactional
    public Appraisal userAppraisal(Appraisal appraisal) {

        OrderInfo order = orderInfoRepo.findById(appraisal.getOrderInfoId()).orElseThrow(new BusinessException("无订单"));
        //OrderInfo order = appraisal.getOrder();
        if (OrderStatus.RATED.equals(order.getStatus())) {

            order.setRated(true);
            order.setStatus(OrderStatus.COMPLETED);
            orderInfoRepo.save(order);

            appraisal.setMerchantId(order.getMerchantId());
            appraisal.setRiderId(order.getRiderId());
            appraisal.setLikes(0);
            appraisal.setAppraiseTime(LocalDateTime.now());
            appraisal.setEnabled(true);

            appraisal = appraisalRepo.save(appraisal);
            //更新销量数据
            salesService.addLike(appraisal);
            return appraisal;
        } else if (OrderStatus.COMPLETED.equals(order.getStatus())) {
            throw new BusinessException("订单已评价");
        } else {
            throw new BusinessException("订单未完成");
        }
    }

    /*
    按商品查找评价
     */
    public List<AppraisalMerDTO> goodsAppraisals(Long goodsId) {
        List<OrderGoodsSpec> specs = orderGoodsSpecRepo.findAllByGoodsId(goodsId);
        if (ObjectUtil.isNull(specs)) {
            return null;
        }
        List<AppraisalMerDTO> appraisals = CollUtil.newArrayList();
        specs.forEach(s -> {
            Appraisal appraisal = appraisalRepo.findByOrderInfoId(s.getOrderInfoId())
                    .orElseThrow(new BusinessException("无订单"));
            if (ObjectUtil.isNotNull(appraisal)) {
                appraisals.add(this.toMerDTO(appraisal));
            }
        });
        return appraisals;
    }

    /**
     * 转商家显示dto
     *
     * @param appraisal 评价
     * @return 商家需要信息的评价dto
     */
    public AppraisalMerDTO toMerDTO(Appraisal appraisal) {
        OrderInfo order = orderInfoRepo.findById(appraisal.getOrderInfoId()).orElseThrow(new BusinessException("无订单"));
        List<Goods> collect = order.getOrderGoodsSpecs()
                .stream()
                .map(OrderGoodsSpec::getGoods)
                .collect(Collectors.toList());
        String goodsName = collect.stream().map(Goods::getName).collect(Collectors.joining(","));
        User user = order.getUser();

        AppraisalMerDTO dto = new AppraisalMerDTO();
        BeanUtil.copyProperties(appraisal, dto);

        dto.setAvatar(user.getAvatar());
        dto.setGoodsName(goodsName);
        dto.setNickname(user.getNickname());
        return dto;
    }

    /**
     * 商户评价排序
     *
     * @param merchantId    商户id
     * @param appraisalSort 评价规则
     * @return 商户所有评价
     */
    public List<Appraisal> appraisalsSort(Long merchantId, AppraisalSort appraisalSort) {
        List<Appraisal> appraisals = appraisalRepo.findAllByMerchantId(merchantId);
        //默认时间排序
        appraisals.sort((a, b) -> b.getAppraiseTime().compareTo(a.getAppraiseTime()));

        List<Appraisal> good = appraisals.stream().filter(Appraisal::getGoodsLike).collect(Collectors.toList());
        List<Appraisal> bad = appraisals.stream().filter(a -> !a.getGoodsLike()).collect(Collectors.toList());

        List<Appraisal> appraisals1 = new ArrayList<>();
        switch (appraisalSort) {
            //最新
            case LATEST:
                appraisals1.addAll(appraisals.stream().filter(
                        a -> !a.getAppraiseTime().isBefore(LocalDateTime.now().plusMonths(1)))
                        .collect(Collectors.toList()));
                break;
            //好评
            case PRAISE:
                appraisals1.addAll(good);
                appraisals1.addAll(bad);
                break;
            //差评
            case BAD_REVIEW:
                appraisals1.addAll(bad);
                appraisals1.addAll(good);
                break;
            //有图
            case HAVE_PIC:
                List<Appraisal> pic = appraisals.stream().filter(a -> StrUtil.isNotBlank(a.getImg()))
                        .collect(Collectors.toList());
                List<Appraisal> noPic = appraisals.stream().filter(a -> StrUtil.isBlank(a.getImg()))
                        .collect(Collectors.toList());
                appraisals1.addAll(pic);
                appraisals1.addAll(noPic);
                break;
            default:
                appraisals1.addAll(appraisals);
        }
        return appraisals1;
    }

    /*
    骑手端，自己评价的展示
     */
    public List<AppraisalRidDTO> showRider(Long riderId) {
        List<Appraisal> appraisals = appraisalRepo.findAllByRiderId(riderId);
        return appraisals.stream().map(this::toRidDTO).collect(Collectors.toList());
    }

    /*
    转骑手评价dto
     */
    public AppraisalRidDTO toRidDTO(Appraisal a) {
        AppraisalRidDTO ridDTO = AppraisalRidDTO
                .builder()
                .id(a.getId())
                .riderLike(a.getRiderLike())
                .userNickname("匿名")
                .riderAppraise(a.getRiderAppraise())
                .date(a.getAppraiseTime().toLocalDate())
                .build();

        //商家用户名
        merchantRepo.findById(a.getMerchantId())
                .ifPresent(m -> ridDTO.setMerShowName(m.getShowName()));

        if (ObjectUtil.isNotEmpty(a.getFastIds())) {
            List<String> content = new ArrayList<>();
            LongArrayConverter converter = new LongArrayConverter();
            List<Long> longs = converter.convertToEntityAttribute(a.getFastIds());
            longs.forEach(l ->
                    //快捷内容
                    fastAppraisalRepo.findById(l).ifPresent(f -> content.add(f.getContent()))
            );
            ridDTO.setContent(content);
        }
        return ridDTO;
    }

    /*
    用户端骑手的展示
     */
    public ShowAppRidDTO showAppRid(Long riderId) {
        //查处所有骑手评价
        List<Appraisal> appraisals = appraisalRepo.findAllByRiderId(riderId);
        //查找骑手信息
        Rider rider = riderRepo.findById(riderId).orElseThrow(new BusinessException("无骑手"));
        User user = rider.getUser();

        Integer awesome = appraisalRepo.countByRiderIdAndRiderLikeIs(riderId, 1);
        Integer bad = appraisalRepo.countByRiderIdAndRiderLikeIs(riderId, 2);
        Integer general = appraisalRepo.countByRiderIdAndRiderLikeIs(riderId, 3);

        LongArrayConverter converter = new LongArrayConverter();

        Map<Long, Integer> map = new HashMap<>();

        //取出所有快捷标签
        appraisals.forEach(a -> {
            if (ObjectUtil.isNotEmpty(a.getFastIds())) {
                List<Long> longs = converter.convertToEntityAttribute(a.getFastIds());
                longs.forEach(l ->
                        map.merge(l, 1, Integer::sum)
                );
            }
        });

        List<Map.Entry<Long, Integer>> list = new ArrayList<>(map.entrySet());
//        list.sort(Comparator.comparing(Map.Entry<Long, Integer>::getValue));
        list.sort((a, b) -> b.getValue().compareTo(a.getValue()));

        if (list.size() > 6) {
            list = list.subList(0, 6);
        }
        //转换为内容
        List<String> content = new ArrayList<>(map.size());
        list.forEach(m ->
                fastAppraisalRepo.findById(m.getKey()).ifPresent(f -> content.add(f.getContent() + " " + m.getValue()))
        );

        return ShowAppRidDTO.builder()
                .awesome(awesome)
                .bad(bad)
                .general(general)
                .avatar(user.getAvatar())
                .nickname(user.getNickname())
                .content(content)
                .build();
    }


    /*
    管理后台评价的展示DTO
     */
    public ApDTO toDTO(Appraisal appraisal) {
        ApDTO dto = new ApDTO();
        BeanUtil.copyProperties(appraisal, dto);
        BeanUtil.copyProperties(this.toMerDTO(appraisal),dto);
        BeanUtil.copyProperties(this.toRidDTO(appraisal),dto);
        //查找骑手信息
        Rider rider = riderRepo.findById(appraisal.getRiderId()).orElseThrow(new BusinessException("无骑手"));
        User user = rider.getUser();
        dto.setRiderName(user.getNickname());
        return dto;
    }
}
