package com.jeeplus.psimanage.dishManage.service;

import cn.hutool.extra.spring.SpringUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.jeeplus.common.TokenProvider;
import com.jeeplus.psimanage.dishManage.domain.PsiDishLibrary;
import com.jeeplus.psimanage.dishManage.domain.PsiDishMenu;
import com.jeeplus.psimanage.dishManage.domain.PsiDishMenuDish;
import com.jeeplus.psimanage.dishManage.domain.PsiDishType;
import com.jeeplus.psimanage.dishManage.mapper.PsiDishLibraryMapper;
import com.jeeplus.psimanage.dishManage.mapper.PsiDishMenuDishMapper;
import com.jeeplus.psimanage.dishManage.mapper.PsiDishMenuMapper;
import com.jeeplus.sys.feign.IUserApi;
import com.jeeplus.sys.service.dto.UserDTO;
import com.jeeplus.utils.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Date;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.UUID;

/**
 * 菜单管理
 */
@Service
@Transactional(rollbackFor = Exception.class)
public class PsiDishMenuService extends ServiceImpl<PsiDishMenuDishMapper, PsiDishMenuDish> {

    @Resource
    private PsiDishMenuMapper psiDishMenuMapper;

    @Resource
    private PsiDishMenuDishMapper menuDishMapper;

    @Resource
    private PsiDishLibraryMapper dishLibraryMapper;

    public IPage<PsiDishMenuDish> list(Page<PsiDishMenuDish> page, PsiDishMenuDish info) {
        getOrCreateCurrentMenu();
        QueryWrapper<PsiDishMenuDish> wrapper = buildMenuDishQuery(info);
        wrapper.eq("md.del_flag", "0");
        wrapper.and(w -> w.eq("md.is_history", "0").or().isNull("md.is_history"));
        return menuDishMapper.findCurrentDishList(page, wrapper);
    }

    public IPage<PsiDishMenu> historyList(Page<PsiDishMenu> page) {
        QueryWrapper<PsiDishMenu> wrapper = new QueryWrapper<>();
        wrapper.eq("m.del_flag", "0");
        wrapper.eq("m.is_history", "1");
        return psiDishMenuMapper.findHistoryMenuList(page, wrapper);
    }

    public IPage<PsiDishMenuDish> historyDetailList(Page<PsiDishMenuDish> page, String menuId, PsiDishMenuDish info) {
        if (StringUtils.isBlank(menuId)) {
            return page;
        }
        QueryWrapper<PsiDishMenuDish> wrapper = buildMenuDishQuery(info);
        wrapper.eq("md.del_flag", "0");
        wrapper.eq("md.is_history", "1");
        wrapper.eq("md.menu_id", menuId);
        return menuDishMapper.findHistoryDishList(page, wrapper);
    }

    public IPage<PsiDishLibrary> availableDishList(Page<PsiDishLibrary> page, PsiDishLibrary info) {
        PsiDishMenu menu = getOrCreateCurrentMenu();
        QueryWrapper<PsiDishLibrary> wrapper = new QueryWrapper<>();
        wrapper.eq("a.del_flag", "0");
        wrapper.eq("a.status", "0");
        if (StringUtils.isNotBlank(info.getDishName())) {
            wrapper.like("a.dish_name", info.getDishName());
        }
        if (StringUtils.isNotBlank(info.getDishCode())) {
            wrapper.like("a.dish_code", info.getDishCode());
        }
        if (StringUtils.isNotBlank(info.getTypeId())) {
            wrapper.eq("a.type_id", info.getTypeId());
        }
        return menuDishMapper.findAvailableDishList(page, wrapper, menu.getId());
    }

    public List<PsiDishLibrary> orderDishList(String typeId, String dishName) {
        return menuDishMapper.findOrderDishList(typeId, dishName);
    }

    public List<PsiDishType> orderTypeList() {
        return menuDishMapper.findOrderTypeList();
    }

    public String addDishes(List<String> dishIds) {
        if (dishIds == null || dishIds.isEmpty()) {
            return "请选择要添加的菜品";
        }
        PsiDishMenu menu = getOrCreateCurrentMenu();
        UserDTO userDto = SpringUtil.getBean(IUserApi.class).getByToken(TokenProvider.getCurrentToken());
        Date now = new Date();
        int sort = menuDishMapper.getMaxSort(menu.getId()) == null ? 0 : menuDishMapper.getMaxSort(menu.getId());
        int addCount = 0;
        for (String dishId : dishIds) {
            if (StringUtils.isBlank(dishId) || existsCurrentMenuDish(menu.getId(), dishId)) {
                continue;
            }
            PsiDishLibrary dish = dishLibraryMapper.queryById(dishId);
            if (dish == null || !"0".equals(dish.getStatus())) {
                continue;
            }
            PsiDishMenuDish menuDish = new PsiDishMenuDish();
            menuDish.setId(UUID.randomUUID().toString().replace("-", ""));
            menuDish.setMenuId(menu.getId());
            menuDish.setDishId(dish.getId());
            menuDish.setSalePrice(dish.getSalePrice() == null ? BigDecimal.ZERO : dish.getSalePrice());
            menuDish.setSort(++sort);
            menuDish.setIsHistory("0");
            menuDish.setCreateById(userDto.getId());
            menuDish.setCreateTime(now);
            menuDish.setUpdateById(userDto.getId());
            menuDish.setUpdateTime(now);
            menuDish.setDelFlag(0);
            menuDishMapper.insert(menuDish);
            addCount++;
        }
        return addCount == 0 ? "所选菜品已在当前菜单中" : "添加成功";
    }

    public String saveDishes(List<String> dishIds) {
        if (dishIds == null) {
            dishIds = new ArrayList<>();
        }
        PsiDishMenu menu = getOrCreateCurrentMenu();
        List<PsiDishMenuDish> currentDishList = menuDishMapper.selectList(new LambdaQueryWrapper<PsiDishMenuDish>()
                .eq(PsiDishMenuDish::getMenuId, menu.getId())
                .eq(PsiDishMenuDish::getDelFlag, 0)
                .and(w -> w.eq(PsiDishMenuDish::getIsHistory, "0").or().isNull(PsiDishMenuDish::getIsHistory)));
        Map<String, PsiDishMenuDish> currentDishMap = new LinkedHashMap<>();
        for (PsiDishMenuDish currentDish : currentDishList) {
            currentDishMap.put(currentDish.getDishId(), currentDish);
        }

        LinkedHashSet<String> selectedDishIds = new LinkedHashSet<>();
        for (String dishId : dishIds) {
            if (StringUtils.isBlank(dishId)) {
                continue;
            }
            PsiDishLibrary dish = dishLibraryMapper.queryById(dishId);
            if (dish != null && ("0".equals(dish.getStatus()) || currentDishMap.containsKey(dishId))) {
                selectedDishIds.add(dishId);
            }
        }
        if (!dishIds.isEmpty() && selectedDishIds.isEmpty()) {
            return "所选菜品不存在或已停用";
        }

        List<String> removeIds = new ArrayList<>();
        for (PsiDishMenuDish currentDish : currentDishList) {
            if (!selectedDishIds.contains(currentDish.getDishId())) {
                removeIds.add(currentDish.getId());
            }
        }
        if (!removeIds.isEmpty()) {
            menuDishMapper.deleteBatchIds(removeIds);
        }

        UserDTO userDto = SpringUtil.getBean(IUserApi.class).getByToken(TokenProvider.getCurrentToken());
        Date now = new Date();
        int sort = 0;
        for (String dishId : selectedDishIds) {
            PsiDishMenuDish currentDish = currentDishMap.get(dishId);
            if (currentDish != null) {
                PsiDishMenuDish update = new PsiDishMenuDish();
                update.setId(currentDish.getId());
                update.setSort(++sort);
                update.setUpdateById(userDto.getId());
                update.setUpdateTime(now);
                menuDishMapper.updateById(update);
                continue;
            }
            PsiDishLibrary dish = dishLibraryMapper.queryById(dishId);
            PsiDishMenuDish menuDish = new PsiDishMenuDish();
            menuDish.setId(UUID.randomUUID().toString().replace("-", ""));
            menuDish.setMenuId(menu.getId());
            menuDish.setDishId(dishId);
            menuDish.setSalePrice(dish.getSalePrice() == null ? BigDecimal.ZERO : dish.getSalePrice());
            menuDish.setSort(++sort);
            menuDish.setIsHistory("0");
            menuDish.setCreateById(userDto.getId());
            menuDish.setCreateTime(now);
            menuDish.setUpdateById(userDto.getId());
            menuDish.setUpdateTime(now);
            menuDish.setDelFlag(0);
            menuDishMapper.insert(menuDish);
        }
        return "菜单菜品保存成功";
    }

    public String updatePrice(PsiDishMenuDish info) {
        if (info == null || StringUtils.isBlank(info.getId())) {
            return "请选择要调整的菜品";
        }
        if (info.getSalePrice() == null || info.getSalePrice().compareTo(BigDecimal.ZERO) < 0) {
            return "菜单价格不能小于0";
        }
        UserDTO userDto = SpringUtil.getBean(IUserApi.class).getByToken(TokenProvider.getCurrentToken());
        PsiDishMenuDish update = new PsiDishMenuDish();
        update.setId(info.getId());
        update.setSalePrice(info.getSalePrice());
        update.setUpdateById(userDto.getId());
        update.setUpdateTime(new Date());
        menuDishMapper.updateById(update);
        return "价格保存成功";
    }

    public String deleteByIds(String ids) {
        if (StringUtils.isBlank(ids)) {
            return "请选择要删除的菜品";
        }
        menuDishMapper.deleteBatchIds(java.util.Arrays.asList(ids.split(",")));
        return "删除成功";
    }

    public String updateMenu(List<String> dishIds) {
        if (dishIds == null || dishIds.isEmpty()) {
            return "请至少选择一道菜品";
        }
        PsiDishMenu currentMenu = getOrCreateCurrentMenu();
        List<PsiDishMenuDish> currentDishList = menuDishMapper.selectList(new LambdaQueryWrapper<PsiDishMenuDish>()
                .eq(PsiDishMenuDish::getMenuId, currentMenu.getId())
                .eq(PsiDishMenuDish::getDelFlag, 0)
                .and(w -> w.eq(PsiDishMenuDish::getIsHistory, "0").or().isNull(PsiDishMenuDish::getIsHistory)));

        Map<String, PsiDishMenuDish> currentDishMap = new LinkedHashMap<>();
        for (PsiDishMenuDish currentDish : currentDishList) {
            currentDishMap.put(currentDish.getDishId(), currentDish);
        }

        List<PsiDishLibrary> selectedDishList = new ArrayList<>();
        for (String dishId : new LinkedHashSet<>(dishIds)) {
            if (StringUtils.isBlank(dishId)) {
                continue;
            }
            PsiDishLibrary dish = dishLibraryMapper.queryById(dishId);
            if (dish == null || (!"0".equals(dish.getStatus()) && !currentDishMap.containsKey(dishId))) {
                continue;
            }
            selectedDishList.add(dish);
        }
        if (selectedDishList.isEmpty()) {
            return "所选菜品不存在或已停用";
        }

        UserDTO userDto = SpringUtil.getBean(IUserApi.class).getByToken(TokenProvider.getCurrentToken());
        Date now = new Date();
        PsiDishMenu archiveMenu = new PsiDishMenu();
        archiveMenu.setId(currentMenu.getId());
        archiveMenu.setIsHistory("1");
        archiveMenu.setHistoryTime(now);
        archiveMenu.setUpdateById(userDto.getId());
        archiveMenu.setUpdateTime(now);
        psiDishMenuMapper.updateById(archiveMenu);

        PsiDishMenu newCurrentMenu = new PsiDishMenu();
        newCurrentMenu.setId(UUID.randomUUID().toString().replace("-", ""));
        newCurrentMenu.setIsHistory("0");
        newCurrentMenu.setCreateById(userDto.getId());
        newCurrentMenu.setCreateTime(now);
        newCurrentMenu.setUpdateById(userDto.getId());
        newCurrentMenu.setUpdateTime(now);
        newCurrentMenu.setDelFlag(0);
        psiDishMenuMapper.insert(newCurrentMenu);

        for (PsiDishMenuDish currentDish : currentDishList) {
            PsiDishMenuDish archiveDish = new PsiDishMenuDish();
            archiveDish.setId(currentDish.getId());
            archiveDish.setIsHistory("1");
            archiveDish.setHistoryTime(now);
            archiveDish.setUpdateById(userDto.getId());
            archiveDish.setUpdateTime(now);
            menuDishMapper.updateById(archiveDish);
        }

        int sort = 0;
        for (PsiDishLibrary selectedDish : selectedDishList) {
            PsiDishMenuDish currentDish = currentDishMap.get(selectedDish.getId());
            PsiDishMenuDish newCurrentDish = new PsiDishMenuDish();
            newCurrentDish.setId(UUID.randomUUID().toString().replace("-", ""));
            newCurrentDish.setMenuId(newCurrentMenu.getId());
            newCurrentDish.setDishId(selectedDish.getId());
            newCurrentDish.setSalePrice(currentDish == null
                    ? (selectedDish.getSalePrice() == null ? BigDecimal.ZERO : selectedDish.getSalePrice())
                    : currentDish.getSalePrice());
            newCurrentDish.setSort(++sort);
            newCurrentDish.setRemarks(currentDish == null ? null : currentDish.getRemarks());
            newCurrentDish.setIsHistory("0");
            newCurrentDish.setCreateById(userDto.getId());
            newCurrentDish.setCreateTime(now);
            newCurrentDish.setUpdateById(userDto.getId());
            newCurrentDish.setUpdateTime(now);
            newCurrentDish.setDelFlag(0);
            menuDishMapper.insert(newCurrentDish);
        }
        return "菜单更新成功";
    }

    public PsiDishMenuDish findCurrentByDishId(String dishId) {
        if (StringUtils.isBlank(dishId)) {
            return null;
        }
        return menuDishMapper.findCurrentByDishId(dishId);
    }

    private PsiDishMenu getOrCreateCurrentMenu() {
        PsiDishMenu menu = psiDishMenuMapper.selectOne(new LambdaQueryWrapper<PsiDishMenu>()
                .eq(PsiDishMenu::getDelFlag, 0)
                .and(w -> w.eq(PsiDishMenu::getIsHistory, "0").or().isNull(PsiDishMenu::getIsHistory))
                .orderByDesc(PsiDishMenu::getCreateTime)
                .last("limit 1"));
        if (menu != null) {
            return menu;
        }
        UserDTO userDto = SpringUtil.getBean(IUserApi.class).getByToken(TokenProvider.getCurrentToken());
        Date now = new Date();
        menu = new PsiDishMenu();
        menu.setId(UUID.randomUUID().toString().replace("-", ""));
        menu.setIsHistory("0");
        menu.setCreateById(userDto.getId());
        menu.setCreateTime(now);
        menu.setUpdateById(userDto.getId());
        menu.setUpdateTime(now);
        menu.setDelFlag(0);
        psiDishMenuMapper.insert(menu);
        return menu;
    }

    private QueryWrapper<PsiDishMenuDish> buildMenuDishQuery(PsiDishMenuDish info) {
        QueryWrapper<PsiDishMenuDish> wrapper = new QueryWrapper<>();
        if (info == null) {
            return wrapper;
        }
        if (StringUtils.isNotBlank(info.getDishName())) {
            wrapper.like("dl.dish_name", info.getDishName());
        }
        if (StringUtils.isNotBlank(info.getTypeId())) {
            wrapper.eq("dl.type_id", info.getTypeId());
        }
        if (StringUtils.isNotBlank(info.getStatus())) {
            wrapper.eq("dl.status", info.getStatus());
        }
        return wrapper;
    }

    private boolean existsCurrentMenuDish(String menuId, String dishId) {
        Integer count = menuDishMapper.selectCount(new LambdaQueryWrapper<PsiDishMenuDish>()
                .eq(PsiDishMenuDish::getMenuId, menuId)
                .eq(PsiDishMenuDish::getDishId, dishId)
                .eq(PsiDishMenuDish::getDelFlag, 0)
                .and(w -> w.eq(PsiDishMenuDish::getIsHistory, "0").or().isNull(PsiDishMenuDish::getIsHistory)));
        return count != null && count > 0;
    }
}
