/*
 * Copyright (c) 2018-2999 广州亚米信息科技有限公司 All rights reserved.
 *
 * https://www.gz-yami.com/
 *
 * 未经允许，不可做商业用途！
 *
 * 版权所有，侵权必究！
 */

package com.yami.shop.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.collection.CollectionUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
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.google.common.collect.Lists;
import com.yami.shop.bean.dto.ListCategoryDTO;
import com.yami.shop.bean.model.Category;
import com.yami.shop.bean.model.ShopCategory;
import com.yami.shop.bean.param.CategoryScoreConfigParam;
import com.yami.shop.bean.param.ScoreConfigParam;
import com.yami.shop.bean.vo.ListCategoryForUserVO;
import com.yami.shop.bean.vo.ListCategoryVO;
import com.yami.shop.common.config.Constant;
import com.yami.shop.common.exception.GlobalException;
import com.yami.shop.dao.*;
import com.yami.shop.service.CategoryService;
import com.yami.shop.service.SysConfigService;
import lombok.AllArgsConstructor;
import org.springframework.beans.BeanUtils;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.cache.annotation.Caching;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import java.util.*;
import java.util.stream.Collectors;

/**
 * @author LGH
 */
@Service
@AllArgsConstructor
public class CategoryServiceImpl extends ServiceImpl<CategoryMapper, Category> implements CategoryService {

    private final CategoryMapper categoryMapper;

    private final CategoryBrandMapper categoryBrandMapper;

    private final CategoryProdMapper categoryPropMapper;
    private final ShopCategoryMapper shopCategoryMapper;

    private final ProductMapper productMapper;

    private SysConfigService sysConfigService;

    @Override
    @Transactional(rollbackFor = Exception.class)
//	@CacheEvict(cacheNames = "CategoryListByParentIdAndShopId", key = "#category.parentId + ':' + #category.shopId")
    @Caching(evict = {
            @CacheEvict(cacheNames = "CategoryListByParentIdAndShopId", key = "#category.parentId + ':' + #category.shopId"),
            @CacheEvict(cacheNames = "CategoryListByShopId", key = "#category.shopId + ':category'")
    })
    public void saveCategroy(Category category) {
        category.setRecTime(new Date());
        // 保存分类信息
        categoryMapper.insert(category);

        insertBrandsAndAttributes(category);

        if (Objects.equals(category.getParentId(), Constant.CATEGORY_ID) && Objects.equals(category.getShopId(), Constant.PLATFORM_SHOP_ID)) {
            this.changeScoreConfig();
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    @Caching(evict = {
            @CacheEvict(cacheNames = "CategoryListByParentIdAndShopId", key = "#category.parentId + ':' + #category.shopId"),
            @CacheEvict(cacheNames = "CategoryListByShopId", key = "#category.shopId + ':category'")
    })
    public void updateCategroy(Category category) {
        Category categoryDB = categoryMapper.selectById(category.getCategoryId());
        category.setUpdateTime(new Date());

        // 保存分类信息
        categoryMapper.updateById(category);

        if (Objects.equals(categoryDB.getStatus(), 1) && Objects.equals(category.getStatus(), 0)) {
            if (Objects.equals(category.getParentId(), 0L)) {
                List<Category> categorieList = categoryMapper.selectList(new LambdaQueryWrapper<Category>().eq(Category::getParentId, category.getCategoryId()));
                for (Category categoryByParentId : categorieList) {
                    categoryByParentId.setStatus(0);
                    //从正常改为下线
                    productMapper.offlineProdByCategoryId(categoryByParentId.getCategoryId());
                }
                updateBatchById(categorieList);
            } else {
                //从正常改为下线
                productMapper.offlineProdByCategoryId(category.getCategoryId());
            }
        }

        //修改积分配置中的分类数据
        if (!Objects.equals(category.getCategoryName(), category.getOldCategoryName())) {
            this.changeScoreConfig();
        }
        // 先删除后增加
        deleteBrandsAndAttributes(category.getCategoryId());
        insertBrandsAndAttributes(category);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
//	@CacheEvict(cacheNames = "CategoryListByParentIdAndShopId", key = "#category.parentId + ':' + #category.shopId")
    @Caching(evict = {
            @CacheEvict(cacheNames = "CategoryListByParentIdAndShopId", key = "#category.parentId + ':' + #category.shopId"),
            @CacheEvict(cacheNames = "CategoryListByShopId", key = "#category.shopId + ':category'")
    })
    public void deleteCategroy(Category category) {
        categoryMapper.deleteById(category.getCategoryId());
        //修改积分配置中的分类数据
        if (Objects.equals(category.getParentId(), Constant.CATEGORY_ID)) {
            this.changeScoreConfig();
        }
        deleteBrandsAndAttributes(category.getCategoryId());
    }

    @Override
    public Category getCategoryByCategoryIdAndShopId(Long categoryId, Long shopId) {
        Category category = categoryMapper.selectOne(new LambdaQueryWrapper<Category>().eq(Category::getCategoryId, categoryId).eq(Category::getShopId, shopId));
        if (category == null) {
            throw new GlobalException("无法获取分类信息");
        }
        return category;
    }

    @Override
//    @Cacheable(cacheNames = "CategoryListByParentIdAndShopId", key = "#parentId + ':' + #shopId")
    public IPage<Category> listByParentIdAndShopId(Long parentId, Long shopId, Integer current, Integer size) {
        if (Objects.isNull(shopId)) {
            IPage<Category> page = page(new Page<>(current, size), new LambdaQueryWrapper<Category>()
                    .eq(Category::getParentId, parentId)
                    .eq(Category::getStatus, 1)
                    .orderByDesc(Category::getSeq)
                    .orderByDesc(Category::getCategoryId));
            List<Category> categories = page.getRecords();
            if (CollectionUtil.isNotEmpty(categories)) {
                for (Category category : categories) {
                    List<Category> son = categoryMapper.selectList(new LambdaQueryWrapper<Category>()
                            .eq(Category::getParentId, category.getCategoryId())
                            .eq(Category::getStatus, 1)
                            .orderByDesc(Category::getSeq));
                    category.setCategories(son);
                    if (CollectionUtil.isNotEmpty(son)) {
                        for (Category item : son) {
                            List<Category> third = categoryMapper.selectList(new LambdaQueryWrapper<Category>()
                                    .eq(Category::getParentId, item.getCategoryId())
                                    .eq(Category::getStatus, 1)
                                    .orderByDesc(Category::getSeq));
                            item.setCategories(third);
                        }
                    }
                }
            }
            Page res = new Page();
            BeanUtils.copyProperties(page, res);
            res.setRecords(categories);
            return res;
        }
        // 如果是平台分类，则特殊处理
        if (shopId == 0) {
//            List<Category> categoriesTwo = categoryMapper.listByParentId(parentId);
//            List<Category> categoriesThree = categoryMapper.listThreeByParentId(parentId);
//            for (Category category : categoriesThree) {
//                category.setPic(shopConfig.getDomain().getResourcesDomainName() + "/" + category.getPic());
//                category.setIcon(shopConfig.getDomain().getResourcesDomainName() + "/" + category.getIcon());
//            }
//            //根据父类id分组，并放入对应得父类中
//            if (CollectionUtils.isNotEmpty(categoriesThree) && CollectionUtils.isNotEmpty(categoriesTwo)) {
//                Map<Long, List<Category>> categoryMap = categoriesThree.stream().collect(groupingBy(Category::getParentId));
//                for (Category category : categoriesTwo) {
//                    if (categoryMap.containsKey(category.getCategoryId())) {
//                        List<Category> categories = categoryMap.get(category.getCategoryId());
//                        category.setCategories(categories);
//                    }
//                }
//            }
//            return categoriesTwo;
            return new Page<>();
        } else {
            IPage<Category> page2 = page(new Page<>(current, size), new LambdaQueryWrapper<Category>()
                    .eq(Category::getShopId, shopId)
                    .eq(Category::getParentId, parentId)
                    .eq(Category::getStatus, 1)
                    .orderByDesc(Category::getSeq)
                    .orderByDesc(Category::getCategoryId));
            return page2;
        }
    }

    @Override
    @Cacheable(cacheNames = "CategoryListByShopId", key = "#shopId + ':category'")
    public List<Category> listByShopId(Long shopId) {
        return categoryMapper.selectList(new LambdaQueryWrapper<Category>().eq(Category::getShopId, shopId));
    }

    @Override
    public IPage<ListCategoryVO> listCategory(ListCategoryDTO listCategoryDTO) {
        IPage<ListCategoryVO> listCategoryVOIPage = categoryMapper.listCategory(new Page<>(listCategoryDTO.getCurrent(), listCategoryDTO.getSize()), listCategoryDTO);
        listCategoryVOIPage.getRecords().forEach(listCategoryVO -> {
            listCategoryVO.setGrade(0);
            if (listCategoryVO.getResource() == null) {
                listCategoryVO.setResource("");
            } else {
                listCategoryVO.setResource(listCategoryVO.getResource() + "个商品");
            }
            listCategoryVO.setProductBeBound(0);
            listCategoryVO.setChildren(categoryMapper.listCategoryChildren(new ListCategoryDTO().setParentId(listCategoryVO.getCategoryID())));
            listCategoryVO.getChildren().forEach(listCategoryVO1 -> {
                listCategoryVO1.setGrade(1);
                if (listCategoryVO1.getResource() == null) {
                    listCategoryVO1.setResource("");
                } else {
                    listCategoryVO1.setResource(listCategoryVO1.getResource() + "个商品");
                }
                List<ListCategoryVO> listCategoryVOS = categoryMapper.listCategoryChildren(new ListCategoryDTO().setParentId(listCategoryVO1.getCategoryID()));
                if (listCategoryVOS.isEmpty()) {
                    listCategoryVO1.setProductBeBound(1);
                    listCategoryVO1.setChildren(new ArrayList<>());
                } else {
                    listCategoryVO1.setProductBeBound(0);
                    listCategoryVO1.setChildren(listCategoryVOS);
                    listCategoryVO1.getChildren().forEach(listCategoryVO2 -> {
                        listCategoryVO2.setGrade(2);
                        if (listCategoryVO2.getResource() == null) {
                            listCategoryVO2.setResource("");
                        } else {
                            listCategoryVO2.setResource(listCategoryVO2.getResource() + "个商品");
                        }
                        listCategoryVO2.setProductBeBound(1);
                        listCategoryVO2.setChildren(new ArrayList<>());
                    });
                }
            });
        });
        return listCategoryVOIPage;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Integer parseCategoryFile(MultipartFile excelFile, Long shopId) throws Exception {
        // 1. 校验并解析Excel
        List<List<String>> dataRows = validateAndParseExcel(excelFile);

        // 2. 保存分类层级（若允许放宽主键依赖，可开启批量插入）
        saveCategoryHierarchy(dataRows, shopId);

        // 3. 返回成功导入的行数（每行对应一组三级分类）
        return dataRows.size();
    }

    @Override
    public List<ListCategoryForUserVO> listCategoryForUser(Long channelId,Long shopId) {
        List<ShopCategory> shopCategories = shopCategoryMapper.selectAppListAll(channelId,shopId);
        Map<Long, List<ShopCategory>> parentMap = shopCategories.stream()
                .collect(Collectors.groupingBy(ShopCategory::getPid));
        // 初始层级为一级分类（grade = 1）
        return buildCategoryTree(parentMap.getOrDefault(0L, Collections.emptyList()), parentMap, 0);
    }

    private List<ListCategoryForUserVO> buildCategoryTree(List<ShopCategory> categories, Map<Long, List<ShopCategory>> parentMap, int currentLevel) {
        if (CollectionUtil.isEmpty(categories)) return Collections.emptyList();
        return categories.stream()
                .map(category -> {
                    ListCategoryForUserVO vo = new ListCategoryForUserVO();
                    vo.setCategoryName(category.getName());
                    vo.setSeq(category.getNum());
                        vo.setParentId(category.getPid());
                    vo.setCategoryId(category.getId());
                    vo.setIcon(category.getIcon());

                    // 动态计算当前分类的等级（1: 一级, 2: 二级, 3: 三级）
                    int grade = currentLevel;
                    vo.setGrade(grade); // 如果 VO 类中需要保留 grade 字段，可保留此行

                    // 判断是否为二级或三级分类，并设置 productBeBound 字段
                    int productBeBound = 0;
                    if (grade == 1 || grade == 2) {
                        // 三级分类直接绑定商品
                        if (grade == 2) {
                            productBeBound = 1;
                        }
                        // 二级分类若无子分类（三级分类），则允许绑定商品
                        else if (grade == 1) {
                            List<ShopCategory> children = parentMap.getOrDefault(category.getId(), Collections.emptyList());
                            productBeBound = children.isEmpty() ? 1 : 0;
                        }
                    }
                    vo.setProductBeBound(productBeBound);

                    // 递归构建子分类树，层级 +1
                    List<ShopCategory> children = parentMap.getOrDefault(category.getId(), Collections.emptyList());

                    children.sort(Comparator.comparingInt(ShopCategory::getNum));

                    vo.setChildren(buildCategoryTree(children, parentMap, currentLevel + 1));

                    return vo;
                })
                .collect(Collectors.toList());
    }

    // 校验与解析分离
    private List<List<String>> validateAndParseExcel(MultipartFile excelFile) throws Exception {
//		Workbook workBook = WorkbookFactory.create(excelFile.getInputStream());
//
//		Sheet sheet = workBook.getSheetAt(0);
//
//		// 校验标题行
//		Row headerRow = sheet.getRow(0);
//		List<String> headers = new ArrayList<>();
//		if (headerRow != null) {
//			for (int i = 0; i < headerRow.getLastCellNum(); i++) {
//				Cell cell = headerRow.getCell(i, Row.MissingCellPolicy.CREATE_NULL_AS_BLANK);
//				cell.setCellType(CellType.STRING);
//				String value = cell.getStringCellValue().trim();
//				if (value.isEmpty()) throw new GlobalException("第" + (i+1) + "列标题为空");
//				headers.add(value);
//			}
//		}
//
//		// 校验列数与列名
//		if (headers.size() != 3) throw new GlobalException("模板列数必须为3列");
//		String[] expected = {"一级分类名称", "二级分类名称", "三级分类名称"};
//		for (int i = 0; i < expected.length; i++) {
//			if (!headers.get(i).equals(expected[i])) {
//				throw new GlobalException("第" + (i+1) + "列名称应为【" + expected[i] + "】");
//			}
//		}
//
//		// 提取数据行
//		List<List<String>> result = new ArrayList<>();
//		for (int rowNum = 1; rowNum <= sheet.getLastRowNum(); rowNum++) {
//			Row dataRow = sheet.getRow(rowNum);
//			List<String> rowData = new ArrayList<>(3);
//			for (int i = 0; i < 3; i++) {
//				Cell cell = dataRow.getCell(i, Row.MissingCellPolicy.CREATE_NULL_AS_BLANK);
//				cell.setCellType(CellType.STRING);
//				rowData.add(cell.getStringCellValue().trim());
//			}
//			if (rowData.get(0).isEmpty() || rowData.get(1).isEmpty()) {
//				throw new GlobalException("一级和二级分类名称不能为空");
//			}
//			result.add(rowData);
//		}
        return new ArrayList<>();
    }

    // 分类保存逻辑（若允许放宽主键依赖，可开启批量插入）
    private void saveCategoryHierarchy(List<List<String>> dataRows, Long shopId) {
        dataRows.forEach(row -> {
            String cat1Name = row.get(0);
            String cat2Name = row.get(1);
            String cat3Name = row.get(2);

            // 1. 处理一级分类（parent_id = 0）
            Category cat1 = categoryMapper.selectByNameAndParentId(cat1Name, 0L, shopId);
            if (cat1 == null) {
                cat1 = buildCategory(shopId, 0L, cat1Name, 0);
                categoryMapper.insert(cat1);
            }

            // 2. 处理二级分类（parent_id = cat1.id）
            Category cat2 = categoryMapper.selectByNameAndParentId(cat2Name, cat1.getCategoryId(), shopId);
            if (cat2 == null) {
                cat2 = buildCategory(shopId, cat1.getCategoryId(), cat2Name, 1);
                categoryMapper.insert(cat2);
            }

            // 3. 处理三级分类（parent_id = cat2.id，允许为空）
            if (!cat3Name.isEmpty()) {
                Category cat3 = categoryMapper.selectByNameAndParentId(cat3Name, cat2.getCategoryId(), shopId);
                if (cat3 == null) {
                    cat3 = buildCategory(shopId, cat2.getCategoryId(), cat3Name, 2);
                    categoryMapper.insert(cat3);
                }
            }
        });
    }

    // 构建分类实体（可复用）
    private Category buildCategory(Long shopId, Long parentId, String name, int grade) {
        return new Category()
                .setShopId(shopId)
                .setParentId(parentId)
                .setCategoryName(name)
                .setGrade(grade)
                .setSeq(1) // 默认 seq 值
                .setStatus(1) // 默认启用状态
                .setRecTime(new Date())
                .setUpdateTime(new Date());
    }

    private void deleteBrandsAndAttributes(Long categoryId) {
        // 删除所有分类所关联的品牌
        categoryBrandMapper.deleteByCategoryId(categoryId);
        // 删除所有分类所关联的参数
        categoryPropMapper.deleteByCategoryId(categoryId);
    }

    private void insertBrandsAndAttributes(Category category) {
        //保存分类与品牌信息
        if (CollUtil.isNotEmpty(category.getBrandIds())) {
            categoryBrandMapper.insertCategoryBrand(category.getCategoryId(), category.getBrandIds());
        }


    }

    /**
     * 刷新积分配置中的分类数据
     */
    private void changeScoreConfig() {
        ScoreConfigParam scoreParamDb = sysConfigService.getSysConfigObject(Constant.SCORE_CONFIG, ScoreConfigParam.class);
        if (Objects.isNull(scoreParamDb)) {
            throw new GlobalException("请先前往 【会员管理】-> 【积分成长值配置】-> 【积分获取配置】 进行配置并保存 ");
        }
        //判断分类数据是否正确
        List<Category> categoryList = categoryMapper.selectList(new LambdaQueryWrapper<Category>()
                .eq(Category::getParentId, Constant.CATEGORY_ID)
                .eq(Category::getShopId, Constant.PLATFORM_SHOP_ID)
                .orderByAsc(Category::getCategoryId)
        );
        Map<Long, Category> categoryMap = categoryList.stream().collect(Collectors.toMap(Category::getCategoryId, category -> category));
        // 还没有分类数据时，scoreParamDb.getCategoryConfigs()为null,所以为它new一个对象
        if (Objects.isNull(scoreParamDb.getCategoryConfigs())) {
            scoreParamDb.setCategoryConfigs(Lists.newArrayList());
        }
        Iterator<CategoryScoreConfigParam> iterator = scoreParamDb.getCategoryConfigs().iterator();
        //更新数据并去除已删除的数据
        while (iterator.hasNext()) {
            CategoryScoreConfigParam categoryScoreConfigParam = iterator.next();
            Category category = categoryMap.get(categoryScoreConfigParam.getCategoryId());
            if (Objects.isNull(category)) {
                iterator.remove();
            } else {
                //刷新分类名称
                categoryScoreConfigParam.setCategoryName(categoryScoreConfigParam.getCategoryName());
                //删除map中已进行操作过的分类
                categoryMap.remove(categoryScoreConfigParam.getCategoryId());
            }
        }
        // 获取map中剩下的分类的id（剩下的分类为积分配置json中所没有的分类，需要新增）
        Set<Long> longs = categoryMap.keySet();
        // 新增积分配置json中的分类数据
        for (Long catrgoryId : longs) {
            Category category = categoryMap.get(catrgoryId);
            CategoryScoreConfigParam categoryScoreConfigParam = new CategoryScoreConfigParam();
            categoryScoreConfigParam.setCategoryId(category.getCategoryId());
            categoryScoreConfigParam.setCategoryName(category.getCategoryName());
            categoryScoreConfigParam.setGetScoreLimit(1.00);
            categoryScoreConfigParam.setUseScoreLimit(1.00);
            scoreParamDb.getCategoryConfigs().add(categoryScoreConfigParam);
        }
        //保存数据
        sysConfigService.saveOrUpdateSysConfigService(scoreParamDb, Constant.SCORE_CONFIG);
    }
}
