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.SpPrinterConfig;
import com.hfkj.config.SpPrinterTemplate;
import com.hfkj.dao.BsMealTableOrderMapper;
import com.hfkj.entity.*;
import com.hfkj.service.BsDeviceService;
import com.hfkj.service.group.BsStoreGroupService;
import com.hfkj.service.meal.*;
import com.hfkj.sysenum.DeviceTypeEnum;
import com.hfkj.sysenum.MealTableOrderPayStatusEnum;
import com.hfkj.sysenum.MealTableOrderStatusEnum;
import org.apache.commons.collections4.MapUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.io.IOException;
import java.math.BigDecimal;
import java.util.*;

/**
 * @className: BsMealTableOrderServiceImpl
 * @author: HuRui
 * @date: 2023/11/30
 **/
@Service("mealTableOrderService")
public class BsMealTableOrderServiceImpl implements BsMealTableOrderService {

    @Resource
    private BsMealTableOrderMapper mealTableOrderMapper;

    @Resource
    private BsMealTableOrderProductService mealTableOrderProductService;

    @Resource
    private BsMealTableService mealTableService;

    @Resource
    private BsStoreGroupService storeGroupService;

    @Resource
    private BsDeviceService deviceService;


    @Resource
    private RedisTemplate redisTemplate;

    @Override
    public void editData(BsMealTableOrder mealTableOrder) {
        if (mealTableOrder.getId() == null) {
            mealTableOrder.setCreateTime(new Date());
            mealTableOrder.setUpdateTime(new Date());
            mealTableOrderMapper.insert(mealTableOrder);
        } else {
            mealTableOrder.setUpdateTime(new Date());
            mealTableOrderMapper.updateByPrimaryKey(mealTableOrder);
        }
    }

    @Override
    public BsMealTableOrder getCurrentTableOrder(String serialNumber) {
        BsMealTableOrderExample example = new BsMealTableOrderExample();
        example.createCriteria()
                .andSerialNumberEqualTo(serialNumber)
                .andStatusEqualTo(MealTableOrderStatusEnum.status1.getNumber());
        List<BsMealTableOrder> orderList = mealTableOrderMapper.selectByExample(example);
        if (!orderList.isEmpty()) {
            return orderList.get(0);
        }
        return null;
    }

    @Override
    public BsMealTableOrder getTableOrderByOrderNo(String orderNo) {
        BsMealTableOrderExample example = new BsMealTableOrderExample();
        example.createCriteria().andOrderNoEqualTo(orderNo);
        List<BsMealTableOrder> orderList = mealTableOrderMapper.selectByExample(example);
        if (!orderList.isEmpty()) {
            return orderList.get(0);
        }
        return null;
    }

    @Override
    public BsMealTableOrder getTableOrderByPayOrderNo(String payOrderNo) {
        BsMealTableOrderExample example = new BsMealTableOrderExample();
        example.createCriteria().andPayOrderNoEqualTo(payOrderNo);
        List<BsMealTableOrder> orderList = mealTableOrderMapper.selectByExample(example);
        if (!orderList.isEmpty()) {
            return orderList.get(0);
        }
        return null;
    }

    @Override
    public List<BsMealTableOrder> getTableOrderList(Map<String, Object> param) {
        BsMealTableOrderExample example = new BsMealTableOrderExample();
        BsMealTableOrderExample.Criteria criteria = example.createCriteria().andStatusNotEqualTo(MealTableOrderStatusEnum.status0.getNumber());

        if (MapUtils.getLong(param, "storeId") != null) {
            criteria.andStoreIdEqualTo(MapUtils.getLong(param, "storeId"));
        }

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

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

    @Override
    public void paySuccess(BsTradeOrder tradeOrder) {
        // 查询订单详情
        BsMealTableOrder mealTableOrder = getTableOrderByPayOrderNo(tradeOrder.getOutTradeNo());
        if (mealTableOrder != null) {
            mealTableOrder.setPayPrice(tradeOrder.getTradeAmount());
            editData(mealTableOrder);

            // 关台
            mealTableService.endTable(mealTableOrder.getSerialNumber());
        }
    }

    @Override
    @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    public void operateOrderProduct(String orderNo, JSONArray productArray) {
        // 查询订单
        BsMealTableOrder order = getTableOrderByOrderNo(orderNo);
        if (order == null) {
            throw ErrorHelp.genException(SysCode.System, ErrorCode.REQ_PARAMS_ERROR, "未知的的订单号");
        }
        String lockKey = "MEAL_ORDER_" + order.getOrderNo();
        try {
            Boolean lock = redisTemplate.opsForValue().setIfAbsent(lockKey, null);
            if(lock) {
                // 加锁成功
                // 操作类型  1:添加  2:减少
                for (Object obj : productArray) {
                    JSONObject product = (JSONObject) obj;
                    // 查询产品
                    BsStoreProduct storeProduct = storeGroupService.findStoreProduct(product.getLong("productId"));
                    if (storeProduct == null) {
                        throw ErrorHelp.genException(SysCode.System, ErrorCode.REQ_PARAMS_ERROR, "未知的的产品");
                    }
                    // 查询交易订单中的产品
                    BsMealTableOrderProduct orderProduct = mealTableOrderProductService.getOrderProduct(orderNo, storeProduct.getId());
                    if (orderProduct == null) {
                        orderProduct = new BsMealTableOrderProduct();
                        orderProduct.setOrderId(order.getId());
                        orderProduct.setOrderNo(order.getOrderNo());
                        orderProduct.setProductCategoryId(storeProduct.getProductCategoryId());
                        orderProduct.setProductCategoryName(storeProduct.getProductCategoryName());
                        orderProduct.setProductId(storeProduct.getId());
                        orderProduct.setProductImg(storeProduct.getImg());
                        orderProduct.setProductName(storeProduct.getName());
                        orderProduct.setProductSpec(storeProduct.getSpec());
                        orderProduct.setProductPrice(storeProduct.getPrice());
                        orderProduct.setProductNum(product.getInteger("number"));
                        orderProduct.setProductTotalPrice(new BigDecimal(orderProduct.getProductNum().toString()).multiply(orderProduct.getProductPrice()));
                        orderProduct.setStatus(1);
                    } else {
                        if (product.getInteger("number") <= 0) {
                            orderProduct.setStatus(0);
                        }
                        orderProduct.setProductNum(product.getInteger("number"));
                        orderProduct.setProductTotalPrice(new BigDecimal(orderProduct.getProductNum().toString()).multiply(orderProduct.getProductPrice()));
                    }
                    mealTableOrderProductService.editData(orderProduct);
                }
                // 重新计算交易总价
                order.setOrderAmount(new BigDecimal("0"));

                Map<String,Object> param = new HashMap<>();
                param.put("orderNo", order.getOrderNo());
                List<BsMealTableOrderProduct> orderProductList = mealTableOrderProductService.getOrderProductList(param);
                for (BsMealTableOrderProduct product : orderProductList) {
                    order.setOrderAmount(order.getOrderAmount().add(product.getProductTotalPrice()));
                }
                editData(order);

                redisTemplate.delete(lockKey);

            } else {
                System.out.println("加锁失败");
                Thread.sleep(100);   // 加锁失败，重试
                operateOrderProduct(orderNo, productArray);
            }
        } 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, "未知错误");
        }

    }
}
