package cn.iocoder.yudao.module.system.service.dishes;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.NumberUtil;
import cn.hutool.core.util.ObjUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import cn.iocoder.yudao.framework.common.pojo.PageParam;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
import cn.iocoder.yudao.module.system.api.dish.dto.DishExcelDto;
import cn.iocoder.yudao.module.system.controller.admin.dishes.vo.DishesPageReqVO;
import cn.iocoder.yudao.module.system.controller.admin.dishes.vo.DishesRespVO;
import cn.iocoder.yudao.module.system.controller.admin.dishes.vo.DishesSaveReqVO;
import cn.iocoder.yudao.module.system.controller.admin.dishesnutrition.vo.DishesNutritionPageReqVO;
import cn.iocoder.yudao.module.system.controller.admin.dishesnutrition.vo.DishesNutritionSaveReqVO;
import cn.iocoder.yudao.module.system.controller.admin.dishesraw.vo.DishesRawPageReqVO;
import cn.iocoder.yudao.module.system.controller.admin.dishesraw.vo.DishesRawSaveReqVO;
import cn.iocoder.yudao.module.system.controller.app.dishes.vo.AppSaveVO;
import cn.iocoder.yudao.module.system.controller.app.dishes.vo.AppUpdateVO;
import cn.iocoder.yudao.module.system.dal.dataobject.dishes.DishesDO;
import cn.iocoder.yudao.module.system.dal.dataobject.dishesnutrition.DishesNutritionDO;
import cn.iocoder.yudao.module.system.dal.dataobject.dishesraw.DishesRawDO;
import cn.iocoder.yudao.module.system.dal.dataobject.dishestype.DishesTypeDO;
import cn.iocoder.yudao.module.system.dal.mysql.dishes.DishesMapper;
import cn.iocoder.yudao.module.system.enums.ErrorCodeConstants;
import cn.iocoder.yudao.module.system.service.deviceinfo.DeviceInfoService;
import cn.iocoder.yudao.module.system.service.dishesnutrition.DishesNutritionService;
import cn.iocoder.yudao.module.system.service.dishesraw.DishesRawService;
import cn.iocoder.yudao.module.system.service.dishestype.DishesTypeService;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import lombok.SneakyThrows;
import org.aspectj.weaver.ast.Var;
import org.springframework.stereotype.Service;
import org.springframework.validation.annotation.Validated;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.time.format.TextStyle;
import java.util.ArrayList;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.stream.Collectors;

import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;

/**
 * 菜品管理 Service 实现类
 *
 * @author 开发账号
 */
@Service
@Validated
public class DishesServiceImpl implements DishesService {

    @Resource
    private DishesMapper dishesMapper;
    @Resource
    private DishesNutritionService dishesNutritionService;
    @Resource
    private DishesRawService dishesRawService;
    @Resource
    private DeviceInfoService deviceInfoService;
    @Resource
    private HttpServletRequest httpServletRequest;
    @Resource
    private DishesTypeService dishesTypeService;

    @Override
    @SneakyThrows
    public Long createDishes(DishesSaveReqVO createReqVO) {
        // 插入
        DishesDO dishes = BeanUtils.toBean(createReqVO, DishesDO.class);
        dishes.setDeleted(Boolean.FALSE);

        checkDishes(dishes.getDishesName(),dishes.getCarteenId(),null);

        LocalDateTime today = LocalDateTime.now();
        int hour = today.getHour();
        String time = dishesMapper.getTime(hour);
        String dayOfWeekInChinese = getToday();
        if(StrUtil.isBlank(createReqVO.getWeekTime())){
            dishes.setWeekTime(dayOfWeekInChinese);
        }
        if(StrUtil.isBlank(createReqVO.getTimeSlot())){
            dishes.setTimeSlot(time);
        }

        //计算每g多少钱
        BigDecimal dishesSumPrice = createReqVO.getDishesSumPrice();
        BigDecimal dishesNumber = createReqVO.getDishesNumber();
        BigDecimal div = NumberUtil.div(dishesSumPrice, dishesNumber, 2);
        //避免计算出每克价格约 为0
        if (div.floatValue() <= 0.00f) {
            dishes.setDishesBasePrice(new BigDecimal("0.01"));
        } else {
            dishes.setDishesBasePrice(div);
        }
        dishesMapper.insert(dishes);
        List<DishesNutritionSaveReqVO> list = createReqVO.getDishesNutritionList();
        List<DishesRawSaveReqVO> dishesRawList = createReqVO.getDishesRawList();
        if (ObjUtil.isNotEmpty(list)) {
            list.forEach(f -> f.setDishesId(dishes.getId()));
            dishesNutritionService.createDishesNutritionList(list);
        }
        if (ObjUtil.isNotEmpty(dishesRawList)) {
            dishesRawList.forEach(f -> f.setDishesId(dishes.getId()));
            dishesRawService.createDishesRawList(dishesRawList);
        }
        // 返回
        return dishes.getId();
    }

    @Override
    public Long createDishesApp(AppSaveVO vo) {
        // 插入
        DishesDO dishes = BeanUtils.toBean(vo, DishesDO.class);
        dishes.setDeleted(Boolean.FALSE);

        if(vo.getCarteenId() == null ){
            vo.setCarteenId(deviceInfoService.getCarteen(getHearder())) ;
        }
        dishes.setCarteenId(vo.getCarteenId());
        dishes.setDishesNumber(new BigDecimal("50"));

        checkDishes(dishes.getDishesName(),dishes.getCarteenId(),null);

        LocalDateTime today = LocalDateTime.now();
        int hour = today.getHour();
        String time = dishesMapper.getTime(hour);
        String dayOfWeekInChinese = getToday();
        dishes.setWeekTime(dayOfWeekInChinese);
        dishes.setTimeSlot(time);
        //计算每g多少钱
        BigDecimal dishesSumPrice = vo.getDishesSumPrice();
        BigDecimal dishesNumber = new BigDecimal("50");
        BigDecimal div = NumberUtil.div(dishesSumPrice, dishesNumber, 2);
        //避免计算出每克价格约 为0
        if (div.floatValue() <= 0.00f) {
            dishes.setDishesBasePrice(new BigDecimal("0.01"));
        } else {
            dishes.setDishesBasePrice(div);
        }
        dishesMapper.insert(dishes);
        // 返回
        return dishes.getId();
    }

    @Override
    @SneakyThrows
    public void updateDishes(DishesSaveReqVO updateReqVO) {
        // 校验存在
        validateDishesExists(updateReqVO.getId());
        // 更新
        DishesDO updateObj = BeanUtils.toBean(updateReqVO, DishesDO.class);

        checkDishes(updateObj.getDishesName(),updateObj.getCarteenId(),updateReqVO.getId());

        //计算每g多少钱
        BigDecimal dishesSumPrice = updateObj.getDishesSumPrice();
        BigDecimal dishesNumber = updateObj.getDishesNumber();
        BigDecimal div = NumberUtil.div(dishesSumPrice, dishesNumber, 2);
        //避免计算出每克价格约 为0
        if (div.floatValue() <= 0.00f) {
            updateObj.setDishesBasePrice(new BigDecimal("0.01"));
        } else {
            updateObj.setDishesBasePrice(div);
        }
        dishesMapper.updateById(updateObj);
        List<DishesNutritionSaveReqVO> list = updateReqVO.getDishesNutritionList();
        List<DishesRawSaveReqVO> dishesRawList = updateReqVO.getDishesRawList();
        if (ObjUtil.isNotEmpty(list)) {
            list.forEach(f -> f.setDishesId(updateReqVO.getId()));
            dishesNutritionService.updateDishesNutritionList(list);
        }
        if (ObjUtil.isNotEmpty(dishesRawList)) {
            dishesRawList.forEach(f -> f.setDishesId(updateReqVO.getId()));
            dishesRawService.updateDishesRawList(dishesRawList);
        }
    }

    @Override
    public void updateDishesApp(AppUpdateVO vo) {
        DishesDO dishesDO = validateDishesExists(vo.getId());
        DishesDO updateObj = BeanUtils.toBean(vo, DishesDO.class);

        if(updateObj.getCarteenId() == null ){
            updateObj.setCarteenId(dishesDO.getCarteenId()) ;
        }

        checkDishes(updateObj.getDishesName(),updateObj.getCarteenId(),vo.getId());

        //计算每g多少钱
        BigDecimal dishesSumPrice = updateObj.getDishesSumPrice();
        BigDecimal dishesNumber = new BigDecimal("50");
        BigDecimal div = NumberUtil.div(dishesSumPrice, dishesNumber, 2);
        //避免计算出每克价格约 为0
        if (div.floatValue() <= 0.00f) {
            updateObj.setDishesBasePrice(new BigDecimal("0.01"));
        } else {
            updateObj.setDishesBasePrice(div);
        }
        dishesMapper.updateById(updateObj);
    }

    @Override
    public void deleteDishes(Long id) {
        // 校验存在
        validateDishesExists(id);
        // 删除
        dishesMapper.deleteById(id);
    }

    private DishesDO validateDishesExists(Long id) {
        DishesDO dishesDO = dishesMapper.selectById(id);
        if ( dishesDO == null) {
            throw exception(ErrorCodeConstants.DISHES_NOT_EXISTS);
        }
        return dishesDO;
    }

    /**
     * 获得菜品管理
     *
     * @param id 编号
     * @return 菜品管理
     */
    @Override
    public DishesDO getDishes(Long id) {
        return dishesMapper.selectById(id);
    }

    @Override
    public List<DishesDO> getDishesList(List<Long> ids) {
        return dishesMapper.selectList(Wrappers.<DishesDO>lambdaQuery()
                .in(DishesDO::getId, ids));
    }

    @Override
    public DishesRespVO getDishes1(Long id) {
        DishesRespVO bean = BeanUtils.toBean(dishesMapper.selectById(id), DishesRespVO.class);
        List<DishesNutritionDO> dishesNutritionList = dishesNutritionService.getDishesNutritionList(new DishesNutritionPageReqVO().setDishesId(id));
        DishesRawPageReqVO dishesRawPageReqVO = new DishesRawPageReqVO();
        dishesRawPageReqVO.setDishesId(id);
        dishesRawPageReqVO.setPageSize(PageParam.PAGE_SIZE_NONE);
        List<DishesRawDO> dishesRawList = dishesRawService.getDishesRawPage(dishesRawPageReqVO).getList();
        bean.setDishesNutritionList(dishesNutritionList);
        bean.setDishesRawList(dishesRawList);
        return bean;
    }

    @Override
    public PageResult<DishesDO> getDishesPage(DishesPageReqVO pageReqVO) {
        return dishesMapper.selectPage(pageReqVO);
    }

    @Override
    public PageResult<DishesDO> getDishesPageApp(DishesPageReqVO pageReqVO) {
//        LocalDateTime today = LocalDateTime.now();
//        String dayOfWeekInChinese = today.getDayOfWeek().getDisplayName(TextStyle.FULL, Locale.CHINESE);
//
//        ArrayList<String> week = new ArrayList<>();
//        week.add(dayOfWeekInChinese);
//        week.add("整周");
//        pageReqVO.setWeekTimes(week);
        return dishesMapper.selectPage(pageReqVO);
    }

    @Override
    public Map<Long, String> getDishName(List<Long> ids) {
        List<DishesDO> dishesDOS = dishesMapper.selectList(Wrappers.<DishesDO>lambdaQuery().in(DishesDO::getId, ids));
        Map<Long, String> collect = dishesDOS.stream().collect(Collectors.toMap(DishesDO::getId, DishesDO::getDishesName));
        return collect;
    }

    @Override
    public List<DishesDO> getTodayDishes() {
        LocalDateTime today = LocalDateTime.now();
        int hour = today.getHour();
        String time = dishesMapper.getTime(hour);
        String dayOfWeekInChinese = getToday();

        ArrayList<String> todayTime = new ArrayList<>();
        todayTime.add(time);
        todayTime.add("整天");

        Long carteenId = deviceInfoService.getCarteen(getHearder());
        List<DishesDO> dishesDOS = dishesMapper.selectList(Wrappers.<DishesDO>lambdaQuery()
                .eq(DishesDO::getCarteenId, carteenId)
                .and(w->w.eq(DishesDO::getWeekTime, dayOfWeekInChinese).or().eq(DishesDO::getDailySigns, 1))
                .in(DishesDO::getTimeSlot, todayTime)
                .orderByDesc(DishesDO::getDailySigns,DishesDO::getCreateTime));
        return dishesDOS;
    }

    public String getHearder() {
        try {
            return httpServletRequest.getHeader("Authorization");
        } catch (Exception e) {
            throw exception(2000_10_001, "无法获取设备编码");
        }
    }
    @Override
    public List<DishesDO> getTodayDishesNew() {
        String dayOfWeekInChinese = getToday();

        List<DishesDO> dishesDOS = dishesMapper.selectList(Wrappers.<DishesDO>lambdaQuery()
                .eq(DishesDO::getWeekTime, dayOfWeekInChinese)
                .or()
                .eq(DishesDO::getDailySigns,1)
                .orderByDesc(DishesDO::getCreateTime));
        return dishesDOS;
    }


    void checkDishes(String dishName,Long carteenId,Long id){
        List<DishesDO> dishesDOS = dishesMapper.selectList(Wrappers.<DishesDO>lambdaQuery()
                .eq(DishesDO::getCarteenId, carteenId)
                .eq(DishesDO::getDishesName, dishName)
                .ne(id!=null, DishesDO::getId, id));
        if(!dishesDOS.isEmpty()){
            throw exception(ErrorCodeConstants.DISHES_EXISTS);
        }
    }


    public String getToday(){
        LocalDate currentDate = LocalDate.now();
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
        return currentDate.format(formatter);
    }

    @Override
    public void exportDish(List<DishExcelDto> dishExcels, Long storeId) {

        for (DishExcelDto vo:dishExcels){
            List<DishesDO> dishesDOS = dishesMapper.selectList(Wrappers.<DishesDO>lambdaQuery()
                    .eq(DishesDO::getCarteenId, storeId)
                    .eq(DishesDO::getDishesName, vo.getName()));

            if(CollectionUtil.isNotEmpty(dishesDOS)){
                continue;
            }
            // 插入
            DishesDO dishes = new DishesDO();
            dishes.setDishesName(vo.getName());
            dishes.setDishesSumPrice(vo.getMoney());
            dishes.setDeleted(Boolean.FALSE);
            dishes.setCarteenId(storeId);
            dishes.setDishesNumber(new BigDecimal("50"));
            DishesTypeDO byName = dishesTypeService.getByName(vo.getType(), storeId);
            dishes.setDishecType(ObjectUtil.isNotEmpty(byName)?byName.getId().toString():null);

            LocalDateTime today = LocalDateTime.now();
            int hour = today.getHour();
            String time = dishesMapper.getTime(hour);
            String dayOfWeekInChinese = getToday();
            dishes.setWeekTime(dayOfWeekInChinese);
            dishes.setTimeSlot(time);
            //计算每g多少钱
            BigDecimal dishesSumPrice = vo.getMoney();
            BigDecimal dishesNumber = new BigDecimal("50");
            BigDecimal div = NumberUtil.div(dishesSumPrice, dishesNumber, 2);
            //避免计算出每克价格约 为0
            if (div.floatValue() <= 0.00f) {
                dishes.setDishesBasePrice(new BigDecimal("0.01"));
            } else {
                dishes.setDishesBasePrice(div);
            }
            dishesMapper.insert(dishes);
        }
    }
}