package com.yc.ship.module.resource.service.category;

import cn.hutool.core.lang.tree.TreeNode;
import cn.hutool.core.map.MapUtil;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.IdWorker;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.yc.ship.framework.common.pojo.PageResult;
import com.yc.ship.framework.common.util.object.BeanUtils;
import com.yc.ship.framework.mybatis.core.query.LambdaQueryWrapperX;
import com.yc.ship.framework.mybatis.core.util.MyBatisUtils;
import com.yc.ship.framework.tenant.core.aop.TenantIgnore;
import com.yc.ship.framework.tenant.core.context.TenantContextHolder;
import com.yc.ship.framework.tenant.core.util.TenantUtils;
import com.yc.ship.module.infra.api.config.ConfigApi;
import com.yc.ship.module.resource.controller.admin.category.vo.*;
import com.yc.ship.module.resource.controller.admin.vo.AppCategoryReqVO;
import com.yc.ship.module.resource.controller.admin.vo.AppCategoryRespVO;
import com.yc.ship.module.resource.dal.dataobject.category.CategoryDO;
import com.yc.ship.module.resource.dal.dataobject.category.CategoryExtraDO;
import com.yc.ship.module.resource.dal.mysql.category.CategoryExtraMapper;
import com.yc.ship.module.resource.dal.mysql.category.CategoryMapper;
import com.yc.ship.module.resource.enums.ErrorCodeConstants;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.validation.annotation.Validated;

import javax.annotation.Resource;
import java.util.*;
import java.util.concurrent.atomic.AtomicReference;
import java.util.stream.Collectors;

import static com.yc.ship.framework.common.exception.util.ServiceExceptionUtil.exception;


/**
 * 资源-产品分类 Service 实现类
 *
 * @author 管理员
 */
@Service
@Validated
public class CategoryServiceImpl implements CategoryService {

    @Resource
    private ConfigApi configApi;

    @Resource
    private CategoryMapper categoryMapper;
    @Resource
    private CategoryExtraMapper categoryExtraMapper;

    @Override
    @Transactional
    public Long createCategory(CategorySaveReqVO createReqVO) {
        // 插入
        CategoryDO category = BeanUtils.toBean(createReqVO, CategoryDO.class);
        Long id = IdWorker.getId(category);
        category.setId(id);
        category.setDeleted(false);
        String allParentIds = this.getAllParentIds(category.getParentId());
        category.setParentPath(allParentIds);
        categoryMapper.insert(category);

        // 全路径名称
        try {
            List<CategoryRespVO> list = categoryMapper.getAllUpCategoryById(id, category.getType());
            String fullPathName = list.stream().map(CategoryRespVO::getCateName).collect(Collectors.joining("/"));
            category.setFullPathName(fullPathName);
            categoryMapper.updateById(category);
        }catch (Exception e){

        }

//        if (category.getType() == 2) {
//            CategoryExtraDO categoryExtra;
//            if (createReqVO.getExtraInfo() == null) {
//                categoryExtra = new CategoryExtraDO();
//            } else {
//                categoryExtra = BeanUtils.toBean(createReqVO.getExtraInfo(), CategoryExtraDO.class);
//            }
//            categoryExtra.setId(category.getId());
//            categoryExtra.setDeleted(false);
//            categoryExtraMapper.insert(categoryExtra);
//        }
        if (category.getType() == 1) {
            // 将父级分类的产品移动到为当前分类下
            categoryMapper.updateProductCategoryId(category.getId(), category.getParentId());
        }
        // 返回
        return category.getId();
    }

    @Override
    public void updateCategory(CategorySaveReqVO updateReqVO) {
        // 校验存在
        CategoryDO categoryDO = validateCategoryExists(updateReqVO.getId());
        // 更新
        CategoryDO updateObj = BeanUtils.toBean(updateReqVO, CategoryDO.class);
        // 保存全路径名称
        if (Objects.isNull(updateReqVO.getFullPathName())) {
            List<CategoryRespVO> list = categoryMapper.getAllUpCategoryById(updateReqVO.getId(), updateReqVO.getType());
            String fullPathName = list.stream().map(CategoryRespVO::getCateName).collect(Collectors.joining("/"));
            updateObj.setFullPathName(fullPathName);
        } else if (!Objects.equals(categoryDO.getCateName(), updateObj.getCateName())) {
            // 修改子节点全路径名称
            List<CategoryRespVO> list = categoryMapper.getAllDownCategoryById(updateObj.getId(), updateReqVO.getType());
            list.forEach(category -> {
                String fullPathName = category.getFullPathName().replace(categoryDO.getCateName(), updateObj.getCateName());
                if (Objects.equals(category.getId(), updateObj.getId())) {
                    updateObj.setFullPathName(fullPathName);
                } else {
                    categoryMapper.update(new LambdaUpdateWrapper<CategoryDO>()
                            .eq(CategoryDO::getId, category.getId())
                            .set(CategoryDO::getFullPathName, fullPathName));
                }
            });
        }
        categoryMapper.updateById(updateObj);
//        if (updateReqVO.getType() == 2) {
//            CategoryExtraDO categoryExtraDO = categoryExtraMapper.selectById(updateReqVO.getId());
//            if (ObjectUtil.isEmpty(categoryExtraDO)) {
//                categoryExtraDO = BeanUtils.toBean(updateReqVO.getExtraInfo(), CategoryExtraDO.class);
//                categoryExtraDO.setId(updateReqVO.getId());
//                categoryExtraDO.setDeleted(false);
//                categoryExtraMapper.insert(categoryExtraDO);
//            } else {
//                if (StringUtils.equals("1", updateReqVO.getExtraInfo().getOperationType())) {
//                    updateReqVO.getExtraInfo().setId(categoryExtraDO.getId());
//                    UpdateWrapper<CategoryExtraDO> updateWrapper = new UpdateWrapper<>();
//                    updateWrapper.eq("id", categoryExtraDO.getId());
//                    updateWrapper.set("applet_products", updateReqVO.getExtraInfo().getAppletProducts());
//                    categoryExtraMapper.update(updateWrapper);
//                } else {
//                    categoryExtraDO = BeanUtils.toBean(updateReqVO.getExtraInfo(), CategoryExtraDO.class);
//                    categoryExtraMapper.updateById(categoryExtraDO);
//                }
//            }
//        }
    }

    @Override
    public void deleteCategory(Long id) {
        // 校验存在
        CategoryDO categoryDO = validateCategoryExists(id);
        if (categoryDO.getType() == 2) {
            categoryExtraMapper.deleteById(id);
        }
        // 删除
        categoryMapper.deleteById(id);
    }

    private CategoryDO validateCategoryExists(Long id) {
        CategoryDO categoryDO = categoryMapper.selectById(id);
        if (categoryDO == null) {
            throw exception(ErrorCodeConstants.CATEGORY_NOT_EXISTS);
        }
        return categoryDO;
    }

    @Override
    public CategoryDO getCategory(Long id) {
        return categoryMapper.selectById(id);
    }

    @Override
    public CategoryRespVO getCategoryExtra(Long id) {
        CategoryDO categoryDO = categoryMapper.selectById(id);
        CategoryRespVO categoryRespVO = BeanUtils.toBean(categoryDO, CategoryRespVO.class);
        if (categoryDO == null) {
            throw exception(ErrorCodeConstants.CATEGORY_EXTRA_NOT_EXISTS);
        }
        if (categoryDO.getType() == 2) {
            CategoryExtraDO categoryExtraDO = categoryExtraMapper.selectById(id);
            categoryRespVO.setExtraInfo(BeanUtils.toBean(categoryExtraDO, CategoryExtraRespVO.class));
        }
        return categoryRespVO;
    }

    @Override
    public PageResult<CategoryDO> getCategoryPage(CategoryPageReqVO pageReqVO) {
        return categoryMapper.selectPage(pageReqVO);
    }

    @Override
    public PageResult<CategoryRespVO> selectCategoryPage(CategoryPageReqVO pageReqVO) {
        IPage<CategoryRespVO> iPage = MyBatisUtils.buildPage(pageReqVO);
        IPage<CategoryRespVO> page = categoryMapper.selectCategoryPage(iPage, pageReqVO);
        return new PageResult<>(page.getRecords(), page.getTotal());
    }

    @Override
    public List<TreeNode> getPlatAllCategoryTreeList(CategoryListReqVO reqVO) {
        AtomicReference<List<CategoryDO>> categoryDOList = new AtomicReference<>(new ArrayList<>());
        //查询所有分销商租户
        List<Map<String, Object>> mapList = categoryMapper.getPlatAllTenantId(TenantContextHolder.getTenantId());
        if (!mapList.isEmpty()) {
            categoryDOList.set(categoryMapper.getCategoryByTenantIds(mapList));
        }
        // 构建 TreeNode
        return categoryDOList.get().stream()
                .map(e -> new TreeNode<>(e.getId(), e.getParentId(), e.getCateName(), e.getSortNum())
                        .setExtra(MapUtil.<String, Object>builder()
                                .put("cateCode", e.getCateCode())
                                .build()))
                .collect(Collectors.toList());
    }

    @Override
    public List<Map<String, Object>> getPlatAllTenantId(Long tenantId) {
        return categoryMapper.getPlatAllTenantId(tenantId);
    }

    @Override
    public List<TreeNode> getCategoryTreeList(CategoryListReqVO reqVO) {
        if (ObjectUtil.isNull(reqVO.getTenantId())) {
            reqVO.setTenantId(TenantContextHolder.getTenantId());
        } else {
            Map<String, Object> map = categoryMapper.getPlatTenantId(TenantContextHolder.getTenantId());
            reqVO.setTenantId(MapUtil.getLong(map, "tenant_id", 1L));
        }
        AtomicReference<List<CategoryDO>> categoryDOList = new AtomicReference<>(new ArrayList<>());
        TenantUtils.execute(reqVO.getTenantId(), () -> categoryDOList.set(
                categoryMapper.selectList(new LambdaQueryWrapperX<CategoryDO>()
                        .eqIfPresent(CategoryDO::getType, reqVO.getType())
                        .eqIfPresent(CategoryDO::getUseStatus, reqVO.getUseStatus())
                        .eq(CategoryDO::getDeleted, false)
                )));

        // 构建 TreeNode
        return categoryDOList.get().stream()
                .map(e -> new TreeNode<>(e.getId(), e.getParentId(), e.getCateName(), e.getSortNum())
                        .setExtra(MapUtil.<String, Object>builder()
                                .put("cateCode", e.getCateCode())
                                .put("sort", e.getSortNum())
                                .build()))
                .collect(Collectors.toList());
    }

    @Override
    public List<CategoryDO> getCategoryList(CategoryListReqVO reqVO) {
        return categoryMapper.selectList(reqVO);
    }

    @Override
    public List<CategoryRespVO> selectListWithSupplierNum(CategoryPageReqVO reqVO) {
        return categoryMapper.selectListWithSupplierNum(reqVO);
    }

    /**
     * @param catalogues
     * @param businessType 业务类型 1.栏目 2.分类
     * @return
     */
    @Override
    public List<CategoryRespVO> selectListByCatalogues(Long catalogues, Integer businessType) {
        return categoryMapper.selectListByCatalogues(catalogues.toString(), businessType);
    }

    @Override
    public List<AppCategoryRespVO> getCategoryList(AppCategoryReqVO reqVO) {
        CategoryListReqVO categoryReqVO = BeanUtils.toBean(reqVO, CategoryListReqVO.class);
        Long tenantId = TenantContextHolder.getTenantId();
        categoryReqVO.setTenantId(tenantId);
        categoryReqVO.setParentId(reqVO.getId());
        List<CategoryDO> categoryList = getCategoryList(categoryReqVO);
        List<AppCategoryRespVO> appCategoryRespVOS = BeanUtils.toBean(categoryList, AppCategoryRespVO.class);
        for (AppCategoryRespVO respVO : appCategoryRespVOS) {
            CategoryExtraDO categoryExtraDO = categoryExtraMapper.selectById(respVO.getId());
            respVO.setExtraInfo(BeanUtils.toBean(categoryExtraDO, CategoryExtraRespVO.class));
        }
        if (reqVO.getEnableHotAds() != null) {
            appCategoryRespVOS = appCategoryRespVOS.stream().filter(e -> Objects.equals(e.getExtraInfo().getEnableHotAds(), reqVO.getEnableHotAds())).collect(Collectors.toList());
        }
        return appCategoryRespVOS;
    }



    @Override
    @TenantIgnore
    public List<Map<String, Object>> getCategoryExtraList(AppCategoryReqVO reqVO) {
        return null;
    }

    @Override
    public List<CategoryRespVO> getListByIds(CategoryListReqVO reqVO) {
        return categoryMapper.getListByIds(reqVO);
    }

    @Override
    public List<CategoryRespVO> getCategoryRespListByIds(Long id) {
        return categoryMapper.getAllUpCategoryById(id, 1);
    }

    @Override
    public List<CategoryDO> getListByIds(List<Long> ids) {
        if(ids.isEmpty()) {
            return Collections.emptyList();
        }
        return categoryMapper.selectByIds(ids);
    }

    private String getAllParentIds(Long id) {
        if (0L == id) {
            return "";
        }
        List<Long> parentIds = new ArrayList<>();
        parentIds.add(id);
        CategoryDO category = this.getCategory(id);
        Long parentId = category.getParentId();

        while (parentId != 0L) {
            parentIds.add(parentId);
            category = this.getCategory(parentId);
            parentId = category.getParentId();
        }
        return parentIds.stream().map(Object::toString)
                .collect(Collectors.joining(","));
    }


}
