package com.bonus.material.tool.service.Impl;

import com.bonus.common.core.web.domain.AjaxResult;
import com.bonus.common.security.utils.SecurityUtils;
import com.bonus.material.tool.domain.ToolEntity;
import com.bonus.material.tool.mapper.ToolMapper;
import com.bonus.material.tool.service.ToolService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;

import static com.bonus.common.biz.constant.MaterialConstants.ADMIN_ID;
import static com.bonus.common.biz.constant.MaterialConstants.PROVINCE_COMPANY_DEPT_ID;

@Service
public class ToolServiceImpl implements ToolService {
    private static final Logger log = LoggerFactory.getLogger(ToolServiceImpl.class);
    @Resource
    private ToolMapper toolMapper;

    /**
     * 工具类型树
     *
     * @param entity 实体
     * @return 树结构
     */
    @Override
    public AjaxResult getTreeSelect(ToolEntity entity) {
        // 1. 按条件查询目标节点（符合筛选条件的节点）
        List<ToolEntity> allNodes = toolMapper.getTreeSelect(entity);
        // 2. 找出所有根节点（parent_id = null 或 parent_id = 0，根据业务调整）
        List<ToolEntity> rootNodes = allNodes.stream().filter(node -> node.getParentId() == null || node.getParentId() == 0).collect(Collectors.toList());
        // 3. 为每个根节点递归添加子节点
        for (ToolEntity root : rootNodes) {
            addChildren(root, allNodes);
        }
        return AjaxResult.success(rootNodes);
    }

    /**
     * 工具类型表格
     *
     * @param entity 实体
     * @return 表格
     */
    @Override
    public List<ToolEntity> list(ToolEntity entity) {

        return toolMapper.list(entity);
    }

    /**
     * 工具类型新增
     *
     * @param entity 实体
     * @return 表格
     */
    @Override
    public AjaxResult add(ToolEntity entity) {
        // 1. 校验父节点ID是否存在（避免空指针）
        Long parentId = entity.getParentId();
        if (parentId == null) {
            log.warn("新增工具类型失败：父节点ID不能为空");
            return AjaxResult.error("父节点ID不能为空，新增失败");
        }

        try {
            // 2. 查询父节点信息（校验父节点有效性）
            ToolEntity parentTool = toolMapper.getToolByTypeId(parentId);
            if (parentTool == null) {
                log.warn("新增工具类型失败：父节点不存在，parentId={}", parentId);
                return AjaxResult.error("父节点不存在，新增失败");
            }

            // 3. 校验父节点层级（限制最大层级为5，子节点即6级）
            String parentLevel = parentTool.getLevel();
            if (parentLevel == null || parentLevel.trim().isEmpty()) {
                log.error("新增工具类型失败：父节点层级未设置，parentId={}", parentId);
                return AjaxResult.error("父节点信息异常，新增失败");
            }
            int parentLevelNum;
            try {
                parentLevelNum = Integer.parseInt(parentLevel.trim());
            } catch (NumberFormatException e) {
                log.error("新增工具类型失败：父节点层级格式错误（非数字），parentLevel={}", parentLevel, e);
                return AjaxResult.error("父节点层级异常，新增失败");
            }
            if (parentLevelNum > 4) {
                log.warn("新增工具类型失败：父节点层级超过限制（最大4级），parentLevel={}", parentLevel);
                return AjaxResult.error("父节点层级超过上限（最大支持4级），无法新增子节点");
            }

            // 4. 校验同层级下名称是否重复（避免重复新增）
            int sameNameCount = toolMapper.getToolByTypeIdAndTypeName(entity);
            if (sameNameCount > 0) {
                log.warn("新增工具类型失败：同层级下名称已存在，typeName={}, parentId={}", entity.getTypeName(), parentId);
                return AjaxResult.error("当前分类下已存在同名类型，新增失败");
            }


            // 5. 设置当前节点层级（父层级+1）
            entity.setLevel(String.valueOf(parentLevelNum + 1));
            entity.setCreateBy(SecurityUtils.getLoginUser().getSysUser().getNickName());
            // 7. 执行新增操作
            int insertNum = toolMapper.add(entity);
            if (insertNum > 0) {
                //toolMapper.addLedger(entity.getTypeId());
                log.info("新增工具类型成功：typeId={}, typeName={}", entity.getTypeId(), entity.getTypeName());
                return AjaxResult.success("新增成功", entity.getTypeId()); // 返回新增ID，便于前端使用
            } else {
                log.error("新增工具类型失败：数据库插入受影响行数为0，entity={}", entity);
                return AjaxResult.error("新增失败，请重试");
            }

        } catch (Exception e) {
            // 捕获所有未预期异常，记录详细日志
            log.error("新增工具类型发生异常：entity={}", entity, e);
            return AjaxResult.error("系统异常，新增失败");
        }
    }

    /**
     * 修改工具类型
     *
     * @param entity 工具类型实体（含更新后的数据）
     * @return 操作结果
     */
    @Override
    public AjaxResult update(ToolEntity entity) {
        // 1. 校验主键ID是否存在
        Long typeId = entity.getTypeId();
        if (typeId == null) {
            log.warn("修改工具类型失败：主键ID不能为空");
            return AjaxResult.error("主键ID不能为空，修改失败");
        }

        try {
            // 2. 查询当前节点原始信息（用于对比变更和校验）
            ToolEntity originalTool = toolMapper.getToolByTypeId(typeId);
            if (originalTool == null) {
                log.warn("修改工具类型失败：当前节点不存在，typeId={}", typeId);
                return AjaxResult.error("当前节点不存在，修改失败");
            }

            // 3. 处理父节点变更（若父节点ID有修改）
            Long newParentId = entity.getParentId();
            Long oldParentId = originalTool.getParentId();
            ToolEntity newParentTool = null;

            if (!Objects.equals(newParentId, oldParentId)) {
                // 3.1 新父节点ID非空校验
                if (newParentId == null) {
                    log.warn("修改工具类型失败：新父节点ID不能为空，typeId={}", typeId);
                    return AjaxResult.error("新父节点ID不能为空，修改失败");
                }

                // 3.2 校验新父节点是否存在
                newParentTool = toolMapper.getToolByTypeId(newParentId);
                if (newParentTool == null) {
                    log.warn("修改工具类型失败：新父节点不存在，newParentId={}, typeId={}", newParentId, typeId);
                    return AjaxResult.error("新父节点不存在，修改失败");
                }

                // 3.3 禁止自引用（父节点ID不能是自身ID）
                if (newParentId.equals(typeId)) {
                    log.warn("修改工具类型失败：新父节点ID不能是自身，typeId={}", typeId);
                    return AjaxResult.error("父节点不能选择自身，修改失败");
                }

                // 3.4 校验新父节点层级（最大5级，子节点即6级）
                String newParentLevel = newParentTool.getLevel();
                if (newParentLevel == null || newParentLevel.trim().isEmpty()) {
                    log.error("修改工具类型失败：新父节点层级未设置，newParentId={}", newParentId);
                    return AjaxResult.error("新父节点信息异常，修改失败");
                }
                int newParentLevelNum;
                try {
                    newParentLevelNum = Integer.parseInt(newParentLevel.trim());
                } catch (NumberFormatException e) {
                    log.error("修改工具类型失败：新父节点层级格式错误，newParentLevel={}", newParentLevel, e);
                    return AjaxResult.error("新父节点层级异常，修改失败");
                }
                if (newParentLevelNum > 4) {
                    log.warn("修改工具类型失败：新父节点层级超过上限，newParentLevel={}", newParentLevel);
                    return AjaxResult.error("新父节点层级超过上限（最大支持4级），无法作为父节点");
                }
            }

            // 4. 校验名称是否重复（同层级下不允许重名）
            // 构建查询条件：同父节点+同名称+排除自身ID
            ToolEntity query = new ToolEntity();
            query.setParentId(Objects.isNull(newParentId) ? oldParentId : newParentId); // 父节点取新值（若有变更）
            query.setTypeName(entity.getTypeName());
            query.setTypeId(typeId); // 用于排除自身

            int sameNameCount = toolMapper.countSameNameInSameLevel(query);
            if (sameNameCount > 0) {
                log.warn("修改工具类型失败：同层级下名称已存在，typeName={}, parentId={}, typeId={}", entity.getTypeName(), query.getParentId(), typeId);
                return AjaxResult.error("当前分类下已存在同名类型，修改失败");
            }
            // 5. 调整层级（若父节点变更，需同步更新自身层级）
            if (newParentTool != null) {
                int newParentLevelNum = Integer.parseInt(newParentTool.getLevel().trim());
                entity.setLevel(String.valueOf(newParentLevelNum + 1));
            }
            entity.setUpdateBy(SecurityUtils.getLoginUser().getSysUser().getNickName());
            // 6. 补充更新信息
            entity.setUpdateTime(LocalDateTime.now()); // 强制更新时间为当前时间

            // 7. 执行更新操作
            int updateNum = toolMapper.update(entity);
            if (updateNum > 0) {
                log.info("修改工具类型成功：typeId={}, typeName={}", typeId, entity.getTypeName());
                return AjaxResult.success("修改成功");
            } else {
                log.error("修改工具类型失败：数据库更新受影响行数为0，entity={}", entity);
                return AjaxResult.error("修改失败，请重试");
            }

        } catch (Exception e) {
            log.error("修改工具类型发生异常：typeId={}, entity={}", typeId, entity, e);
            return AjaxResult.error("系统异常，修改失败");
        }
    }

    /**
     * 删除工具类型（逻辑删除）
     *
     * @param entity 实体
     * @return 操作结果
     */
    @Override
    public AjaxResult delete(ToolEntity entity) {
        // 1. 校验主键ID
        if (entity.getTypeId() == null) {
            log.warn("删除工具类型失败：主键ID不能为空");
            return AjaxResult.error("主键ID不能为空，删除失败");
        }

        try {
            // 2. 校验当前节点是否存在
            ToolEntity tool = toolMapper.getToolByTypeId(entity.getTypeId());
            if (tool == null) {
                log.warn("删除工具类型失败：节点不存在，typeId={}", entity.getTypeId());
                return AjaxResult.error("节点不存在，删除失败");
            }

            // 3. 校验是否存在子节点（核心逻辑）
            int childrenCount = toolMapper.countChildren(entity);
            if (childrenCount > 0) {
                log.warn("删除工具类型失败：存在子节点，不允许删除，typeId={}, 子节点数量={}", entity.getTypeId(), childrenCount);
                return AjaxResult.error("该节点存在子节点，请先删除子节点后再试");
            }

            // 4. 执行逻辑删除
            ToolEntity deleteEntity = new ToolEntity();
            deleteEntity.setTypeId(entity.getTypeId());
            deleteEntity.setUpdateBy(SecurityUtils.getLoginUser().getSysUser().getNickName());
            deleteEntity.setUpdateTime(LocalDateTime.now());

            int deleteNum = toolMapper.delete(deleteEntity);
            if (deleteNum > 0) {
                log.info("删除工具类型成功：typeId={}, operator={}", entity.getTypeId(), SecurityUtils.getLoginUser().getSysUser().getNickName());
                return AjaxResult.success("删除成功");
            } else {
                log.error("删除工具类型失败：数据库更新受影响行数为0，typeId={}", entity.getTypeId());
                return AjaxResult.error("删除失败，请重试");
            }

        } catch (Exception e) {
            log.error("删除工具类型发生异常：typeId={}", entity.getTypeId(), e);
            return AjaxResult.error("系统异常，删除失败");
        }
    }

    /**
     * 获取下拉选
     *
     * @param query
     * @return 集合
     */
    @Override
    public AjaxResult getSelect(ToolEntity query) {
        try {
            List<Map<String, Object>> select = toolMapper.getSelect(query);
            return AjaxResult.success(select);
        } catch (Exception e) {
            log.error(e.getMessage(), e);
            return AjaxResult.error();
        }
    }

    /**
     * 工具租赁价（批量）修改
     * @param info
     * @return
     */
    @Override
    public Integer updateLeasePrice(ToolEntity info) {
        return toolMapper.updateLeasePrice(info.getTypeIds(), info.getLeasePrice());
    }


    /**
     * 递归为父节点添加子节点
     *
     * @param parent   父节点
     * @param allNodes 所有节点列表
     */
    private void addChildren(ToolEntity parent, List<ToolEntity> allNodes) {
        // 筛选当前父节点的子节点（parent_id = 父节点的 type_id）
        List<ToolEntity> children = allNodes.stream().filter(node -> parent.getTypeId().equals(node.getParentId())).collect(Collectors.toList());

        // 为父节点设置子节点
        parent.setChildren(children);

        // 递归为子节点添加它们的子节点
        for (ToolEntity child : children) {
            addChildren(child, allNodes);
        }
    }
}
