package shop.alien.store.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.RequiredArgsConstructor;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import shop.alien.entity.store.StoreCuisine;
import shop.alien.entity.store.StoreCuisineCombo;
import shop.alien.entity.store.StoreInfo;
import shop.alien.entity.store.dto.CategoryGroupDto;
import shop.alien.entity.store.dto.CuisineComboDto;
import shop.alien.entity.store.dto.CuisineItemDto;
import shop.alien.entity.store.dto.CuisineTypeResponseDto;
import shop.alien.entity.store.StoreCuisineCategory;
import shop.alien.mapper.StoreCuisineMapper;
import shop.alien.mapper.StoreInfoMapper;
import shop.alien.store.service.StoreCuisineComboService;
import shop.alien.store.service.StoreCuisineCategoryService;
import shop.alien.store.service.StoreCuisineService;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * 美食价目表 服务实现类
 *
 * @author auto-generated
 * @since 2025-01-01
 */
@Service
@RequiredArgsConstructor
@Transactional(rollbackFor = Exception.class)
public class StoreCuisineServiceImpl extends ServiceImpl<StoreCuisineMapper, StoreCuisine> implements StoreCuisineService {

    private final StoreCuisineComboService storeCuisineComboService;

    private final ObjectMapper objectMapper = new ObjectMapper();

    private final StoreInfoMapper storeInfoMapper;

    private final StoreCuisineCategoryService storeCuisineCategoryService;

    /**
     * 新增美食（单品或套餐）
     */
    @Override
    public boolean addCuisineCombo(CuisineComboDto cuisineComboDto) {
        // 验证：如果需要预约，预约规则必填
        if (cuisineComboDto.getNeedReserve() != null && cuisineComboDto.getNeedReserve() == 1) {
            if (StringUtils.isBlank(cuisineComboDto.getReserveRule())) {
                throw new IllegalArgumentException("需要预约时，预约规则不能为空");
            }
        }
        
        // 验证字段长度
        validateCuisineFields(cuisineComboDto);
        
        // 1. 保存主表信息到 store_cuisine
        StoreCuisine cuisine = new StoreCuisine();
        BeanUtils.copyProperties(cuisineComboDto, cuisine);
        // 处理分类ID：将分类ID数组转换为JSON字符串格式存储
        cuisine.setCategoryIds(formatCategoryIds(cuisineComboDto.getCategoryIds()));
        save(cuisine);

        // 单品：只写主表，不写中间表
        if (cuisineComboDto.getCuisineType() == 1) {
            return true;
        }

        // 2. 套餐：解析 JSON，生成中间表记录并批量插入
        Integer comboId = cuisine.getId();
        List<StoreCuisineCombo> comboList = buildComboListFromJson(comboId, cuisineComboDto.getGroupJson());
        return storeCuisineComboService.saveBatch(comboList);
    }

    /**
     * 修改美食（单品或套餐）
     */
    @Override
    public boolean updateCuisineCombo(CuisineComboDto cuisineComboDto) {
        // 验证：如果需要预约，预约规则必填
        if (cuisineComboDto.getNeedReserve() != null && cuisineComboDto.getNeedReserve() == 1) {
            if (StringUtils.isBlank(cuisineComboDto.getReserveRule())) {
                throw new IllegalArgumentException("需要预约时，预约规则不能为空");
            }
        }
        
        // 验证字段长度
        validateCuisineFields(cuisineComboDto);
        
        Integer comboId = cuisineComboDto.getId();

        // 1. 更新主表信息
        StoreCuisine cuisine = new StoreCuisine();
        BeanUtils.copyProperties(cuisineComboDto, cuisine);
        cuisine.setId(comboId);
        // 处理分类ID：将分类ID数组转换为JSON字符串格式存储
        cuisine.setCategoryIds(formatCategoryIds(cuisineComboDto.getCategoryIds()));
        updateById(cuisine);

        // 单品：只更新主表即可
        if (cuisineComboDto.getCuisineType() == 1) {
            return true;
        }

        // 2. 套餐：删除旧的中间表记录（逻辑删除）
        LambdaQueryWrapper<StoreCuisineCombo> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(StoreCuisineCombo::getCid, comboId);
        storeCuisineComboService.remove(wrapper);

        // 3. 重新解析 JSON，生成新的中间表记录并批量插入
        List<StoreCuisineCombo> comboList = buildComboListFromJson(comboId, cuisineComboDto.getGroupJson());
        return storeCuisineComboService.saveBatch(comboList);
    }

    /**
     * 获取所有单品名称（cuisine_type = 1），用于添加套餐
     * 
     * @param storeId 门店ID
     * @return 已上架且审核通过的单品列表
     */
    @Override
    public List<StoreCuisine> getSingleName(Integer storeId) {
        return lambdaQuery()
                .eq(StoreCuisine::getStoreId, storeId) // 根据门店ID查询
                .eq(StoreCuisine::getCuisineType, 1) // 类型为单品
                .eq(StoreCuisine::getShelfStatus, 1) // 上架
                .eq(StoreCuisine::getStatus, 1)  // 审核通过
                .list();
    }

    /**
     * 上下架操作：1-上架，2-下架
     */
    @Override
    public boolean changeShelfStatus(Integer id, Integer shelfStatus) {
        StoreCuisine cuisine = new StoreCuisine();
        cuisine.setId(id);
        cuisine.setShelfStatus(shelfStatus);
        return updateById(cuisine);
    }


    /**
     * 根据 id 与类型获取详情（新格式）：
     * - type = 1：返回单品详情
     * - type = 2：返回套餐详情（主信息 + 套餐包含的单品列表）
     */
    @Override
    public CuisineTypeResponseDto getByCuisineTypeNew(Integer id, Integer cuisineType) {
        // 1. 先查主表记录
        StoreCuisine base = getById(id);
        if (base == null) {
            return null;
        }

        CuisineTypeResponseDto response = new CuisineTypeResponseDto();
        CuisineTypeResponseDto.CuisineTypeData data = new CuisineTypeResponseDto.CuisineTypeData();
        
        // 填充基本信息
        data.setCuisineType(base.getCuisineType());
        data.setStoreId(base.getStoreId());
        data.setName(base.getName());
        data.setTotalPrice(base.getTotalPrice());
        data.setCategoryIds(base.getCategoryIds());
        // 根据分类ID查询分类名称
        data.setCategoryNames(getCategoryNames(base.getCategoryIds()));
        data.setIsHomepageDisplay(base.getIsHomepageDisplay());
        data.setTags(base.getTags());
        data.setDishReview(base.getDishReview());
        data.setImages(base.getImages());
        data.setImageContent(base.getImageContent());
        data.setDetailContent(base.getDetailContent());
        data.setDescription(base.getDescription());
        data.setExtraNote(base.getExtraNote());
        data.setNeedReserve(base.getNeedReserve());
        data.setReserveRule(base.getReserveRule());
        data.setPeopleLimit(base.getPeopleLimit());
        data.setUsageRule(base.getUsageRule());
        data.setRawJson(base.getRawJson());
        data.setCreatedTime(base.getCreatedTime());
        data.setAuditTime(base.getAuditTime());
        data.setAuditStatus(base.getStatus());
        data.setShelfStatus(base.getShelfStatus());
        // 补充门店电话/名称（仅用于详情返回，不落库）
        StoreInfo storeInfo = storeInfoMapper.selectById(base.getStoreId());
        if (storeInfo != null) {
            data.setStorePhone(storeInfo.getStoreTel());
            data.setStoreName(storeInfo.getStoreName());
        }
        // 单品：groupJson 为空，name 为单品名称
        if (cuisineType != null && cuisineType == 1) {
            response.setName(base.getName());
            data.setGroupJson("");
            response.setData(data);
            return response;
        }

        // 套餐：通过中间表查出包含哪些单品，构建 groupJson
        LambdaQueryWrapper<StoreCuisineCombo> comboWrapper = new LambdaQueryWrapper<>();
        comboWrapper.eq(StoreCuisineCombo::getCid, id);
        List<StoreCuisineCombo> combos = storeCuisineComboService.list(comboWrapper);
        
        if (combos.isEmpty()) {
            response.setName("套餐：" + base.getName());
            data.setGroupJson("[]");
            response.setData(data);
            return response;
        }

        // 收集所有单品 sid
        List<Integer> sidList = combos.stream()
                .map(StoreCuisineCombo::getSid)
                .distinct()
                .collect(Collectors.toList());

        // 一次性查出所有单品
        List<StoreCuisine> singles = lambdaQuery()
                .in(StoreCuisine::getId, sidList)
                .list();
        Map<Integer, StoreCuisine> singleMap = singles.stream()
                .collect(Collectors.toMap(StoreCuisine::getId, s -> s));

        // 按分类分组构建 CategoryGroupDto 列表
        Map<String, List<StoreCuisineCombo>> categoryMap = combos.stream()
                .collect(Collectors.groupingBy(StoreCuisineCombo::getCategory));

        List<CategoryGroupDto> categoryGroups = new ArrayList<>();
        
        for (Map.Entry<String, List<StoreCuisineCombo>> entry : categoryMap.entrySet()) {
            String categoryName = entry.getKey();
            List<StoreCuisineCombo> categoryCombos = entry.getValue();
            
            CategoryGroupDto group = new CategoryGroupDto();
            group.setCategoryName(categoryName);
            
            List<CuisineItemDto> items = new ArrayList<>();
            for (StoreCuisineCombo combo : categoryCombos) {
                StoreCuisine single = singleMap.get(combo.getSid());
                if (single == null) {
                    continue;
                }
                
                CuisineItemDto item = new CuisineItemDto();
                item.setCuisineId(single.getId());
                item.setCuisineName(single.getName());
                item.setQuantity(combo.getSnum());
                item.setUnit("份");
                item.setPrice(single.getTotalPrice());
                items.add(item);
            }
            group.setItems(items);
            categoryGroups.add(group);
        }

        // 将 CategoryGroupDto 列表转换为 JSON 字符串
        String groupJson;
        try {
            groupJson = objectMapper.writeValueAsString(categoryGroups);
        } catch (IOException e) {
            throw new RuntimeException("构建套餐组合 JSON 失败", e);
        }
        data.setGroupJson(groupJson);

        // 构建 name 字段：套餐：{套餐名称}（引用上述{数量}个单品）
        // 计算不同单品的数量（去重后的 sid 数量）
        int singleCount = sidList.size();
        String countText = singleCount == 2 ? "两个" : (singleCount == 3 ? "三个" : singleCount + "个");
        response.setName("套餐：" + base.getName() + "（引用上述" + countText + "单品）");

        response.setData(data);
        return response;
    }

    /**
     * 根据前端传入的 JSON，构建中间表记录列表
     *
     * @param comboId  套餐ID
     * @param groupJson 前端传入的 JSON 字符串
     * @return 中间表记录列表
     */
    private List<StoreCuisineCombo> buildComboListFromJson(Integer comboId, String groupJson) {
        List<CategoryGroupDto> groups;
        try {
            groups = objectMapper.readValue(groupJson, new TypeReference<List<CategoryGroupDto>>() {});
        } catch (IOException e) {
            throw new RuntimeException("解析套餐组合 JSON 失败", e);
        }

        List<StoreCuisineCombo> comboList = new ArrayList<>();
        for (CategoryGroupDto group : groups) {
            String categoryName = group.getCategoryName();
            for (CuisineItemDto item : group.getItems()) {
                StoreCuisineCombo combo = new StoreCuisineCombo();
                combo.setCid(comboId);
                combo.setSid(item.getCuisineId());
                combo.setSnum(item.getQuantity());
                combo.setCategory(categoryName);
                comboList.add(combo);
            }
        }
        return comboList;
    }

    /**
     * 格式化分类ID为JSON数组字符串
     * 如果传入的是有效的JSON数组字符串，直接返回；如果是空或null，返回null
     *
     * @param categoryIds 分类ID字符串（JSON数组格式，如："[1,2,3]"）
     * @return 格式化后的JSON数组字符串，如果为空则返回null
     */
    private String formatCategoryIds(String categoryIds) {
        if (StringUtils.isBlank(categoryIds)) {
            return null;
        }
        
        // 去除首尾空格
        String trimmed = categoryIds.trim();
        
        // 如果已经是有效的JSON数组格式（以[开头，]结尾），直接返回
        if (trimmed.startsWith("[") && trimmed.endsWith("]")) {
            try {
                // 验证是否为有效的JSON数组
                objectMapper.readValue(trimmed, new TypeReference<List<Integer>>() {});
                return trimmed;
            } catch (IOException e) {
                throw new IllegalArgumentException("分类ID格式不正确，应为JSON数组格式，如：[1,2,3]", e);
            }
        }
        
        // 如果不是JSON格式，尝试解析为逗号分隔的字符串并转换为JSON数组
        try {
            String[] ids = trimmed.split(",");
            List<Integer> idList = new ArrayList<>();
            for (String id : ids) {
                String idStr = id.trim();
                if (StringUtils.isNotBlank(idStr)) {
                    idList.add(Integer.parseInt(idStr));
                }
            }
            if (idList.isEmpty()) {
                return null;
            }
            return objectMapper.writeValueAsString(idList);
        } catch (NumberFormatException e) {
            throw new IllegalArgumentException("分类ID格式不正确，应为数字数组", e);
        } catch (IOException e) {
            throw new RuntimeException("转换分类ID为JSON格式失败", e);
        }
    }

    /**
     * 根据分类ID字符串（JSON数组格式）查询分类名称
     *
     * @param categoryIds 分类ID字符串（JSON数组格式，如："[1,2,3]"）
     * @return 分类名称JSON数组字符串（如："[\"热菜\",\"凉菜\"]"），如果categoryIds为空则返回null
     */
    @Override
    public String getCategoryNames(String categoryIds) {
        if (StringUtils.isBlank(categoryIds)) {
            return null;
        }

        try {
            // 解析分类ID数组
            List<Integer> idList = objectMapper.readValue(categoryIds, new TypeReference<List<Integer>>() {});
            if (idList == null || idList.isEmpty()) {
                return null;
            }

            // 批量查询分类信息
            List<StoreCuisineCategory> categories = new ArrayList<>(storeCuisineCategoryService.listByIds(idList));
            if (categories == null || categories.isEmpty()) {
                return "[]";
            }

            // 构建ID到名称的映射
            Map<Integer, String> idToNameMap = categories.stream()
                    .collect(Collectors.toMap(StoreCuisineCategory::getId, StoreCuisineCategory::getCategoryName));

            // 按照原始ID顺序构建名称列表
            List<String> nameList = new ArrayList<>();
            for (Integer id : idList) {
                String name = idToNameMap.get(id);
                if (name != null) {
                    nameList.add(name);
                }
            }

            // 转换为JSON数组字符串
            return objectMapper.writeValueAsString(nameList);
        } catch (IOException e) {
            // 解析分类ID或构建分类名称失败时，返回null，不抛出异常
            return null;
        }
    }

    /**
     * 验证菜品字段长度
     */
    private void validateCuisineFields(CuisineComboDto dto) {
        // 验证菜品标签：限5字，最多3个
        if (StringUtils.isNotBlank(dto.getTags())) {
            try {
                List<String> tags = objectMapper.readValue(dto.getTags(), new TypeReference<List<String>>() {});
                if (tags != null) {
                    if (tags.size() > 3) {
                        throw new IllegalArgumentException("菜品标签最多可添加3个");
                    }
                    for (String tag : tags) {
                        if (tag != null && tag.length() > 5) {
                            throw new IllegalArgumentException("菜品标签长度不能超过5字：" + tag);
                        }
                    }
                }
            } catch (IOException e) {
                throw new IllegalArgumentException("菜品标签格式错误");
            }
        }
        
        // 验证菜品短评：限20字
        if (StringUtils.isNotBlank(dto.getDishReview()) && dto.getDishReview().length() > 20) {
            throw new IllegalArgumentException("菜品短评长度不能超过20字");
        }
        
        // 验证菜品描述：限300字
        if (StringUtils.isNotBlank(dto.getDescription()) && dto.getDescription().length() > 300) {
            throw new IllegalArgumentException("菜品描述长度不能超过300字");
        }
    }
}


