package cn.iocoder.yudao.module.member.service.orderdetail;

import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONUtil;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
import cn.iocoder.yudao.module.member.controller.admin.orderdetaillog.vo.OrderDetailLogSaveReqVO;
import cn.iocoder.yudao.module.member.controller.admin.screen.vo.DishVO;
import cn.iocoder.yudao.module.member.controller.app.orderdetail.vo.AppOrderDetailPageReqVO;
import cn.iocoder.yudao.module.member.controller.app.orderdetail.vo.AppOrderDetailRespVO;
import cn.iocoder.yudao.module.member.controller.app.orderdetail.vo.AppOrderDetailSaveReqVO;
import cn.iocoder.yudao.module.member.controller.app.orderdetail.vo.OtherVO;
import cn.iocoder.yudao.module.member.dal.dataobject.diningplates.DiningPlatesDO;
import cn.iocoder.yudao.module.member.dal.dataobject.order.DishOrderDO;
import cn.iocoder.yudao.module.member.dal.dataobject.orderdetail.OrderDetailDO;
import cn.iocoder.yudao.module.member.dal.mysql.diningplates.DiningPlatesMapper;
import cn.iocoder.yudao.module.member.dal.mysql.order.DishOrderMapper;
import cn.iocoder.yudao.module.member.dal.mysql.orderdetail.OrderDetailMapper;
import cn.iocoder.yudao.module.member.service.async.MemberAsyncService;
import cn.iocoder.yudao.module.member.service.diningplates.DiningPlatesService;
import cn.iocoder.yudao.module.member.service.orderdetaillog.OrderDetailLogService;
import cn.iocoder.yudao.module.member.util.MemberTimeUtils;
import cn.iocoder.yudao.module.system.api.dish.DishesApi;
import cn.iocoder.yudao.module.system.api.dish.dto.DishesRespDto;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.validation.annotation.Validated;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.time.LocalDateTime;
import java.util.List;

import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
import static cn.iocoder.yudao.module.member.enums.ErrorCodeConstants.DINING_PLATES_NUM_NOT_EXISTS;
import static cn.iocoder.yudao.module.member.enums.ErrorCodeConstants.ORDER_DETAIL_NOT_EXISTS;

/**
 * 订单明细 Service 实现类
 *
 * @author 开发账号
 */
@Service
@Validated
public class OrderDetailServiceImpl implements OrderDetailService {

    @Resource
    private OrderDetailMapper orderDetailMapper;

    @Resource
    private DishOrderMapper dishOrderMapper;

    @Resource
    private DiningPlatesMapper  diningPlatesMapper;

    @Resource
    private DishesApi dishesApi;

    @Resource
    private DiningPlatesService diningPlatesService;

    @Resource
    private StringRedisTemplate stringRedisTemplate;

    @Resource
    private HttpServletRequest httpServletRequest;
    @Resource
    private MemberAsyncService asyncService;
    @Resource
    private OrderDetailLogService orderDetailLogService;


    @Override
    @Transactional(rollbackFor = Exception.class)
    public Long createOrderDetail(AppOrderDetailSaveReqVO createReqVO) {
        if(StrUtil.isBlank(createReqVO.getDiningPlatesNum())){
            throw exception(DINING_PLATES_NUM_NOT_EXISTS);
        }
        DiningPlatesDO diningPlatesDO = diningPlatesService.getDiningPlatesByNum(createReqVO.getDiningPlatesNum(), createReqVO.getStoreId());
        if (diningPlatesDO == null ){
            diningPlatesDO = new DiningPlatesDO();
        }
        if (diningPlatesDO.getId() == null) {
            diningPlatesDO.setStoreId(createReqVO.getStoreId());
            diningPlatesDO.setDiningPlatesNum(createReqVO.getDiningPlatesNum());
            diningPlatesService.insertDiningPlates(diningPlatesDO);
        }
        //计算新总价
        DishesRespDto dish = dishesApi.getDish(createReqVO.getDishesId());
        if(createReqVO.getWeight().compareTo(new BigDecimal(dish.getErrorNum()))<=0){
            return 0L;
        }

        if(diningPlatesDO.getOrderId() == null){
            //创建初始订单
            DishOrderDO dishOrderDO = new DishOrderDO();
            dishOrderDO.setDiningPlatesNum(diningPlatesDO.getDiningPlatesNum())
                    .setOrderStatus(DishOrderDO.ABNORMAL)
                    .setStoreId(diningPlatesDO.getStoreId());
            dishOrderMapper.insert(dishOrderDO);
            diningPlatesDO.setOrderId(dishOrderDO.getId());
            diningPlatesDO.setStatus(DiningPlatesDO.USE);
            diningPlatesMapper.updateById(diningPlatesDO);
        }

        String old = stringRedisTemplate.opsForValue().get(createReqVO.getDiningPlatesNum()+"-" +createReqVO.getStoreId());
        BigDecimal oldBigDecimal = new BigDecimal(StrUtil.isBlank(old)?"0":old);
        //计算每个菜品的价格
        BigDecimal bigDecimal1 = dish.getDishesSumPrice().multiply(createReqVO.getWeight()).divide(dish.getDishesNumber(), 2, RoundingMode.HALF_UP);
        //更新价格
        BigDecimal newPrice = bigDecimal1.add(oldBigDecimal).setScale(2, RoundingMode.HALF_UP);
        stringRedisTemplate.opsForValue().set(createReqVO.getDiningPlatesNum() + "-" +createReqVO.getStoreId(), newPrice.toString());

        OtherVO otherVO = new OtherVO();
        String header = getHearder();
        otherVO.setSn(header);
        otherVO.setOrderId(diningPlatesDO.getOrderId());
        otherVO.setDishesName(dish.getDishesName());
        otherVO.setDishesImageUrl(dish.getDishesImageUrl());
        otherVO.setPrice(bigDecimal1);
        otherVO.setUnitPrice(dish.getDishesSumPrice());
        asyncService.createOrderDetail(createReqVO,otherVO);
        //记录日志
        OrderDetailLogSaveReqVO orderDetailLogSaveReqVO = new OrderDetailLogSaveReqVO();
        orderDetailLogSaveReqVO.setStoreId(createReqVO.getStoreId());
        orderDetailLogSaveReqVO.setDeviceSn(header);
        orderDetailLogSaveReqVO.setParam(JSONUtil.toJsonStr(createReqVO));
        orderDetailLogSaveReqVO.setInsertParam(JSONUtil.toJsonStr(otherVO));
        orderDetailLogService.createOrderDetailLog(orderDetailLogSaveReqVO);
        // 返回写死
        return 0L;
    }

    @Override
    public void updateOrderDetail(AppOrderDetailSaveReqVO updateReqVO) {
        // 校验存在
        validateOrderDetailExists(updateReqVO.getId());
        // 更新
        OrderDetailDO updateObj = BeanUtils.toBean(updateReqVO, OrderDetailDO.class);
        if(updateReqVO.getWeight().compareTo(BigDecimal.ZERO) == 0){
            orderDetailMapper.deleteById(updateObj);
        }else {
            orderDetailMapper.updateById(updateObj);
        }
    }

    @Override
    public void updateOrderDetailNew(OrderDetailDO orderDetailDO) {
        // 更新
        if(orderDetailDO.getWeight().compareTo(BigDecimal.ZERO) == 0){
            orderDetailMapper.deleteById(orderDetailDO);
        }else {
            orderDetailMapper.updateById(orderDetailDO);
        }
    }

    @Override
    public void deleteOrderDetail(Long id) {
        // 校验存在
        validateOrderDetailExists(id);
        // 删除
        orderDetailMapper.deleteById(id);
    }

    private void validateOrderDetailExists(Long id) {
        if (orderDetailMapper.selectById(id) == null) {
            throw exception(ORDER_DETAIL_NOT_EXISTS);
        }
    }

    @Override
    public OrderDetailDO getOrderDetail(Long id) {
        return orderDetailMapper.selectById(id);
    }

    @Override
    public PageResult<OrderDetailDO> getOrderDetailPage(AppOrderDetailPageReqVO pageReqVO) {
        return orderDetailMapper.selectPage(pageReqVO);
    }

    @Override
    public List<AppOrderDetailRespVO> selectListByOrderId(Long orderId) {
        Long storeId = dishOrderMapper.selectById(orderId).getStoreId();
        List<OrderDetailDO> orderDetailDOS = orderDetailMapper.selectList(Wrappers.<OrderDetailDO>lambdaQuery().eq(OrderDetailDO::getOrderId, orderId));
        List<AppOrderDetailRespVO> bean = BeanUtils.toBean(orderDetailDOS, AppOrderDetailRespVO.class);
        bean.forEach(f -> f.setStoreId(storeId));
        return bean;
    }

    @Override
    public List<OrderDetailDO> selectListByOrderIds(List<Long> orderIds) {
        List<OrderDetailDO> orderDetailDOS = orderDetailMapper.selectList(Wrappers.<OrderDetailDO>lambdaQuery().in(OrderDetailDO::getOrderId, orderIds));
        return orderDetailDOS;
    }

    public String getHearder() {
        try {
            return httpServletRequest.getHeader("Authorization");
        } catch (Exception e) {
            throw exception(2000_10_001, "无法获取设备编码");
        }
    }

    @Override
    public List<DishVO> selectDishSale(Long storeId, String startTime, String endTime, Integer type) {
        LocalDateTime start = MemberTimeUtils.string2Time(startTime);
        LocalDateTime end = MemberTimeUtils.string2Time(endTime);
        return orderDetailMapper.selectDishSale(storeId, start, end,type);
    }

    @Override
    public void insertOne(OrderDetailDO orderDetailDO) {
        orderDetailMapper.insert(orderDetailDO);
    }
}