package com.xinelu.manage.service.agency.impl;

import com.xinelu.common.constant.Constants;
import com.xinelu.common.core.domain.AjaxResult;
import com.xinelu.common.core.domain.entity.SysRole;
import com.xinelu.common.enums.NodeTypeEnum;
import com.xinelu.common.exception.ServiceException;
import com.xinelu.common.utils.SecurityUtils;
import com.xinelu.common.utils.bean.BeanUtils;
import com.xinelu.common.utils.codes.GenerateSystemCodeUtil;
import com.xinelu.common.utils.regex.RegexUtil;
import com.xinelu.manage.domain.agency.Agency;
import com.xinelu.manage.domain.agencycategory.AgencyCategory;
import com.xinelu.manage.domain.department.Department;
import com.xinelu.manage.dto.agency.AgencyDTO;
import com.xinelu.manage.dto.agency.AgencyTreeDto;
import com.xinelu.manage.dto.agency.HospitalDTO;
import com.xinelu.manage.mapper.agency.AgencyMapper;
import com.xinelu.manage.mapper.department.DepartmentMapper;
import com.xinelu.manage.mapper.sysarea.SysAreaMapper;
import com.xinelu.manage.service.agency.IAgencyService;
import com.xinelu.manage.vo.agency.AgencyTreeVO;
import com.xinelu.manage.vo.agency.AgencyVO;
import com.xinelu.manage.vo.agency.HospitalVO;
import com.xinelu.manage.vo.sysarea.SysAreaVO;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;
import javax.annotation.Resource;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.BooleanUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;


/**
 * 机构信息Service业务层处理
 *
 * @author xinelu
 * @date 2024-02-26
 */
@Service
public class AgencyServiceImpl implements IAgencyService {
    @Resource
    private AgencyMapper agencyMapper;
    @Resource
    private RegexUtil regexUtil;
    @Resource
    private SysAreaMapper sysAreaMapper;
    @Resource
    private DepartmentMapper departmentMapper;
    @Resource
    private GenerateSystemCodeUtil generateSystemCodeUtil;


    /**
     * 查询机构信息
     *
     * @param id 机构信息主键
     * @return 机构信息
     */
    @Override
    public AgencyVO selectAgencyById(Long id) {
        AgencyVO agency = agencyMapper.selectAgencyVOById(id);
        if (Objects.nonNull(agency) && StringUtils.isNotBlank(agency.getAreaCode())) {
            SysAreaVO nurseStationAndAreaCode = sysAreaMapper.getSubordinateRegionsFindSuperiorRegions(agency.getAreaCode());
            if (Objects.nonNull(nurseStationAndAreaCode)) {
                agency.setProvinceCode(StringUtils.isBlank(nurseStationAndAreaCode.getProvinceCode()) ? "" : nurseStationAndAreaCode.getProvinceCode());
                agency.setProvinceName(StringUtils.isBlank(nurseStationAndAreaCode.getProvinceName()) ? "" : nurseStationAndAreaCode.getProvinceName());
                agency.setCityCode(StringUtils.isBlank(nurseStationAndAreaCode.getCityCode()) ? "" : nurseStationAndAreaCode.getCityCode());
                agency.setCityName(StringUtils.isBlank(nurseStationAndAreaCode.getCityName()) ? "" : nurseStationAndAreaCode.getCityName());
                agency.setRegionCode(StringUtils.isBlank(nurseStationAndAreaCode.getRegionCode()) ? "" : nurseStationAndAreaCode.getRegionCode());
                agency.setRegionName(StringUtils.isBlank(nurseStationAndAreaCode.getRegionName()) ? "" : nurseStationAndAreaCode.getRegionName());
                agency.setStreetCode(StringUtils.isBlank(nurseStationAndAreaCode.getStreetCode()) ? "" : nurseStationAndAreaCode.getStreetCode());
                agency.setStreetName(StringUtils.isBlank(nurseStationAndAreaCode.getStreetName()) ? "" : nurseStationAndAreaCode.getStreetName());
                agency.setCommunityCode(StringUtils.isBlank(nurseStationAndAreaCode.getCommunityCode()) ? "" : nurseStationAndAreaCode.getCommunityCode());
                agency.setCommunityName(StringUtils.isBlank(nurseStationAndAreaCode.getCommunityName()) ? "" : nurseStationAndAreaCode.getCommunityName());
            }
        }
        return agency;
    }

    /**
     * 查询机构信息列表
     *
     * @param agency 机构信息
     * @return 机构信息
     */
    @Override
    public List<Agency> selectAgencyList(Agency agency) {
        return agencyMapper.selectAgencyList(agency);
    }

    /**
     * 查询机构信息列表
     *
     * @param agency 机构信息
     * @return 机构信息
     */
    @Override
    public List<Agency> selectAgencyByIdList(Agency agency) {
		// 查询用户角色
	    List<SysRole> roleList = SecurityUtils.getLoginUser().getUser().getRoles();
		if (CollectionUtils.isNotEmpty(roleList)) {
			List<String> dataScopeList = roleList.stream().map(SysRole::getDataScope).collect(Collectors.toList());
			if (!dataScopeList.contains("1")) { // 不是全部数据权限，就只查询本机构
				agency.setId(SecurityUtils.getLoginUser().getUser().getHospitalAgencyId());
			}
		}
        return agencyMapper.selectAgencyList(agency);
    }


    /**
     * 新增机构信息
     *
     * @param agency 机构信息
     * @return 结果
     */
    @Override
    public AjaxResult insertAgency(Agency agency) {
        int i = agencyMapper.selectAgencyNameByAgencyNameInt(agency.getAgencyName());
        if (i > 0) {
            return AjaxResult.error("该名称" + agency.getAgencyName() + "以重复！");
        }
        agency.setCreateTime(LocalDateTime.now());
        agency.setCreateBy(SecurityUtils.getUsername());
        agency.setAgencyCode(Constants.AGENCY_CODE + generateSystemCodeUtil.generateSystemCode(Constants.AGENCY_CODE));
        return AjaxResult.success(agencyMapper.insertAgency(agency));
    }

    /**
     * 修改机构信息
     *
     * @param agency 机构信息
     * @return 结果
     */
    @Override
    public AjaxResult updateAgency(Agency agency) {
        if (Objects.isNull(agency.getId())) {
            return AjaxResult.error("请选择机构信息！");
        }
        Agency dataAgency = agencyMapper.selectAgencyById(agency.getId());
        if (StringUtils.isNotBlank(dataAgency.getAgencyName()) && !agency.getAgencyName().equals(dataAgency.getAgencyName())) {
            int i = agencyMapper.selectAgencyNameByAgencyNameInt(agency.getAgencyName());
            if (i > 0) {
                throw new ServiceException("该名称" + agency.getAgencyName() + "以重复！");
            }
        }
        agency.setUpdateTime(LocalDateTime.now());
        agency.setUpdateBy(SecurityUtils.getUsername());
        return AjaxResult.success(agencyMapper.updateAgencyById(agency));
    }

    /**
     * 批量删除机构信息
     *
     * @param ids 需要删除的机构信息主键
     * @return 结果
     */
    @Override
    public AjaxResult deleteAgencyByIds(Long[] ids) {
        int size = agencyMapper.selectSubordinateAgencyById(ids).size();
        if (size > 0) {
            return AjaxResult.error("该机构存在下级机构，请先删除其下级机构！");
        }
        return AjaxResult.success(agencyMapper.deleteAgencyByIds(ids));
    }

    /**
     * 删除机构信息信息
     *
     * @param id 机构信息主键
     * @return 结果
     */
    @Override
    public int deleteAgencyById(Long id) {
        return agencyMapper.deleteAgencyById(id);
    }

    /**
     * 树图
     *
     * @return AgencyVO
     */
    @Override
    public List<AgencyTreeVO> agencyList() {
		// 根据角色判断取数据
	    AgencyTreeDto query = new AgencyTreeDto();
	    List<SysRole> roleList = SecurityUtils.getLoginUser().getUser().getRoles();
	    if (CollectionUtils.isNotEmpty(roleList)) {
		    List<String> dataScopeList = roleList.stream().map(SysRole::getDataScope).collect(Collectors.toList());
		    if (dataScopeList.contains("1")) {// 全部数据权限
		    } else if (dataScopeList.contains("7")) { // 本机构及下属机构
			    query.setAgencyAndChild("1");
			    query.setId(SecurityUtils.getLoginUser().getUser().getHospitalAgencyId());
		    } else if (dataScopeList.contains("6")) { // 本机构
			    query.setId(SecurityUtils.getLoginUser().getUser().getHospitalAgencyId());
		    }
	    }
        List<AgencyVO> agencies = agencyMapper.selectAgencyVOList(query);
        for (AgencyVO agency : agencies) {
            agency.setValue(agency.getId().toString());
        }
        List<AgencyVO> agenciesTree = buildDeptTree(agencies);
        return agenciesTree.stream().map(AgencyTreeVO::new).collect(Collectors.toList());
    }

    /**
     * 机构信息导入
     *
     * @param agencyList 机构信息
     * @return 导入结果
     **/
    @Transactional(rollbackFor = Exception.class)
    @Override
    public AjaxResult insertAgencyImportList(List<AgencyDTO> agencyList) {
        //判断添加的数据是否为空
        if (CollectionUtils.isEmpty(agencyList)) {
            return AjaxResult.error("请添加机构导入信息！");
        }
        //根据护理站名称做去除处理
        List<AgencyDTO> importDataList = agencyList.stream().filter(item -> StringUtils.isNotBlank(item.getAgencyName())).distinct().collect(Collectors.toList());
        //校验联系电话格式是否正确
        AgencyDTO agency = importDataList.stream().filter(item -> StringUtils.isNotBlank(item.getAgencyPhone())).filter(item -> BooleanUtils.isFalse(regexUtil.regexPhone(item.getAgencyPhone()))).findFirst().orElse(new AgencyDTO());
        if (StringUtils.isNotBlank(agency.getAgencyPhone())) {
            return AjaxResult.error("当前机构联系电话：" + agency.getAgencyPhone() + " 格式不正确，请重新录入！");
        }
        List<String> agencyNames = importDataList.stream().filter(item -> StringUtils.isNotBlank(item.getAgencyName())).map(AgencyDTO::getAgencyName).distinct().collect(Collectors.toList());
        //根据名称查询机构基本信息
        List<AgencyDTO> allAgencyInfo = agencyMapper.getAllAgencyInfo(agencyNames);
        //做差集，去除数据库中已经存在的机构信息
        List<AgencyDTO> subtractList = new ArrayList<>(CollectionUtils.subtract(importDataList, allAgencyInfo));
        if (CollectionUtils.isEmpty(subtractList)) {
            return AjaxResult.success();
        }
        //上级机构查询
        List<AgencyDTO> agencyIds = new ArrayList<>();
        List<String> parentAgencyCodeList = agencyList.stream().filter(Objects::nonNull).map(AgencyDTO::getParentAgencyCode).filter(Objects::nonNull).distinct().collect(Collectors.toList());
        if (CollectionUtils.isNotEmpty(parentAgencyCodeList)) {
            agencyIds = agencyMapper.selectAgencyId(parentAgencyCodeList);
        }
        //机构类别查询
        List<AgencyCategory> agencyCategories = new ArrayList<>();
        List<String> categoryCode = agencyList.stream().filter(Objects::nonNull).map(AgencyDTO::getCategoryCode).filter(Objects::nonNull).distinct().collect(Collectors.toList());
        if (CollectionUtils.isNotEmpty(categoryCode)) {
            agencyCategories = agencyMapper.selectAgencyCategoryId(categoryCode);
        }
        List<Agency> saveAgencyList = new ArrayList<>();
        for (AgencyDTO item : subtractList) {
            if (StringUtils.isBlank(item.getAgencyName())) {
                return AjaxResult.error("机构名称不能为空！");
            }
            item.setCreateBy(SecurityUtils.getUsername());
            item.setCreateTime(LocalDateTime.now());
            Agency newAgency = new Agency();
            BeanUtils.copyProperties(item, newAgency);
            if (CollectionUtils.isNotEmpty(agencyIds)) {
                AgencyDTO agencyDTO = agencyIds.stream().filter(Objects::nonNull).filter(items -> StringUtils.isNotBlank(items.getAgencyCode()) && Objects.nonNull(items.getId()) && items.getAgencyCode().equals(item.getParentAgencyCode())).findFirst().orElse(new AgencyDTO());
                newAgency.setParentId(agencyDTO.getId());
            }
            if (CollectionUtils.isNotEmpty(agencyCategories)) {
                AgencyCategory agencyCategory = agencyCategories.stream().filter(Objects::nonNull).filter(items -> StringUtils.isNotBlank(items.getCategoryCode()) && Objects.nonNull(items.getId()) && items.getCategoryCode().equals(item.getCategoryCode())).findFirst().orElse(new AgencyCategory());
                newAgency.setAgencyCategoryId(agencyCategory.getId());
            }
            newAgency.setAgencyCode(Constants.AGENCY_CODE + generateSystemCodeUtil.generateSystemCode(Constants.AGENCY_CODE));
            saveAgencyList.add(newAgency);
        }
        int insertCount = agencyMapper.insertAgencyImportList(saveAgencyList);
        if (insertCount <= 0) {
            throw new ServiceException("导入护理站信息失败，请联系管理员！");
        }
        return AjaxResult.success();
    }

    /**
     * 医院园区科室病区联动查询
     *
     * @param hospitalDTO 信息
     * @return AjaxResult
     */
    @Override
    public AjaxResult getAgencyList(HospitalDTO hospitalDTO) {
        //只选医院
        HospitalVO hospitalVO = new HospitalVO();
        if (StringUtils.isNotBlank(hospitalDTO.getNodeType()) && NodeTypeEnum.HOSPITAL.getInfo().equals(hospitalDTO.getNodeType()) && Objects.nonNull(hospitalDTO.getHospitalId())) {
            Agency agency = new Agency();
            agency.setNodeType(NodeTypeEnum.CAMPUS.getInfo());
            agency.setParentId(hospitalDTO.getHospitalId());
            List<Agency> campusList = agencyMapper.selectAgencyList(agency);
            hospitalVO.setCampusList(campusList);
            Department department = new Department();
            department.setNodeType(NodeTypeEnum.DEPARTMENT.getInfo());
            department.setHospitalAgencyId(hospitalDTO.getHospitalId());
            List<Department> departmentList = departmentMapper.selectDepartmentList(department);
            hospitalVO.setDepartmentList(departmentList);
            department.setNodeType(NodeTypeEnum.WARD.getInfo());
            List<Department> wardList = departmentMapper.selectDepartmentList(department);
            hospitalVO.setWardList(wardList);
        }
        //选到园区
        if (StringUtils.isNotBlank(hospitalDTO.getNodeType()) && NodeTypeEnum.CAMPUS.getInfo().equals(hospitalDTO.getNodeType()) && Objects.nonNull(hospitalDTO.getCampusId())) {
            Department department = new Department();
            department.setNodeType(NodeTypeEnum.DEPARTMENT.getInfo());
            department.setHospitalAgencyId(hospitalDTO.getCampusId());
            List<Department> departmentList = departmentMapper.selectDepartmentList(department);
            hospitalVO.setDepartmentList(departmentList);
            department.setNodeType(NodeTypeEnum.WARD.getInfo());
            List<Department> wardList = departmentMapper.selectDepartmentList(department);
            hospitalVO.setWardList(wardList);
        }
        //选到科室
        if (StringUtils.isNotBlank(hospitalDTO.getNodeType()) && NodeTypeEnum.DEPARTMENT.getInfo().equals(hospitalDTO.getNodeType()) && Objects.nonNull(hospitalDTO.getDepartmentId())) {
            Department department = new Department();
            department.setNodeType(NodeTypeEnum.WARD.getInfo());
            department.setParentDepartmentId(hospitalDTO.getDepartmentId());
            List<Department> wardList = departmentMapper.selectDepartmentList(department);
            hospitalVO.setWardList(wardList);
        }
        return AjaxResult.success(hospitalVO);
    }

    public List<AgencyVO> buildDeptTree(List<AgencyVO> agencies) {
        List<AgencyVO> returnList = new ArrayList<AgencyVO>();
        List<Long> tempList = new ArrayList<Long>();
        for (AgencyVO agency : agencies) {
            tempList.add(agency.getId());
        }
        for (AgencyVO agency : agencies) {
            // 如果是顶级节点, 遍历该父节点的所有子节点
            if (!tempList.contains(agency.getParentId())) {
                recursionFn(agencies, agency);
                returnList.add(agency);
            }
        }
        if (returnList.isEmpty()) {
            returnList = agencies;
        }
        return returnList;
    }

    private void recursionFn(List<AgencyVO> list, AgencyVO t) {
        // 得到子节点列表
        List<AgencyVO> childList = getChildList(list, t);
        t.setChildren(childList);
        for (AgencyVO tChild : childList) {
            if (hasChild(list, tChild)) {
                recursionFn(list, tChild);
            }
        }
    }

    private List<AgencyVO> getChildList(List<AgencyVO> list, AgencyVO t) {
        List<AgencyVO> tlist = new ArrayList<AgencyVO>();
        Iterator<AgencyVO> it = list.iterator();
        while (it.hasNext()) {
            AgencyVO n = (AgencyVO) it.next();
            if (Objects.nonNull(n.getParentId()) && n.getParentId().longValue() == t.getId().longValue()) {
                tlist.add(n);
            }
        }
        return tlist;
    }

    /**
     * 判断是否有子节点
     */
    private boolean hasChild(List<AgencyVO> list, AgencyVO t) {
        return getChildList(list, t).size() > 0;
    }
}
