package com.jeesharp.business.modules.mall.service.impl;

import cn.hutool.core.util.StrUtil;
import com.jeesharp.business.modules.mall.entity.MallCategory;
import com.jeesharp.business.modules.mall.enums.MallCategoryStatusEnum;
import com.jeesharp.business.modules.mall.mapper.MallCategoryMapper;
import com.jeesharp.business.modules.mall.service.MallCategoryService;
import com.jeesharp.business.modules.common.constants.PlatformTenantConstants;
import com.jeesharp.business.modules.mall.vo.MallCategoryQueryVO;
import com.jeesharp.framework.mybatis.core.service.CrudService;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Deque;
import java.util.HashMap;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * 商品分类 Service 实现类
 */
@Service
@Transactional(readOnly = true)
public class MallCategoryServiceImpl extends CrudService<MallCategoryMapper, MallCategory, MallCategoryQueryVO> implements MallCategoryService {

    private static final String IDS_SEPARATOR = ",";

    @Override
    public List<MallCategory> listEnabledForPortal() {
        MallCategoryQueryVO query = new MallCategoryQueryVO();
        query.setStatus(MallCategoryStatusEnum.ENABLED.getValue());
        query.setOrderBy("sortOrder asc");
        return findList(query);
    }

    @Override
    @Transactional(readOnly = false)
    public void createCategory(MallCategory entity) {
        save(entity);
    }

    @Override
    @Transactional(readOnly = false)
    public void updateCategory(MallCategory entity) {
        update(entity);
    }

    @Override
    public List<MallCategory> listByTemplateId(String templateId) {
        if (StrUtil.isBlank(templateId)) {
            return List.of();
        }
        return mapper.selectByTemplateId(PlatformTenantConstants.PLATFORM_TENANT_CODE, templateId.trim());
    }

    @Override
    public List<MallCategory> listByTemplateIds(List<String> templateIds) {
        if (templateIds == null || templateIds.isEmpty()) {
            return List.of();
        }
        List<String> tids = templateIds.stream()
            .filter(StrUtil::isNotBlank)
            .map(String::trim)
            .distinct()
            .collect(Collectors.toList());
        if (tids.isEmpty()) {
            return List.of();
        }
        return mapper.selectByTemplateIds(PlatformTenantConstants.PLATFORM_TENANT_CODE, tids);
    }

    @Override
    public List<MallCategory> listByIds(List<String> ids) {
        if (ids == null || ids.isEmpty()) {
            return List.of();
        }
        List<String> idList = ids.stream()
            .filter(StrUtil::isNotBlank)
            .map(String::trim)
            .distinct()
            .collect(Collectors.toList());
        if (idList.isEmpty()) {
            return List.of();
        }
        return mapper.selectByIds(PlatformTenantConstants.PLATFORM_TENANT_CODE, idList);
    }

    @Override
    public List<MallCategory> listPlatformEnabledForPublish() {
        return mapper.selectEnabledByTenantCode(PlatformTenantConstants.PLATFORM_TENANT_CODE);
    }

    @Override
    public boolean hasChildCategory(String parentId) {
        if (StrUtil.isBlank(parentId)) {
            return false;
        }
        return mapper.countChildrenByParentId(PlatformTenantConstants.PLATFORM_TENANT_CODE, parentId.trim()) > 0;
    }

    @Override
    public List<String> listSelfAndDescendantIds(String categoryId) {
        if (StrUtil.isBlank(categoryId)) {
            return List.of();
        }
        String rootId = categoryId.trim();
        List<MallCategory> all = listEnabledForPortal();
        Map<String, List<String>> childrenByParent = new HashMap<>();
        for (MallCategory category : all) {
            if (category == null || StrUtil.isBlank(category.getId())) {
                continue;
            }
            String parentKey = normalizeParentKey(category.getParentId());
            childrenByParent.computeIfAbsent(parentKey, key -> new ArrayList<>()).add(category.getId().trim());
        }
        LinkedHashSet<String> ids = new LinkedHashSet<>();
        Deque<String> queue = new ArrayDeque<>();
        queue.add(rootId);
        while (!queue.isEmpty()) {
            String currentId = queue.poll();
            if (StrUtil.isBlank(currentId) || !ids.add(currentId.trim())) {
                continue;
            }
            List<String> children = childrenByParent.get(currentId.trim());
            if (children != null) {
                for (String childId : children) {
                    if (StrUtil.isNotBlank(childId)) {
                        queue.add(childId.trim());
                    }
                }
            }
        }
        return new ArrayList<>(ids);
    }

    private static String normalizeParentKey(String parentId) {
        if (StrUtil.isBlank(parentId)) {
            return "0";
        }
        return parentId.trim();
    }

    @Override
    public String resolveInheritedTemplateId(String categoryId) {
        if (StrUtil.isBlank(categoryId)) {
            return null;
        }
        String cur = categoryId.trim();
        for (int guard = 0; guard < 64 && StrUtil.isNotBlank(cur); guard++) {
            MallCategory cat = get(cur);
            if (cat == null) {
                return null;
            }
            if (StrUtil.isNotBlank(cat.getTemplateId())) {
                return cat.getTemplateId().trim();
            }
            String pid = cat.getParentId();
            if (StrUtil.isBlank(pid) || "0".equals(pid.trim())) {
                break;
            }
            cur = pid.trim();
        }
        return null;
    }
}
