package shop.alien.dining.service.impl;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import shop.alien.entity.store.StoreCuisine;
import shop.alien.entity.store.StoreCuisineCategory;
import shop.alien.entity.store.StoreInfo;
import shop.alien.entity.store.StoreTable;
import shop.alien.entity.store.dto.StoreInfoWithHomepageCuisinesDTO;
import shop.alien.entity.store.vo.CategoryWithCuisinesVO;
import shop.alien.mapper.StoreCuisineCategoryMapper;
import shop.alien.mapper.StoreCuisineMapper;
import shop.alien.mapper.StoreInfoMapper;
import shop.alien.mapper.StoreTableMapper;
import shop.alien.dining.service.StoreInfoService;
import org.apache.commons.lang3.StringUtils;

import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

/**
 * 门店信息查询服务实现类
 *
 * @author system
 * @since 2025-02-02
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class StoreInfoServiceImpl implements StoreInfoService {

    private final StoreTableMapper storeTableMapper;
    private final StoreCuisineCategoryMapper storeCuisineCategoryMapper;
    private final StoreCuisineMapper storeCuisineMapper;
    private final StoreInfoMapper storeInfoMapper;

    @Override
    public List<StoreTable> getTablesByStoreId(Integer storeId) {
        log.info("根据门店ID查询桌号列表, storeId={}", storeId);
        
        LambdaQueryWrapper<StoreTable> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(StoreTable::getStoreId, storeId);
        wrapper.eq(StoreTable::getDeleteFlag, 0);
        wrapper.orderByAsc(StoreTable::getTableNumber);
        
        return storeTableMapper.selectList(wrapper);
    }

    @Override
    public List<StoreCuisineCategory> getCategoriesByStoreId(Integer storeId) {
        log.info("根据门店ID查询菜品种类列表, storeId={}", storeId);
        
        LambdaQueryWrapper<StoreCuisineCategory> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(StoreCuisineCategory::getStoreId, storeId);
        wrapper.eq(StoreCuisineCategory::getDeleteFlag, 0);
        wrapper.eq(StoreCuisineCategory::getStatus, 1); // 只查询启用的分类
        wrapper.orderByAsc(StoreCuisineCategory::getSort); // 按排序字段排序
        
        return storeCuisineCategoryMapper.selectList(wrapper);
    }

    @Override
    public List<StoreCuisine> getCuisinesByCategoryId(Integer categoryId) {
        log.info("根据菜品种类ID查询菜品信息列表, categoryId={}", categoryId);
        
        // 先查询分类信息，获取 storeId
        StoreCuisineCategory category = storeCuisineCategoryMapper.selectById(categoryId);
        if (category == null) {
            log.warn("菜品种类不存在, categoryId={}", categoryId);
            return new java.util.ArrayList<>();
        }
        
        // 查询该门店下所有上架的菜品（与 getCategoriesWithCuisinesByStoreId 中 cuisines 查询条件、排序一致）
        LambdaQueryWrapper<StoreCuisine> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(StoreCuisine::getStoreId, category.getStoreId());
        wrapper.eq(StoreCuisine::getDeleteFlag, 0);
        wrapper.eq(StoreCuisine::getShelfStatus, 1); // 只查询上架的菜品
        wrapper.orderByAsc(StoreCuisine::getId); // 与 categories-with-cuisines 中 cuisines 顺序一致
        
        List<StoreCuisine> allCuisines = storeCuisineMapper.selectList(wrapper);
        
        // 过滤出包含该分类ID的菜品
        // categoryIds 是 JSON 数组格式，如：[1,2,3]
        return allCuisines.stream()
                .filter(cuisine -> {
                    String categoryIdsStr = cuisine.getCategoryIds();
                    if (StringUtils.isBlank(categoryIdsStr)) {
                        return false;
                    }
                    try {
                        // 解析 JSON 数组
                        List<Integer> categoryIds = JSON.parseArray(categoryIdsStr, Integer.class);
                        return categoryIds != null && categoryIds.contains(categoryId);
                    } catch (Exception e) {
                        log.warn("解析菜品分类IDs失败, cuisineId={}, categoryIds={}, error={}", 
                                cuisine.getId(), categoryIdsStr, e.getMessage());
                        // 如果解析失败，使用简单的字符串匹配作为降级方案
                        return categoryIdsStr.contains(String.valueOf(categoryId));
                    }
                })
                .collect(Collectors.toList());
    }

    @Override
    public List<CategoryWithCuisinesVO> getCategoriesWithCuisinesByStoreId(Integer storeId, String keyword) {
        log.info("根据门店ID查询菜品种类及下属菜品, storeId={}, keyword={}", storeId, keyword);
        List<StoreCuisineCategory> categories = getCategoriesByStoreId(storeId);
        if (categories == null || categories.isEmpty()) {
            return new ArrayList<>();
        }
        // 与 getCuisinesByCategoryId 相同的查询条件与排序，保证 cuisines 字段与 /store/info/cuisines 一致
        LambdaQueryWrapper<StoreCuisine> cuisineWrapper = new LambdaQueryWrapper<>();
        cuisineWrapper.eq(StoreCuisine::getStoreId, storeId);
        cuisineWrapper.eq(StoreCuisine::getDeleteFlag, 0);
        cuisineWrapper.eq(StoreCuisine::getShelfStatus, 1);
        cuisineWrapper.orderByAsc(StoreCuisine::getId);
        List<StoreCuisine> allCuisines = storeCuisineMapper.selectList(cuisineWrapper);
        if (allCuisines == null) {
            allCuisines = new ArrayList<>();
        }
        boolean filterByName = StringUtils.isNotBlank(keyword);
        String keywordLower = filterByName ? keyword.trim().toLowerCase() : null;
        List<CategoryWithCuisinesVO> result = new ArrayList<>();
        for (StoreCuisineCategory category : categories) {
            Integer categoryId = category.getId();
            List<StoreCuisine> cuisines = allCuisines.stream()
                    .filter(c -> belongsToCategory(c, categoryId))
                    .filter(c -> !filterByName || (c.getName() != null && c.getName().toLowerCase().contains(keywordLower)))
                    .collect(Collectors.toList());
            result.add(new CategoryWithCuisinesVO(category, cuisines));
        }
        return result;
    }

    private boolean belongsToCategory(StoreCuisine cuisine, Integer categoryId) {
        String categoryIdsStr = cuisine.getCategoryIds();
        if (StringUtils.isBlank(categoryIdsStr)) {
            return false;
        }
        try {
            List<Integer> categoryIds = JSON.parseArray(categoryIdsStr, Integer.class);
            return categoryIds != null && categoryIds.contains(categoryId);
        } catch (Exception e) {
            return categoryIdsStr.contains(String.valueOf(categoryId));
        }
    }

    @Override
    public boolean deleteCategory(Integer categoryId) {
        log.info("删除菜品种类（仅解除绑定+逻辑删分类）, categoryId={}", categoryId);
        if (categoryId == null) {
            log.warn("删除菜品种类失败：分类ID为空");
            return false;
        }
        StoreCuisineCategory category = storeCuisineCategoryMapper.selectById(categoryId);
        if (category == null) {
            log.warn("删除菜品种类失败：分类不存在, categoryId={}", categoryId);
            return false;
        }
        Integer storeId = category.getStoreId();
        // 1. 解除绑定：将该分类ID从所有关联菜品的 category_ids 中移除，价目表菜品其它字段不变
        LambdaQueryWrapper<StoreCuisine> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(StoreCuisine::getStoreId, storeId);
        wrapper.eq(StoreCuisine::getDeleteFlag, 0);
        List<StoreCuisine> allCuisines = storeCuisineMapper.selectList(wrapper);
        if (allCuisines != null) {
            for (StoreCuisine cuisine : allCuisines) {
                if (!belongsToCategory(cuisine, categoryId)) {
                    continue;
                }
                String newCategoryIds = removeCategoryIdFromJson(cuisine.getCategoryIds(), categoryId);
                cuisine.setCategoryIds(newCategoryIds);
                storeCuisineMapper.updateById(cuisine);
            }
        }
        // 2. 逻辑删除菜品种类
        storeCuisineCategoryMapper.deleteById(categoryId);
        log.info("删除菜品种类完成, categoryId={}", categoryId);
        return true;
    }

    /** 从 categoryIds 的 JSON 数组中移除指定 categoryId，返回新 JSON 字符串；若为空则返回 null */
    private String removeCategoryIdFromJson(String categoryIdsStr, Integer categoryId) {
        if (StringUtils.isBlank(categoryIdsStr)) {
            return null;
        }
        try {
            List<Integer> list = JSON.parseArray(categoryIdsStr, Integer.class);
            if (list == null || list.isEmpty()) {
                return null;
            }
            list.remove(categoryId);
            if (list.isEmpty()) {
                return null;
            }
            return JSON.toJSONString(list);
        } catch (Exception e) {
            log.warn("解析 categoryIds 失败, categoryIdsStr={}, 原样返回", categoryIdsStr, e);
            return categoryIdsStr;
        }
    }

    @Override
    public StoreInfoWithHomepageCuisinesDTO getStoreInfoWithHomepageCuisines(Integer storeId) {
        log.info("根据商铺ID查询店铺信息和首页展示美食价目表, storeId={}", storeId);
        
        // 1. 查询店铺信息
        StoreInfo storeInfo = storeInfoMapper.selectById(storeId);
        if (storeInfo == null) {
            throw new RuntimeException("店铺不存在");
        }
        
        // 2. 查询首页展示的美食价目表（is_homepage_display = 1，上架状态 = 1，审核通过 = 1）
        LambdaQueryWrapper<StoreCuisine> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(StoreCuisine::getStoreId, storeId);
        wrapper.eq(StoreCuisine::getDeleteFlag, 0);
        wrapper.eq(StoreCuisine::getIsHomepageDisplay, 1); // 首页展示
        wrapper.eq(StoreCuisine::getShelfStatus, 1); // 上架状态
        wrapper.eq(StoreCuisine::getStatus, 1); // 审核通过
        wrapper.orderByDesc(StoreCuisine::getCreatedTime); // 按创建时间倒序
        
        List<StoreCuisine> homepageCuisines = storeCuisineMapper.selectList(wrapper);
        if (homepageCuisines == null) {
            homepageCuisines = new ArrayList<>();
        }
        
        // 3. 构建返回DTO
        StoreInfoWithHomepageCuisinesDTO dto = new StoreInfoWithHomepageCuisinesDTO();
        dto.setStoreInfo(storeInfo);
        dto.setHomepageCuisines(homepageCuisines);
        
        log.info("查询完成, storeId={}, 首页展示美食数量={}", storeId, homepageCuisines.size());
        return dto;
    }
}
