package shop.alien.store.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import com.alibaba.nacos.common.utils.CollectionUtils;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import shop.alien.entity.result.R;
import shop.alien.entity.store.LifeGroupBuyThali;
import shop.alien.entity.store.LifeLikeRecord;
import shop.alien.entity.store.StoreImg;
import shop.alien.entity.store.StoreMenu;
import shop.alien.entity.store.vo.StoreMenuVo;
import shop.alien.mapper.LifeGroupBuyThaliMapper;
import shop.alien.mapper.LifeLikeRecordMapper;
import shop.alien.mapper.StoreMenuMapper;
import shop.alien.store.service.StoreImgService;
import shop.alien.store.service.StoreMenuService;
import shop.alien.store.util.StoreLikeRecordIdentityHelper;
import shop.alien.store.util.StoreLikeRecordIdentityHelper.StoreLikerScope;

import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * 二期-门店推荐 服务实现类
 *
 * @author ssk
 * @since 2024-12-05
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class StoreMenuServiceImpl extends ServiceImpl<StoreMenuMapper, StoreMenu> implements StoreMenuService {

    private final StoreMenuMapper storeMenuMapper;

    private final LifeLikeRecordMapper lifeLikeRecordMapper;

    private final StoreLikeRecordIdentityHelper lifeLikeIdentityHelper;

    private final StoreImgService storeImgService;

    private final LifeGroupBuyThaliMapper lifeGroupBuyThaliMapper;

    /**
     * 菜品类型：非推荐
     */
    private static final Integer DISH_TYPE_NON_RECOMMEND = 0;

    /**
     * 菜品类型：推荐
     */
    private static final Integer DISH_TYPE_RECOMMEND = 1;

    /**
     * 点赞状态：未点赞
     */
    private static final Integer LIKE_STATUS_NO = 0;

    /**
     * 点赞状态：已点赞
     */
    private static final Integer LIKE_STATUS_YES = 1;

    /**
     * 获取门店菜单
     *
     * @param storeId      门店id
     * @param dishType     菜品类型, 0:非推荐, 1:推荐
     * @param phoneId      消息标识
     * @param dishMenuType 菜单类型：1-菜单，2-酒水
     * @return list
     */
    @Override
    public List<StoreMenuVo> getStoreMenu(Integer storeId, Integer dishType, String phoneId, Integer dishMenuType) {
        // 查询菜单列表
        Integer queryDishType = (dishType != null && dishType == 0) ? null : dishType;
        List<StoreMenuVo> menuList = storeMenuMapper.getStoreMenuInfoList(storeId, queryDishType, dishMenuType);

        // 如果是推荐菜且有用户标识，批量查询点赞状态
        if (dishType != null && dishType == 1 && StringUtils.isNotEmpty(phoneId)
                && CollectionUtils.isNotEmpty(menuList)) {
            // 将菜单ID转换为String集合，用于查询点赞记录
            Set<String> menuIdStrSet = menuList.stream()
                    .map(item -> String.valueOf(item.getId()))
                    .collect(Collectors.toSet());

            // 批量查询点赞记录
            StoreLikerScope likerScope = lifeLikeIdentityHelper.resolveFromDianzanId(phoneId);
            LambdaQueryWrapper<LifeLikeRecord> likeQuery = new LambdaQueryWrapper<>();
            likeQuery.in(LifeLikeRecord::getHuifuId, menuIdStrSet);
            lifeLikeIdentityHelper.applyLikerFilter(likeQuery, likerScope);
            List<LifeLikeRecord> likeRecordList = lifeLikeRecordMapper.selectList(likeQuery);

            // 构建已点赞的菜单ID集合
            Set<String> likedMenuIdSet = likeRecordList.stream()
                    .map(LifeLikeRecord::getHuifuId)
                    .collect(Collectors.toSet());

            // 设置点赞状态
            menuList.forEach(item -> {
                String menuIdStr = String.valueOf(item.getId());
                if (likedMenuIdSet.contains(menuIdStr)) {
                    item.setIsLike(1);
                } else {
                    item.setIsLike(0);
                }
            });
        }

        // 按排序字段排序
        return menuList.stream()
                .sorted(Comparator.comparing(StoreMenuVo::getSort))
                .collect(Collectors.toList());
    }

    /**
     * 获取菜品详情
     *
     * @param id 菜品id
     * @return StoreMenuVo
     */
    @Override
    public StoreMenuVo getMenuInfo(Integer id) {
        return storeMenuMapper.getMenuInfo(id);
    }

    /**
     * 新增或修改门店菜品
     *
     * @param storeMenu
     * @return
     */
    @Override
    public R<String> saveOrUpdateMenu(StoreMenu storeMenu) {
        boolean flag = false;
        LambdaQueryWrapper<StoreMenu> storeMenuLambdaQueryWrapper = new LambdaQueryWrapper<>();
        //修改菜品
        if (storeMenu.getId() != null) {
            flag = this.updateById(storeMenu);
            if (!flag) {
                log.error("菜单修改失败");
                return R.fail("菜单修改失败");
            }
            return R.success("菜单修改成功");
        } else {//新增菜品
            if (StringUtils.isEmpty(storeMenu.getDishName())) {
                return R.fail("请输入菜品名称");
            }
            storeMenuLambdaQueryWrapper.eq(StoreMenu::getStoreId, storeMenu.getStoreId());
            List<StoreMenu> menuList = this.list(storeMenuLambdaQueryWrapper);
            if (CollectionUtil.isNotEmpty(menuList)) {
                int maxSort = menuList.stream().map(StoreMenu::getSort).reduce(Integer::max).get();
                storeMenu.setSort(maxSort + 1);
            } else {
                storeMenu.setSort(1);
            }
            //保存菜品
            flag = this.save(storeMenu);
            if (!flag) {
                return R.fail("菜品新增失败");
            }
        }
        return R.success("新增菜品成功");
    }

    /**
     * 新增或修改门店菜品new
     *
     * @param storeMenuVo
     * @return
     */
    @Override
    public R<String> saveOrUpdateMenus(StoreMenuVo storeMenuVo) {
        boolean flag = false;
        LambdaQueryWrapper<StoreMenu> storeMenuLambdaQueryWrapper = new LambdaQueryWrapper<>();
        int imgId = 0;
        if (storeMenuVo.getImgId() == null || storeMenuVo.getImgId() == 0) {
            StoreImg storeImg = new StoreImg();
            storeImg.setStoreId(storeMenuVo.getStoreId());
            storeImg.setImgType(7);
            storeImg.setImgUrl(storeMenuVo.getImgUrl());
            storeImg.setImgDescription(storeMenuVo.getDishName());
            storeImgService.saveOrUpdate(storeImg);
            imgId = storeImg.getId();
        } else {
            imgId = storeMenuVo.getImgId();
        }

        // 封装storeMenu参数
        StoreMenu storeMenu = new StoreMenu();
        BeanUtils.copyProperties(storeMenuVo, storeMenu);
        storeMenu.setImgId(imgId);

        //修改菜品
        if (storeMenu.getId() != null) {
            flag = this.updateById(storeMenu);
            if (!flag) {
                log.error("菜单修改失败");
                return R.fail("菜单修改失败");
            }
            return R.success("菜单修改成功");
        } else {
            //新增菜品
            // 校验菜品参数
            if (StringUtils.isEmpty(storeMenu.getDishName())) {
                return R.fail("请输入菜品名称");
            }

            storeMenuLambdaQueryWrapper.eq(StoreMenu::getStoreId, storeMenu.getStoreId());
            List<StoreMenu> menuList = this.list(storeMenuLambdaQueryWrapper);
            if (CollectionUtil.isNotEmpty(menuList)) {
                int maxSort = menuList.stream().map(StoreMenu::getSort).reduce(Integer::max).get();
                storeMenu.setSort(maxSort + 1);
            } else {
                storeMenu.setSort(1);
            }
            //保存菜品
            flag = this.save(storeMenu);
            if (!flag) {
                return R.fail("菜品新增失败");
            }
        }
        return R.success("新增菜品成功");
    }

    /**
     * 菜品排序信息
     *
     * @param storeMenuVo
     * @return
     */
    @Override
    public Boolean getSortMenuInfo(StoreMenuVo storeMenuVo) {
        boolean flag = false;
        if (CollectionUtil.isNotEmpty(storeMenuVo.getSortList())) {
            for (int i = 0; i < storeMenuVo.getSortList().size(); i++) {
                LambdaQueryWrapper<StoreMenu> lambdaQueryWrapper = new LambdaQueryWrapper();
                lambdaQueryWrapper.eq(StoreMenu::getId, storeMenuVo.getSortList().get(i).getId());
                StoreMenu storeMenu = this.getOne(lambdaQueryWrapper);
                storeMenu.setSort(i + 1);
                flag = this.updateById(storeMenu);
            }
        }
        return flag;
    }

    @Override
    public Boolean saveMenuSort(List<StoreMenu> storeMenuList) {
        return this.updateBatchById(storeMenuList);
    }

    /**
     * 删除菜品或推荐菜 根据类型区分
     *
     * @param ids
     * @param dishType 0:菜品 1:推荐菜
     * @return
     */
    @Override
    public R deleteMenu(List<Integer> ids, int dishType) {
        QueryWrapper<StoreMenu> queryWrapperMenu = new QueryWrapper<>();
        boolean flag = false;
        if (dishType == 0) {
            List<LifeGroupBuyThali> lifeGroupBuyThaliList = lifeGroupBuyThaliMapper.selectList(new LambdaQueryWrapper<LifeGroupBuyThali>().in(LifeGroupBuyThali::getDetailId, ids));
            if (CollectionUtil.isNotEmpty(lifeGroupBuyThaliList)) {
                return R.fail("当前菜品存在于团购中，不可删除");
            }
            flag = this.removeByIds(ids);
        } else {
            queryWrapperMenu.in("id", ids);
            List<StoreMenu> storeMenuList = baseMapper.selectList(queryWrapperMenu);
            storeMenuList.forEach(item -> {
                item.setDishType(0);
                this.updateById(item);
            });
            flag = true;
        }
        if (!flag) {
            return R.fail("删除失败");
        }
        return R.success("删除成功");
    }

    @Override
    public StoreMenuVo getMenuCountByStoreId(int storeId) {
        StoreMenuVo storeMenuVo = new StoreMenuVo();
        LambdaUpdateWrapper<StoreMenu> updateWrapper = new LambdaUpdateWrapper<>();
        updateWrapper.eq(StoreMenu::getStoreId, storeId);
        updateWrapper.eq(StoreMenu::getDeleteFlag, 0);
        List<StoreMenu> storeMenuList = storeMenuMapper.selectList(updateWrapper);
        if (CollectionUtils.isNotEmpty(storeMenuList)) {
            storeMenuVo.setMenuCount(storeMenuList.size());
            Map<Integer, List<StoreMenu>> groupByDishType = storeMenuList.stream()
                    .collect(Collectors.groupingBy(StoreMenu::getDishType));
            List<StoreMenu> suggestList = groupByDishType.get(1);
            if (CollectionUtils.isNotEmpty(suggestList)) {
                storeMenuVo.setSuggestCount(suggestList.size());
            } else {
                storeMenuVo.setSuggestCount(0);
            }
        } else {
            storeMenuVo.setMenuCount(0);
            storeMenuVo.setSuggestCount(0);
        }
        return storeMenuVo;
    }

    /**
     * 获取用户对该菜品是否点赞
     *
     * @param userId 用户id
     * @param menuId 菜品id
     * @return boolean
     */
    @Override
    public boolean getMenuLikeStatus(String userId, Integer menuId) {
        StoreLikerScope likerScope = lifeLikeIdentityHelper.resolveFromDianzanId(userId);
        LambdaQueryWrapper<LifeLikeRecord> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(LifeLikeRecord::getHuifuId, menuId).eq(LifeLikeRecord::getDeleteFlag, 0);
        lifeLikeIdentityHelper.applyLikerFilter(wrapper, likerScope);
        return lifeLikeRecordMapper.selectCount(wrapper) > 0;
    }


    /**
     * 获取门店菜单（客户端）
     * <p>
     * 根据门店ID查询菜单列表，支持按菜品类型和菜单类型筛选。
     * 当查询推荐菜且提供用户手机号时，会批量查询并设置用户的点赞状态。
     * 最终结果按排序字段升序排列。
     * </p>
     *
     * @param storeId      门店ID，必填，必须大于0
     * @param dishType     菜品类型，可选，0:全部, 1:推荐
     * @param phoneId      用户手机号，可选，用于查询用户对推荐菜的点赞状态
     * @param dishMenuType 菜单类型，可选，1-菜单，2-酒水
     * @return 菜单列表，按排序字段升序排列，如果查询结果为空则返回空列表
     */
    @Override
    public Map<String, Object> getClientMenuByStoreId(Integer storeId, Integer dishType, String phoneId, Integer dishMenuType) {
        log.info("开始获取用户端菜单，门店ID：{}，菜品类型：{}，用户手机号：{}，菜单类型：{}",
                storeId, dishType, phoneId, dishMenuType);

        // 参数校验
        if (storeId == null || storeId <= 0) {
            log.warn("获取用户端菜单失败，门店ID无效：{}", storeId);
            throw new IllegalArgumentException("门店ID不能为空且必须大于0");
        }

        // 先查询该门店的所有菜单数据（不应用筛选条件），用于统计
        List<StoreMenuVo> allMenuList = storeMenuMapper.getClientMenuByStoreId(storeId, null, null);

        // 按照六种组合进行分组统计（基于所有菜单数据，不受筛选条件影响）：
        // 1. dish_menu_type = 1（菜单），dish_type = 0（全部）
        // 2. dish_menu_type = 1（菜单），dish_type = 1（推荐）
        // 3. dish_menu_type = 2（酒水），dish_type = 0（全部）
        // 4. dish_menu_type = 2（酒水），dish_type = 1（推荐）
        // 5. dish_menu_type = 1和2（全部），dish_type = 0（全部）
        // 6. dish_menu_type = 1和2（全部），dish_type = 1（推荐）
        Map<String, Integer> countMap = new HashMap<>();

        if (CollectionUtils.isNotEmpty(allMenuList)) {
            // 统计：dish_menu_type = 1（菜单），dish_type = 1（推荐）
            long menuRecommendCount = allMenuList.stream()
                    .filter(item -> "1".equals(item.getDishMenuType())
                            && DISH_TYPE_RECOMMEND.equals(item.getDishType()))
                    .count();
            countMap.put("menu_recommend", (int) menuRecommendCount);

            // 统计：dish_menu_type = 1（菜单），dish_type = 0（全部）
            long menuAllCount = allMenuList.stream()
                    .filter(item -> "1".equals(item.getDishMenuType())
                            && (item.getDishType() == null || DISH_TYPE_NON_RECOMMEND.equals(item.getDishType())))
                    .count();
            countMap.put("menu_all", (int) menuAllCount + (int) menuRecommendCount);

            // 统计：dish_menu_type = 2（酒水），dish_type = 1（推荐）
            long drinkRecommendCount = allMenuList.stream()
                    .filter(item -> "2".equals(item.getDishMenuType())
                            && DISH_TYPE_RECOMMEND.equals(item.getDishType()))
                    .count();
            countMap.put("drink_recommend", (int) drinkRecommendCount);

            // 统计：dish_menu_type = 2（酒水），dish_type = 0（全部）
            long drinkAllCount = allMenuList.stream()
                    .filter(item -> "2".equals(item.getDishMenuType())
                            && (item.getDishType() == null || DISH_TYPE_NON_RECOMMEND.equals(item.getDishType())))
                    .count();
            countMap.put("drink_all", (int) drinkAllCount + (int) drinkRecommendCount);

            // 新增统计：dist_type 为全部，dish_menu_type 为 1 和 2（菜单和酒水都包含）
            int allMenuAllCount = countMap.get("menu_all") + countMap.get("drink_all");
            countMap.put("all_menu_all", allMenuAllCount);

            // 新增统计：dist_type 为 1（推荐），dish_menu_type 为 1 和 2（菜单和酒水都包含）
            int allMenuRecommendCount = countMap.get("menu_recommend") + countMap.get("drink_recommend");
            countMap.put("all_menu_recommend", allMenuRecommendCount);
        } else {
            // 如果没有数据，返回0
            countMap.put("menu_all", 0);
            countMap.put("menu_recommend", 0);
            countMap.put("drink_all", 0);
            countMap.put("drink_recommend", 0);
            countMap.put("all_menu_all", 0);
            countMap.put("all_menu_recommend", 0);
        }

        // 处理菜品类型参数：当dishType为0时，转换为null以查询所有类型
        Integer queryDishType = (dishType != null && DISH_TYPE_NON_RECOMMEND.equals(dishType)) ? null : dishType;

        // 根据筛选条件查询菜单列表（用于返回给前端）
        List<StoreMenuVo> menuList = storeMenuMapper.getClientMenuByStoreId(storeId, queryDishType, dishMenuType);

        // 如果查询结果为空，返回空列表但保留统计信息
        if (CollectionUtils.isEmpty(menuList)) {
            log.info("获取用户端菜单完成，门店ID：{}，未查询到符合条件的菜单数据", storeId);
            Map<String, Object> result = new HashMap<>();
            result.put("list", Collections.emptyList());
            result.put("count", countMap);
            return result;
        }

        log.info("获取用户端菜单，门店ID：{}，查询到符合条件的菜单数量：{}", storeId, menuList.size());

        // 如果是推荐菜且有用户标识，批量查询并设置点赞状态
        if (DISH_TYPE_RECOMMEND.equals(dishType) && StringUtils.isNotEmpty(phoneId)) {
            setLikeStatusForMenuList(menuList, phoneId);
        } else {
            // 非推荐菜或未提供用户手机号时，设置默认未点赞状态
            menuList.forEach(item -> item.setIsLike(LIKE_STATUS_NO));
        }

        // 按排序字段升序排序
        List<StoreMenuVo> sortedMenuList = menuList.stream()
                .sorted(Comparator.comparing(StoreMenuVo::getSort, Comparator.nullsLast(Integer::compareTo)))
                .collect(Collectors.toList());

        // 构建返回结果
        Map<String, Object> result = new HashMap<>();
        result.put("list", sortedMenuList);
        result.put("count", countMap);

        log.info("获取用户端菜单完成，门店ID：{}，返回菜单数量：{}，统计信息：菜单-全部={}，菜单-推荐={}，酒水-全部={}，酒水-推荐={}，全部-全部={}，全部-推荐={}",
                storeId, sortedMenuList.size(),
                countMap.get("menu_all"), countMap.get("menu_recommend"),
                countMap.get("drink_all"), countMap.get("drink_recommend"),
                countMap.get("all_menu_all"), countMap.get("all_menu_recommend"));

        return result;
    }

    /**
     * 批量设置菜单的点赞状态
     * <p>
     * 根据用户手机号和菜单ID列表，批量查询点赞记录，并设置每个菜单的点赞状态
     * </p>
     *
     * @param menuList 菜单列表
     * @param phoneId  用户手机号
     */
    private void setLikeStatusForMenuList(List<StoreMenuVo> menuList, String phoneId) {
        if (CollectionUtils.isEmpty(menuList) || StringUtils.isEmpty(phoneId)) {
            return;
        }

        log.debug("开始批量查询点赞状态，用户手机号：{}，菜单数量：{}", phoneId, menuList.size());

        // 将菜单ID转换为String集合，用于查询点赞记录
        Set<String> menuIdStrSet = menuList.stream()
                .map(item -> String.valueOf(item.getId()))
                .filter(id -> id != null && !"null".equals(id))
                .collect(Collectors.toSet());

        if (menuIdStrSet.isEmpty()) {
            log.warn("菜单ID集合为空，无法查询点赞状态");
            menuList.forEach(item -> item.setIsLike(LIKE_STATUS_NO));
            return;
        }

        // 批量查询点赞记录
        StoreLikerScope likerScope = lifeLikeIdentityHelper.resolveFromDianzanId(phoneId);
        LambdaQueryWrapper<LifeLikeRecord> likeQuery = new LambdaQueryWrapper<>();
        likeQuery.eq(LifeLikeRecord::getDeleteFlag, 0)
                .in(LifeLikeRecord::getHuifuId, menuIdStrSet);
        lifeLikeIdentityHelper.applyLikerFilter(likeQuery, likerScope);
        List<LifeLikeRecord> likeRecordList = lifeLikeRecordMapper.selectList(likeQuery);

        // 构建已点赞的菜单ID集合
        Set<String> likedMenuIdSet = likeRecordList.stream()
                .map(LifeLikeRecord::getHuifuId)
                .filter(id -> id != null)
                .collect(Collectors.toSet());

        log.debug("查询到点赞记录数量：{}，已点赞菜单数量：{}",
                likeRecordList.size(), likedMenuIdSet.size());

        // 设置点赞状态
        menuList.forEach(item -> {
            if (item.getId() == null) {
                item.setIsLike(LIKE_STATUS_NO);
                return;
            }

            String menuIdStr = String.valueOf(item.getId());
            if (likedMenuIdSet.contains(menuIdStr)) {
                item.setIsLike(LIKE_STATUS_YES);
            } else {
                item.setIsLike(LIKE_STATUS_NO);
            }
        });
    }

    /**
     * 获取菜品详情
     *
     * @param id 菜品id
     * @return StoreMenuVo
     */
    @Override
    public StoreMenuVo getClientMenuInfoById(Integer id, String phoneId) {
        StoreMenuVo storeMenuVo = storeMenuMapper.getClientMenuInfoById(id);
        if(StringUtils.isNotEmpty(phoneId)){
            // 批量查询点赞记录
            StoreLikerScope likerScope = lifeLikeIdentityHelper.resolveFromDianzanId(phoneId);
            LambdaQueryWrapper<LifeLikeRecord> likeQuery = new LambdaQueryWrapper<>();
            likeQuery.eq(LifeLikeRecord::getDeleteFlag, 0)
                    .eq(LifeLikeRecord::getHuifuId, storeMenuVo.getId());
            lifeLikeIdentityHelper.applyLikerFilter(likeQuery, likerScope);
            int likeCount = lifeLikeRecordMapper.selectCount(likeQuery);
            if(likeCount > 0){
                storeMenuVo.setIsLike(1);
            }
        } else {
            storeMenuVo.setLikeCount(0);
            storeMenuVo.setIsLike(0);
        }

        return storeMenuVo;
    }
}
