package com.eitc.patient.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.eitc.common.utils.SecurityUtils;
import com.eitc.common.utils.bean.BeanUtils;
import com.eitc.patient.domain.DiagnosisType;
import com.eitc.patient.dto.DiagnosisTypeOrderDoctorDto;
import com.eitc.patient.mapper.DiagnosisTypeMapper;
import com.eitc.patient.service.IDiagnosisTypeOrderDoctorService;
import com.eitc.patient.service.IDiagnosisTypeService;
import com.eitc.patient.tree.DiagnosisTypeTree;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * DiagnosisTypeServiceImpl
 *
 * @author mtx
 * @date: 2024/05/17 15:39
 */
@Service
public class DiagnosisTypeServiceImpl extends ServiceImpl<DiagnosisTypeMapper, DiagnosisType> implements IDiagnosisTypeService {

    @Resource
    private IDiagnosisTypeOrderDoctorService diagnosisTypeOrderDoctorService;

    /**
     * 获取面包屑
     *
     * @param parentId id
     * @return 字符串
     * @author mtx
     * @date: 2024/5/31 10:12
     */
    @Override
    public String findCrumb(String parentId) {
        if (!"0".equals(parentId)) {
            // 获取父级
            DiagnosisType service = this.getById(parentId);
            String diagnosisName = service.getDiagnosisName();
            // 循环添加子集面包屑
            String s = findCrumb(service.getParentId());
            if (StringUtils.isNotBlank(s)) {
                return s + " > " + diagnosisName;
            } else {
                return diagnosisName;
            }
        }
        return "";
    }

    /**
     * 根据搜索条件查询所有的诊断分类
     *
     * @param diagnosisType 搜索条件
     * @return 列表
     */
    @Override
    public List<DiagnosisType> getDiagnosisTypes(DiagnosisType diagnosisType) {
        LambdaQueryWrapper<DiagnosisType> eq = Wrappers.<DiagnosisType>lambdaQuery()
                .eq(StringUtils.isNotBlank(diagnosisType.getDiagnosisName()), DiagnosisType::getDiagnosisName, diagnosisType.getDiagnosisName())
                .orderByDesc(DiagnosisType::getDiagnosisName);

        return this.list(eq);
    }

    /**
     * 封装属性结构
     *
     * @param parentId 父级id
     * @param list     数据
     * @return 封装好的数据
     */
    @Override
    public List<DiagnosisTypeTree> getChildren(String parentId, List<DiagnosisTypeTree> list) {
        return list.stream().filter(t -> Objects.equals(t.getParentId(), parentId)).peek(
                m -> m.setChildrenList(getChildren(m.getId(), list))
        ).collect(Collectors.toList());
    }

    /**
     * 根据医生ID查找诊断类型树形列表。
     * 该方法主要用于获取与医生相关的诊断类型树，用于前端展示或筛选。
     * 如果医生没有关联的诊断类型，则返回所有的诊断类型树。
     *
     * @return 树形结构列表，包含诊断类型信息。
     */
    @Override
    public List<DiagnosisTypeTree> findTreeList() {
        // 根据当前登录用户的ID查找与其关联的诊断类型订单
        List<DiagnosisTypeOrderDoctorDto> dtoList = diagnosisTypeOrderDoctorService.findListByDoctorId(String.valueOf(SecurityUtils.getUserId()));
        // 用于存储诊断类型ID和对应的诊断类型ID的映射
        Map<String, String> map = new HashMap<>();
        // 初始化诊断类型列表
        List<DiagnosisType> list = new ArrayList<>();

        // 如果关联的诊断类型订单列表为空，则直接获取所有的诊断类型
        if (CollectionUtils.isEmpty(dtoList)) {
            list = this.getDiagnosisTypes(new DiagnosisType());
        } else {
            // 遍历关联的诊断类型订单，转换为诊断类型对象，并存储映射关系
            for (DiagnosisTypeOrderDoctorDto dto : dtoList) {
                DiagnosisType dt = new DiagnosisType();
                BeanUtils.copyProperties(dto, dt);
                map.put(dto.getId(), dto.getDiagnosisTypeId());
                list.add(dt);
            }
        }

        // 将诊断类型列表转换为树形结构列表
        List<DiagnosisTypeTree> treeBeans = new ArrayList<>();
        list.forEach(t -> {
            DiagnosisTypeTree diagnosisTypeTree = new DiagnosisTypeTree();
            BeanUtils.copyProperties(t, diagnosisTypeTree);
            treeBeans.add(diagnosisTypeTree);
        });

        // 获取树形结构中的根节点
        List<DiagnosisTypeTree> children = this.getChildren("0", treeBeans);
        // 将映射关系中的诊断类型ID设置到树形结构中，用于后续的关联操作
        setTreeIdToDiagnosisTypeId(children, map);

        return children;
    }


    /**
     * 将诊断类型树的ID设置为诊断类型ID的映射值。
     * 此方法递归处理一个诊断类型树列表，将每个节点的ID替换为映射表中对应的值。
     * 这样做的目的是为了更新树结构中节点的ID，确保ID的唯一性和一致性。
     *
     * @param list 诊断类型树列表，包含待处理的树结构。
     * @param map  用于映射旧ID到新ID的映射表，提供ID的替换规则。
     */
    public void setTreeIdToDiagnosisTypeId(List<DiagnosisTypeTree> list, Map<String, String> map) {
        // 检查列表是否为空，如果为空则直接返回，无需处理。
        if (CollectionUtils.isEmpty(list)) {
            return;
        }
        // 遍历列表中的每个诊断类型树节点。
        for (DiagnosisTypeTree diagnosisTypeTree : list) {
            // 递归处理当前节点的子节点列表，确保树结构的所有节点都被处理。
            List<DiagnosisTypeTree> childrenList = diagnosisTypeTree.getChildrenList();
            setTreeIdToDiagnosisTypeId(childrenList, map);
            // 使用映射表中旧ID对应的 新ID 更新当前节点的ID。
            if (StringUtils.isNotBlank(map.get(diagnosisTypeTree.getId()))) {
                diagnosisTypeTree.setId(map.get(diagnosisTypeTree.getId()));
            }
        }
    }


}
