package com.ycwl.basic.repository;

import com.ycwl.basic.utils.JacksonUtil;
import com.fasterxml.jackson.core.type.TypeReference;
import com.ycwl.basic.mapper.OrderMapper;
import com.ycwl.basic.model.pc.order.entity.OrderEntity;
import com.ycwl.basic.model.pc.order.entity.OrderItemEntity;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;

import java.util.List;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

@Component
public class OrderRepository {
    @Autowired
    private OrderMapper orderMapper;
    @Autowired
    private RedisTemplate<String, String> redisTemplate;

    public static final String ORDER_CACHE_KEY = "order:%s";
    public static final String ORDER_ITEMS_CACHE_KEY = "order:%s:items";
    public static final String ORDER_ITEM_CACHE_KEY = "order:item:%s";
    public static final String ORDER_USER_FACE_TYPE_BUY_ITEM_CACHE_KEY = "order:user:%s:face:%s:type:%s:id:%s";

    public OrderEntity getOrder(Long orderId) {
        if (redisTemplate.hasKey(String.format(ORDER_CACHE_KEY, orderId))) {
            return JacksonUtil.parseObject(redisTemplate.opsForValue().get(String.format(ORDER_CACHE_KEY, orderId)), OrderEntity.class);
        }
        OrderEntity orderEntity = orderMapper.get(orderId);
        if (orderEntity != null) {
            redisTemplate.opsForValue().set(String.format(ORDER_CACHE_KEY, orderId), JacksonUtil.toJSONString(orderEntity), 60, TimeUnit.SECONDS);
        }
        return orderEntity;
    }

    public List<OrderItemEntity> getOrderItems(Long orderId) {
        if (redisTemplate.hasKey(String.format(ORDER_ITEMS_CACHE_KEY, orderId))) {
            return JacksonUtil.parseObject(redisTemplate.opsForValue().get(String.format(ORDER_ITEMS_CACHE_KEY, orderId)), new TypeReference<List<Long>>() {})
                    .stream().map(this::getOrderItemByOrderItemId).collect(Collectors.toList());
        }
        List<OrderItemEntity> orderItemEntities = orderMapper.listOrderItemByOrderId(orderId);
        if (orderItemEntities != null) {
            redisTemplate.opsForValue().set(
                    String.format(ORDER_ITEMS_CACHE_KEY, orderId),
                    JacksonUtil.toJSONString(orderItemEntities.stream().map(OrderItemEntity::getId).collect(Collectors.toList()))
            );
        }
        return orderItemEntities;
    }

    public OrderItemEntity getOrderItemByOrderItemId(Long orderItemId) {
        if (redisTemplate.hasKey(String.format(ORDER_ITEM_CACHE_KEY, orderItemId))) {
            return JacksonUtil.parseObject(redisTemplate.opsForValue().get(String.format(ORDER_ITEM_CACHE_KEY, orderItemId)), OrderItemEntity.class);
        }
        OrderItemEntity orderItemEntity = orderMapper.getOrderItem(orderItemId);
        if (orderItemEntity != null) {
            redisTemplate.opsForValue().set(String.format(ORDER_ITEM_CACHE_KEY, orderItemId), JacksonUtil.toJSONString(orderItemEntity));
        }
        return orderItemEntity;
    }

    public void clearOrderCache(Long orderId) {
        OrderEntity order = getOrder(orderId);
        redisTemplate.delete(String.format(ORDER_CACHE_KEY, orderId));
        getOrderItems(orderId).forEach(orderItem -> {
            redisTemplate.delete(String.format(ORDER_ITEM_CACHE_KEY, orderItem.getId()));
            clearUserBuyFaceItemCache(order.getMemberId(), order.getFaceId(), orderItem.getGoodsType(), orderItem.getGoodsId());
        });
        redisTemplate.delete(String.format(ORDER_ITEMS_CACHE_KEY, orderId));
    }

    public void updateOrder(Long orderId, OrderEntity updateEntity) {
        updateEntity.setId(orderId);
        orderMapper.updateOrder(updateEntity);
        clearOrderCache(orderId);
    }

    /**
     * 检查用户是否购买了指定商品，并额外校验订单的faceId是否匹配
     * @param userId 用户ID
     * @param faceId 人脸ID
     * @param goodsType 商品类型
     * @param goodsId 商品ID
     * @return 是否已购买且faceId匹配
     */
    public boolean checkUserBuyFaceItem(Long userId, Long faceId, int goodsType, Long goodsId) {
        synchronized (this) {
            String cacheKey = String.format(ORDER_USER_FACE_TYPE_BUY_ITEM_CACHE_KEY, userId, faceId, goodsType, goodsId);
            if (redisTemplate.hasKey(cacheKey)) {
                return "1".equals(redisTemplate.opsForValue().get(cacheKey));
            }
            OrderEntity orderEntity = orderMapper.getUserBuyFaceItem(userId, faceId, goodsType, goodsId);
            if (orderEntity == null) {
                redisTemplate.opsForValue().set(cacheKey, "0", 60, TimeUnit.SECONDS);
                return false;
            }
            if (Integer.valueOf(1).equals(orderEntity.getStatus())) {
                redisTemplate.opsForValue().set(cacheKey, "1");
                return true;
            } else {
                redisTemplate.opsForValue().set(cacheKey, "0", 60, TimeUnit.SECONDS);
                return false;
            }
        }
    }

    public void clearUserBuyFaceItemCache(Long userId, Long faceId, int goodsType, Long goodsId) {
        redisTemplate.delete(String.format(ORDER_USER_FACE_TYPE_BUY_ITEM_CACHE_KEY, userId, faceId, goodsType, goodsId));
    }
}
