package com.ruoyi.web.modules.order.service.impl;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.web.modules.account.domain.BizMember;
import com.ruoyi.web.modules.account.facade.IMemberFacade;
import com.ruoyi.web.modules.order.constant.CheckoutConstants;
import com.ruoyi.web.modules.order.constant.OrderAppConstants;
import com.ruoyi.web.modules.order.constant.OrderConstants;
import com.ruoyi.web.modules.order.domain.BizGoodsReview;
import com.ruoyi.web.modules.order.domain.BizOrder;
import com.ruoyi.web.modules.order.domain.BizOrderItem;
import com.ruoyi.web.modules.order.dto.OrderAppListQueryDTO;
import com.ruoyi.web.modules.order.dto.OrderReviewSubmitDTO;
import com.ruoyi.web.modules.order.mapper.BizGoodsReviewMapper;
import com.ruoyi.web.modules.order.mapper.BizOrderItemMapper;
import com.ruoyi.web.modules.order.mapper.BizOrderMapper;
import com.ruoyi.web.modules.order.service.IOrderReviewAppService;
import com.ruoyi.web.modules.order.support.OrderAppSupport;
import com.ruoyi.web.modules.order.vo.OrderAppItemSummaryVO;
import com.ruoyi.web.modules.order.vo.OrderReviewDetailVO;
import com.ruoyi.web.modules.order.vo.OrderReviewListRowVO;

/**
 * C 端订单评价 Service 实现
 */
@Service
public class OrderReviewAppServiceImpl implements IOrderReviewAppService
{
    @Autowired
    private IMemberFacade memberFacade;

    @Autowired
    private BizOrderMapper orderMapper;

    @Autowired
    private BizOrderItemMapper orderItemMapper;

    @Autowired
    private BizGoodsReviewMapper reviewMapper;

    @Autowired
    private OrderAppSupport orderAppSupport;

    @Override
    public List<OrderReviewListRowVO> list(Long memberId, String tab)
    {
        assertMemberEnabled(memberId);
        String reviewTab = StringUtils.isEmpty(tab) ? OrderAppConstants.REVIEW_TAB_PENDING : tab;
        if (OrderAppConstants.REVIEW_TAB_DONE.equals(reviewTab))
        {
            return buildDoneRows(memberId);
        }
        OrderAppListQueryDTO query = new OrderAppListQueryDTO();
        query.setTab(OrderAppConstants.TAB_REVIEW_PENDING);
        List<BizOrder> orders = orderMapper.selectMemberAppList(memberId, query);
        return buildPendingRows(orders);
    }

    @Override
    public OrderReviewDetailVO getByOrder(Long memberId, Long orderId, Long orderItemId)
    {
        assertMemberEnabled(memberId);
        requireOrder(memberId, orderId);
        BizGoodsReview review = resolveReview(orderId, orderItemId);
        if (review == null)
        {
            throw new ServiceException("评价不存在");
        }
        OrderReviewDetailVO vo = new OrderReviewDetailVO();
        vo.setReviewId(review.getReviewId());
        vo.setOrderId(review.getOrderId());
        vo.setScore(review.getScore());
        vo.setContent(review.getContent());
        vo.setPics(orderAppSupport.splitPics(review.getReviewPics()));
        vo.setCreateTime(review.getCreateTime());
        vo.setReplyContent(review.getReplyContent());
        vo.setReplyTime(review.getReplyTime());
        return vo;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void submit(Long memberId, Long orderId, OrderReviewSubmitDTO dto)
    {
        assertMemberEnabled(memberId);
        BizOrder order = requireOrder(memberId, orderId);
        if (!OrderConstants.STATUS_COMPLETED.equals(order.getOrderStatus()))
        {
            throw new ServiceException(OrderAppConstants.MSG_REVIEW_NOT_COMPLETED);
        }
        if (dto == null || dto.getScore() == null || dto.getScore() < 1 || dto.getScore() > 5)
        {
            throw new ServiceException(OrderAppConstants.MSG_REVIEW_SCORE_REQUIRED);
        }
        List<BizOrderItem> items = orderItemMapper.selectByOrderId(orderId);
        if (items == null || items.isEmpty())
        {
            throw new ServiceException(OrderAppConstants.MSG_ORDER_ITEM_NOT_FOUND);
        }
        BizOrderItem targetItem = resolveTargetItem(items, dto.getOrderItemId());
        if (reviewMapper.selectByOrderItemId(targetItem.getItemId()) != null)
        {
            throw new ServiceException(OrderAppConstants.MSG_ALREADY_REVIEWED);
        }
        BizMember member = memberFacade.getMember(memberId);
        Date now = new Date();
        BizGoodsReview review = new BizGoodsReview();
        review.setGoodsId(targetItem.getGoodsId());
        review.setOrderId(orderId);
        review.setOrderItemId(targetItem.getItemId());
        review.setMemberId(memberId);
        review.setShopId(order.getShopId());
        review.setMemberNickName(member != null ? member.getNickName() : null);
        review.setMemberAvatar(member != null ? member.getAvatar() : null);
        review.setContent(StringUtils.isEmpty(dto.getContent()) ? "" : dto.getContent());
        review.setScore(dto.getScore());
        if (dto.getPics() != null && dto.getPics().size() > OrderAppConstants.MAX_REVIEW_PICS)
        {
            throw new ServiceException("评价图片最多" + OrderAppConstants.MAX_REVIEW_PICS + "张");
        }
        review.setReviewPics(orderAppSupport.joinPics(dto.getPics()));
        review.setGoodsMainPic(targetItem.getGoodsImage());
        review.setGoodsSpec(targetItem.getGoodsSpec());
        review.setShowFlag("1");
        review.setDelFlag("0");
        review.setCreateTime(now);
        review.setUpdateTime(now);
        reviewMapper.insert(review);
    }

    private BizOrderItem resolveTargetItem(List<BizOrderItem> items, Long orderItemId)
    {
        if (orderItemId != null)
        {
            for (BizOrderItem item : items)
            {
                if (orderItemId.equals(item.getItemId()))
                {
                    return item;
                }
            }
            throw new ServiceException(OrderAppConstants.MSG_ORDER_ITEM_NOT_FOUND);
        }
        return items.get(0);
    }

    private BizGoodsReview resolveReview(Long orderId, Long orderItemId)
    {
        if (orderItemId != null)
        {
            BizGoodsReview review = reviewMapper.selectByOrderItemId(orderItemId);
            if (review != null && orderId.equals(review.getOrderId()))
            {
                return review;
            }
            return null;
        }
        return reviewMapper.selectByOrderId(orderId);
    }

    private List<OrderReviewListRowVO> buildPendingRows(List<BizOrder> orders)
    {
        if (orders == null || orders.isEmpty())
        {
            return Collections.emptyList();
        }
        List<Long> orderIds = orders.stream().map(BizOrder::getOrderId).collect(Collectors.toList());
        List<BizOrderItem> allItems = orderItemMapper.selectByOrderIds(orderIds);
        Map<Long, List<BizOrderItem>> itemsByOrderId = new HashMap<>();
        for (BizOrderItem item : allItems)
        {
            itemsByOrderId.computeIfAbsent(item.getOrderId(), key -> new ArrayList<>()).add(item);
        }
        List<BizGoodsReview> allReviews = reviewMapper.selectByOrderIds(orderIds);
        Map<Long, List<BizGoodsReview>> reviewsByOrderId = new HashMap<>();
        for (BizGoodsReview review : allReviews)
        {
            reviewsByOrderId.computeIfAbsent(review.getOrderId(), key -> new ArrayList<>()).add(review);
        }
        List<OrderReviewListRowVO> rows = new ArrayList<>(orders.size());
        for (BizOrder order : orders)
        {
            List<BizOrderItem> items = itemsByOrderId.getOrDefault(order.getOrderId(), Collections.emptyList());
            Map<Long, BizGoodsReview> reviewByItemId = orderAppSupport.indexReviewsByItemId(items,
                    reviewsByOrderId.get(order.getOrderId()));
            OrderReviewListRowVO row = new OrderReviewListRowVO();
            row.setOrderId(order.getOrderId());
            row.setOrderNo(order.getOrderNo());
            row.setOrderStatus(order.getOrderStatus());
            row.setOrderStatusText(orderAppSupport.toStatusText(order.getOrderStatus()));
            row.setShopId(order.getShopId());
            row.setShopName(order.getShopName());
            row.setPayAmount(order.getPayAmount());
            row.setGoodsAmount(order.getGoodsAmount());
            row.setCreateTime(order.getCreateTime());
            row.setReviewStatus(OrderAppConstants.REVIEW_STATUS_PENDING);
            List<OrderAppItemSummaryVO> itemSummaries = new ArrayList<>();
            for (BizOrderItem item : items)
            {
                OrderAppItemSummaryVO summary = orderAppSupport.toItemSummary(item);
                orderAppSupport.enrichItemReview(summary, order, item, reviewByItemId);
                itemSummaries.add(summary);
            }
            row.setItems(itemSummaries);
            if (!itemSummaries.isEmpty())
            {
                row.setFirstItem(itemSummaries.get(0));
            }
            row.setItemCount(items.size());
            rows.add(row);
        }
        return rows;
    }

    private List<OrderReviewListRowVO> buildDoneRows(Long memberId)
    {
        List<BizGoodsReview> reviews = reviewMapper.selectMemberList(memberId);
        if (reviews == null || reviews.isEmpty())
        {
            return Collections.emptyList();
        }
        List<Long> orderIds = reviews.stream().map(BizGoodsReview::getOrderId).distinct()
                .collect(Collectors.toList());
        Map<Long, List<BizOrderItem>> itemsByOrderId = loadItemsByOrderIds(orderIds);
        List<OrderReviewListRowVO> rows = new ArrayList<>(reviews.size());
        for (BizGoodsReview review : reviews)
        {
            BizOrder order = orderMapper.selectByIdAndMember(review.getOrderId(), memberId);
            OrderReviewListRowVO row = new OrderReviewListRowVO();
            row.setReviewId(review.getReviewId());
            row.setScore(review.getScore());
            row.setContent(review.getContent());
            row.setReviewTime(review.getCreateTime());
            row.setOrderId(review.getOrderId());
            if (order != null)
            {
                row.setOrderNo(order.getOrderNo());
                row.setOrderStatus(order.getOrderStatus());
                row.setOrderStatusText(orderAppSupport.toStatusText(order.getOrderStatus()));
                row.setShopId(order.getShopId());
                row.setShopName(order.getShopName());
                row.setPayAmount(order.getPayAmount());
                row.setGoodsAmount(order.getGoodsAmount());
                row.setCreateTime(order.getCreateTime());
            }
            row.setReviewStatus(OrderAppConstants.REVIEW_STATUS_DONE);
            BizOrderItem item = resolveReviewItem(review, itemsByOrderId);
            row.setFirstItem(orderAppSupport.toItemSummary(item));
            row.setItemCount(1);
            rows.add(row);
        }
        return rows;
    }

    private Map<Long, List<BizOrderItem>> loadItemsByOrderIds(List<Long> orderIds)
    {
        if (orderIds == null || orderIds.isEmpty())
        {
            return Collections.emptyMap();
        }
        List<BizOrderItem> allItems = orderItemMapper.selectByOrderIds(orderIds);
        Map<Long, List<BizOrderItem>> map = new HashMap<>();
        if (allItems == null)
        {
            return map;
        }
        for (BizOrderItem item : allItems)
        {
            map.computeIfAbsent(item.getOrderId(), key -> new ArrayList<>()).add(item);
        }
        return map;
    }

    private BizOrderItem resolveReviewItem(BizGoodsReview review, Map<Long, List<BizOrderItem>> itemsByOrderId)
    {
        List<BizOrderItem> items = itemsByOrderId.get(review.getOrderId());
        if (items != null && !items.isEmpty())
        {
            if (review.getOrderItemId() != null)
            {
                for (BizOrderItem item : items)
                {
                    if (review.getOrderItemId().equals(item.getItemId()))
                    {
                        return item;
                    }
                }
            }
            return items.get(0);
        }
        return toItemFromReview(review);
    }

    private BizOrderItem toItemFromReview(BizGoodsReview review)
    {
        BizOrderItem item = new BizOrderItem();
        item.setGoodsId(review.getGoodsId());
        item.setGoodsImage(review.getGoodsMainPic());
        item.setGoodsSpec(review.getGoodsSpec());
        item.setQuantity(1);
        return item;
    }

    private BizOrder requireOrder(Long memberId, Long orderId)
    {
        BizOrder order = orderMapper.selectByIdAndMember(orderId, memberId);
        if (order == null)
        {
            throw new ServiceException(OrderConstants.MSG_NOT_FOUND);
        }
        return order;
    }

    private void assertMemberEnabled(Long memberId)
    {
        if (!memberFacade.isMemberEnabled(memberId))
        {
            throw new ServiceException(CheckoutConstants.MSG_MEMBER_DISABLED, 403);
        }
    }
}
