package com.hfkj.service.meal.impl;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.hfkj.common.exception.BaseException;
import com.hfkj.common.exception.ErrorCode;
import com.hfkj.common.exception.ErrorHelp;
import com.hfkj.common.exception.SysCode;
import com.hfkj.config.mqtt.MqttProviderService;
import com.hfkj.dao.BsMealShopCartMapper;
import com.hfkj.entity.*;
import com.hfkj.service.group.BsStoreGroupService;
import com.hfkj.service.meal.BsMealShopCartService;
import com.hfkj.service.meal.BsMealTableOrderService;
import com.hfkj.service.meal.BsMealTableService;
import org.apache.commons.collections4.MapUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @className: BsMealShopCartServiceImpl
 * @author: HuRui
 * @date: 2023/11/30
 **/
@Service("mealShopCartService")
public class BsMealShopCartServiceImpl implements BsMealShopCartService {

    @Resource
    private BsMealShopCartMapper mealShopCartMapper;

    @Resource
    private BsMealTableService mealTableService;

    @Resource
    private BsStoreGroupService storeGroupService;

    @Resource
    private BsMealTableOrderService mealTableOrderService;

    @Resource
    private MqttProviderService mqttProviderService;

    @Autowired
    private RedisTemplate redisTemplate;

    @Override
    public void editData(BsMealShopCart shopCart) {
        if (shopCart.getId() == null) {
            shopCart.setCreateTime(new Date());
            shopCart.setUpdateTime(new Date());
            mealShopCartMapper.insert(shopCart);
        } else {
            shopCart.setUpdateTime(new Date());
            mealShopCartMapper.updateByPrimaryKey(shopCart);
        }
    }

    @Override
    public void addProduct(String serialNumber, Long productId,String userIdentity) {
        String lockKey = "MEAL_SHOP_CART_" + serialNumber;
        try {
            Boolean lock = redisTemplate.opsForValue().setIfAbsent(lockKey, null);
            if(lock) {
                // 加锁成功
                // 查询桌台订单
                BsMealTableOrder tableOrder = mealTableOrderService.getCurrentTableOrder(serialNumber);
                if (tableOrder != null) {
                    // 查询产品
                    BsStoreProduct product = storeGroupService.findStoreProduct(productId);
                    if (product == null) {
                        throw ErrorHelp.genException(SysCode.System, ErrorCode.COMMON_ERROR, "未找到产品");
                    }
                    // 查询购物车中的产品
                    BsMealShopCart shopCart = getShopCartProduct(tableOrder.getOrderNo(), productId);
                    if (shopCart == null) {
                        shopCart = new BsMealShopCart();
                        shopCart.setStoreId(tableOrder.getStoreId());
                        shopCart.setStoreName(tableOrder.getStoreName());
                        shopCart.setSerialNumber(tableOrder.getSerialNumber());
                        shopCart.setTableNumber(tableOrder.getTableNumber());
                        shopCart.setTableName(tableOrder.getTableName());
                        shopCart.setOrderNo(tableOrder.getOrderNo());
                        shopCart.setProductCategoryId(product.getProductCategoryId());
                        shopCart.setProductCategoryName(product.getProductCategoryName());
                        shopCart.setProductId(product.getId());
                        shopCart.setProductImg(product.getImg());
                        shopCart.setProductName(product.getName());
                        shopCart.setProductSpec(product.getSpec());
                        shopCart.setProductPrice(product.getPrice());
                        shopCart.setProductNum(1);
                        // 数量 * 产品单价
                        shopCart.setProductTotalPrice(new BigDecimal(shopCart.getProductNum().toString()).multiply(product.getPrice()));
                        shopCart.setStatus(1);
                        editData(shopCart);
                    } else {
                        // 增加数量
                        shopCart.setProductNum(shopCart.getProductNum()+1);
                        // 数量 * 产品单价
                        shopCart.setProductTotalPrice(new BigDecimal(shopCart.getProductNum().toString()).multiply(product.getPrice()));
                        editData(shopCart);
                    }

                    // 推送MQTT
                    Map<String,Object> pushParam = new HashMap<>();
                    pushParam.put("userIdentity", userIdentity);

                    pushParam.put("cmdType", shopCart.getProductNum()==1?CmdTypeEnum.type1.getNumber():CmdTypeEnum.type2.getNumber());
                    pushParam.put("product", product);

                    // 产品列表
                    Map<String,Object> param = new HashMap<>();
                    param.put("serialNumber", serialNumber);
                    pushParam.put("productList", getShopCartProductList(param));

                    mqttProviderService.publish(2, false, "MEAL_TABLE_" + serialNumber, JSONObject.toJSONString(pushParam));
                }

                redisTemplate.delete(lockKey);

            } else {
                System.out.println("加锁失败");
                Thread.sleep(100);   // 加锁失败，重试
                addProduct(serialNumber, productId, userIdentity);
            }
        } catch (BaseException baseException) {
            redisTemplate.delete(lockKey);
            throw ErrorHelp.genException(SysCode.System, ErrorCode.COMMON_ERROR, baseException.getErrorMsg());

        } catch (Exception e) {
            redisTemplate.delete(lockKey);
            throw ErrorHelp.genException(SysCode.System, ErrorCode.COMMON_ERROR, "未知错误");
        }
    }

    @Override
    public void reduceProduct(String serialNumber, Long productId,String userIdentity) {
        String lockKey = "MEAL_SHOP_CART_" + serialNumber;
        try {
            Boolean lock = redisTemplate.opsForValue().setIfAbsent(lockKey, null);
            if(lock) {
                // 加锁成功
                // 查询桌台订单
                BsMealTableOrder tableOrder = mealTableOrderService.getCurrentTableOrder(serialNumber);
                if (tableOrder != null) {
                    // 查询产品
                    BsStoreProduct product = storeGroupService.findStoreProduct(productId);
                    if (product == null) {
                        throw ErrorHelp.genException(SysCode.System, ErrorCode.COMMON_ERROR, "未找到产品");
                    }
                    // 查询购物车中的产品
                    BsMealShopCart shopCart = getShopCartProduct(tableOrder.getOrderNo(), productId);
                    if (shopCart != null) {
                        // 减少数量
                        shopCart.setProductNum(shopCart.getProductNum()-1);
                        // 数量 * 产品单价
                        shopCart.setProductTotalPrice(new BigDecimal(shopCart.getProductNum().toString()).multiply(product.getPrice()));
                        if (shopCart.getProductNum() == 0) {
                            shopCart.setStatus(0);
                        }
                        editData(shopCart);
                    }

                    // 推送MQTT
                    Map<String,Object> pushParam = new HashMap<>();
                    pushParam.put("userIdentity", userIdentity);

                    pushParam.put("cmdType", shopCart.getProductNum()==0?CmdTypeEnum.type3.getNumber():CmdTypeEnum.type4.getNumber());
                    pushParam.put("product", product);

                    // 产品列表
                    Map<String,Object> param = new HashMap<>();
                    param.put("serialNumber", serialNumber);
                    pushParam.put("productList", getShopCartProductList(param));

                    mqttProviderService.publish(2, false, "MEAL_TABLE_" + serialNumber, JSONObject.toJSONString(pushParam));
                }

                redisTemplate.delete(lockKey);

            } else {
                System.out.println("加锁失败");
                Thread.sleep(100);   // 加锁失败，重试
                reduceProduct(serialNumber, productId, userIdentity);
            }
        } catch (BaseException baseException) {
            redisTemplate.delete(lockKey);
            throw ErrorHelp.genException(SysCode.System, ErrorCode.COMMON_ERROR, baseException.getErrorMsg());

        } catch (Exception e) {
            redisTemplate.delete(lockKey);
            throw ErrorHelp.genException(SysCode.System, ErrorCode.COMMON_ERROR, "未知错误");
        }
    }

    @Override
    public void clear(String serialNumber, String userIdentity) {
        String lockKey = "MEAL_SHOP_CART_" + serialNumber;
        try {
            Boolean lock = redisTemplate.opsForValue().setIfAbsent(lockKey, null);
            if(lock) {
                // 加锁成功
                // 查询桌台订单
                BsMealTableOrder tableOrder = mealTableOrderService.getCurrentTableOrder(serialNumber);
                if (tableOrder != null) {
                    mealShopCartMapper.clear(serialNumber);
                }

                // 推送MQTT
                Map<String,Object> pushParam = new HashMap<>();
                pushParam.put("userIdentity", userIdentity);

                pushParam.put("cmdType", CmdTypeEnum.type5.getNumber());
                pushParam.put("product", null);

                // 产品列表
                pushParam.put("productList", new JSONArray());
                mqttProviderService.publish(2, false, "MEAL_TABLE_" + serialNumber, JSONObject.toJSONString(pushParam));

                redisTemplate.delete(lockKey);

            } else {
                System.out.println("加锁失败");
                Thread.sleep(100);   // 加锁失败，重试
                clear(serialNumber, userIdentity);
            }
        } catch (BaseException baseException) {
            redisTemplate.delete(lockKey);
            throw ErrorHelp.genException(SysCode.System, ErrorCode.COMMON_ERROR, baseException.getErrorMsg());

        } catch (Exception e) {
            redisTemplate.delete(lockKey);
            throw ErrorHelp.genException(SysCode.System, ErrorCode.COMMON_ERROR, "未知错误");
        }
    }

    @Override
    public void clearData(String serialNumber) {
        mealShopCartMapper.clear(serialNumber);
    }

    @Override
    public BsMealShopCart getShopCartProduct(String orderNo, Long productId) {
        BsMealShopCartExample example = new BsMealShopCartExample();
        example.createCriteria()
                .andOrderNoEqualTo(orderNo)
                .andProductIdEqualTo(productId)
                .andStatusNotEqualTo(0);
        List<BsMealShopCart> list = mealShopCartMapper.selectByExample(example);
        if (!list.isEmpty()) {
            return list.get(0);
        }
        return null;
    }

    @Override
    public List<BsMealShopCart> getShopCartProductList(Map<String, Object> param) {
        BsMealShopCartExample example = new BsMealShopCartExample();
        BsMealShopCartExample.Criteria criteria = example.createCriteria().andStatusNotEqualTo(0);

        if (StringUtils.isNotBlank(MapUtils.getString(param, "serialNumber"))) {
            criteria.andSerialNumberEqualTo(MapUtils.getString(param, "serialNumber"));
        }

        example.setOrderByClause("create_time desc");
        return mealShopCartMapper.selectByExample(example);
    }
}



enum CmdTypeEnum {

    type1(1, "增加产品"),
    type2(2, "增加产品数量"),
    type3(3, "删除产品"),
    type4(4, "减少产品数量"),
    type5(5, "清空购物车"),
    type6(6, "提交订单"),
    ;

    private Integer number;

    private String name;

    CmdTypeEnum(int number, String name) {
        this.number = number;
        this.name = name;
    }

    public Integer getNumber() {
        return number;
    }

    public void setNumber(Integer number) {
        this.number = number;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}
