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

import cn.hutool.core.util.StrUtil;
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.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.dal.dataobject.order.DishOrderDO;
import cn.iocoder.yudao.module.member.dal.dataobject.orderdetail.OrderDetailDO;
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.diningplates.DiningPlatesService;
import cn.iocoder.yudao.module.member.util.MemberConstants;
import cn.iocoder.yudao.module.system.api.carteen.CarteenApi;
import cn.iocoder.yudao.module.system.api.dish.DishesApi;
import cn.iocoder.yudao.module.system.api.dish.dto.DishesRespDto;
import cn.iocoder.yudao.module.system.api.dishesnutrition.DishesNutritionApi;
import cn.iocoder.yudao.module.system.api.dishesnutrition.dto.DishesNutritionRespDTO;
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.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.List;

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

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

    @Resource
    private OrderDetailMapper orderDetailMapper;

    @Resource
    private CarteenApi carteenApi;

    @Resource
    private DishesNutritionApi dishesNutritionApi;

    @Resource
    private DishOrderMapper dishOrderMapper;

    @Resource
    private DishesApi dishesApi;

    @Resource
    private DiningPlatesService diningPlatesService;

    @Resource
    private StringRedisTemplate stringRedisTemplate;

    @Resource
    private HttpServletRequest httpServletRequest;


    @Override
    @Transactional(rollbackFor = Exception.class)
    public Long createOrderDetail(AppOrderDetailSaveReqVO createReqVO) {

        //餐盘号去获取订单
        DishOrderDO dishOrderDO = dishOrderMapper.selectOne(Wrappers.<DishOrderDO>lambdaQuery()
                .eq(DishOrderDO::getDiningPlatesNum, createReqVO.getDiningPlatesNum())
                .eq(DishOrderDO::getStoreId, createReqVO.getStoreId())
                .eq(DishOrderDO::getOrderStatus, DishOrderDO.INCOMPLETE)
                .orderByDesc(DishOrderDO::getCreateTime)
                .last(MemberConstants.LIMIT_ONE));
        if (dishOrderDO == null) {
            throw exception(ORDER_ALREADY_COMPLETE);
        }

        //判定餐盘是否绑定并刷新绑定时间
        Boolean b = diningPlatesService.checkBind(createReqVO.getDiningPlatesNum(), createReqVO.getStoreId());
        if (!b) {
            throw exception(DINING_PLATES_NOT_BIND);
        }

        DishesRespDto dish = dishesApi.getDish(createReqVO.getDishesId());
        DishesNutritionRespDTO dishEnergy = dishesNutritionApi.getDishEnergy(createReqVO.getDishesId());

        // 插入数据
        OrderDetailDO orderDetail = BeanUtils.toBean(createReqVO, OrderDetailDO.class);

        //判定门店资料是否录入 ->移动到绑盘的时候
        //if(dishOrderDO.getStoreId()==null){
        //    CarteenRespDto carteen = carteenApi.getCarteen(createReqVO.getDishesId());
        //    dishOrderDO.setStoreId(carteen.getId()).setStoreName(carteen.getStoresName());
        //    dishOrderMapper.updateById(dishOrderDO);
        //}
        //计算新总价
        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());

        //计算热量
        if (dishEnergy != null && StrUtil.isNotEmpty(dishEnergy.getDishesNumber())) {
            BigDecimal dishesNumber = new BigDecimal(dishEnergy.getDishesNumber());
            BigDecimal nutritionNumber = new BigDecimal(dishEnergy.getNutritionNumber());
            if (BigDecimal.ZERO.compareTo(dishesNumber) != 0) {
                BigDecimal bigDecimal = createReqVO.getWeight().multiply(nutritionNumber).divide(dishesNumber.multiply(new BigDecimal("4.184")), 2, RoundingMode.HALF_UP);
                orderDetail.setHeat(bigDecimal.doubleValue());
            }
        }

        orderDetail.setOrderId(dishOrderDO.getId()).setDishesName(dish.getDishesName()).setDishUrl(dish.getDishesImageUrl());
        orderDetail.setSn(this.getHearder());
        orderDetail.setPrice(bigDecimal1);
        orderDetailMapper.insert(orderDetail);
        // 返回
        return orderDetail.getId();
    }

    @Override
    public void updateOrderDetail(AppOrderDetailSaveReqVO updateReqVO) {
        // 校验存在
        validateOrderDetailExists(updateReqVO.getId());
        // 更新
        OrderDetailDO updateObj = BeanUtils.toBean(updateReqVO, OrderDetailDO.class);
        orderDetailMapper.updateById(updateObj);
    }

    @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) {
        LocalDate today = LocalDate.now();
        String time = today.format(DateTimeFormatter.ofPattern(MemberConstants.DATE_FORMAT));
        return orderDetailMapper.selectDishSale(time, storeId);
    }


}