package tech.easyflow.skill.service.impl;

import com.mybatisflex.core.query.QueryWrapper;
import com.mybatisflex.spring.service.impl.ServiceImpl;
import org.springframework.stereotype.Service;
import tech.easyflow.common.entity.LoginAccount;
import tech.easyflow.common.satoken.util.SaTokenUtil;
import tech.easyflow.common.web.exceptions.BusinessException;
import tech.easyflow.skill.entity.SkillCategory;
import tech.easyflow.skill.mapper.SkillCategoryMapper;
import tech.easyflow.skill.service.SkillCategoryService;

import java.math.BigInteger;
import java.util.Date;

/**
 * Skill 分类服务实现。
 */
@Service
public class SkillCategoryServiceImpl extends ServiceImpl<SkillCategoryMapper, SkillCategory> implements SkillCategoryService {

    private static final int MAX_LEVEL = 3;

    /**
     * {@inheritDoc}
     */
    @Override
    public void validateUsableCategory(BigInteger categoryId) {
        if (categoryId == null) {
            return;
        }
        SkillCategory category = getById(categoryId);
        if (category == null) {
            throw new BusinessException("Skill 分类不存在");
        }
        if (category.getLevelNo() != null && category.getLevelNo() > MAX_LEVEL) {
            throw new BusinessException("Skill 分类最多支持三级");
        }
        if (category.getStatus() != null && category.getStatus() != 1) {
            throw new BusinessException("Skill 分类不可用");
        }
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public boolean save(SkillCategory entity) {
        applyCategoryFields(entity);
        return super.save(entity);
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public boolean updateById(SkillCategory entity) {
        applyCategoryFields(entity);
        return super.updateById(entity);
    }

    /**
     * 判断分类下是否存在子分类。
     *
     * @param categoryId 分类 ID
     * @return 存在子分类时返回 true
     */
    public boolean hasChildren(BigInteger categoryId) {
        if (categoryId == null) {
            return false;
        }
        return count(QueryWrapper.create().eq(SkillCategory::getParentId, categoryId)) > 0;
    }

    private void applyCategoryFields(SkillCategory category) {
        if (category == null) {
            throw new BusinessException("Skill 分类不能为空");
        }
        if (category.getCategoryName() == null || category.getCategoryName().isBlank()) {
            throw new BusinessException("Skill 分类名称不能为空");
        }
        SkillCategory parent = null;
        if (category.getParentId() != null) {
            parent = getById(category.getParentId());
            if (parent == null) {
                throw new BusinessException("父级 Skill 分类不存在");
            }
            if (category.getId() != null && category.getId().equals(category.getParentId())) {
                throw new BusinessException("父级分类不能是自身");
            }
        }
        int level = parent == null ? 1 : (parent.getLevelNo() == null ? 1 : parent.getLevelNo()) + 1;
        if (level > MAX_LEVEL) {
            throw new BusinessException("Skill 分类最多支持三级");
        }
        LoginAccount account = SaTokenUtil.getLoginAccount();
        Date now = new Date();
        category.setLevelNo(level);
        category.setAncestors(parent == null ? "" : appendAncestor(parent));
        category.setStatus(category.getStatus() == null ? 1 : category.getStatus());
        category.setSortNo(category.getSortNo() == null ? 0 : category.getSortNo());
        if (category.getId() == null) {
            category.setTenantId(account.getTenantId());
            category.setCreated(now);
            category.setCreatedBy(account.getId());
        }
        category.setModified(now);
        category.setModifiedBy(account.getId());
    }

    private String appendAncestor(SkillCategory parent) {
        String ancestors = parent.getAncestors() == null || parent.getAncestors().isBlank()
                ? String.valueOf(parent.getId())
                : parent.getAncestors() + "," + parent.getId();
        if (ancestors.length() > 512) {
            throw new BusinessException("Skill 分类层级路径过长");
        }
        return ancestors;
    }
}
