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

import com.xinelu.common.annotation.DataScope;
import com.xinelu.common.core.domain.AjaxResult;
import com.xinelu.common.core.domain.entity.SysDictData;
import com.xinelu.common.core.domain.entity.SysUser;
import com.xinelu.common.exception.ServiceException;
import com.xinelu.common.utils.SecurityUtils;
import com.xinelu.common.utils.StringUtils;
import com.xinelu.common.utils.bean.BeanUtils;
import com.xinelu.common.utils.regex.RegexUtil;
import com.xinelu.manage.domain.agency.Agency;
import com.xinelu.manage.domain.department.Department;
import com.xinelu.manage.dto.department.DepartmentDTO;
import com.xinelu.manage.mapper.agency.AgencyMapper;
import com.xinelu.manage.mapper.department.DepartmentMapper;
import com.xinelu.manage.service.department.IDepartmentService;
import com.xinelu.manage.vo.department.DepartmentBaseVo;
import com.xinelu.manage.vo.department.DepartmentListVO;
import com.xinelu.manage.vo.department.DepartmentVO;
import com.xinelu.system.mapper.SysDictDataMapper;
import com.xinelu.system.mapper.SysUserMapper;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.BooleanUtils;
import org.apache.commons.lang3.ObjectUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;


/**
 * 科室信息Service业务层处理
 *
 * @author xinelu
 * @date 2024-02-26
 */
@Service
public class DepartmentServiceImpl implements IDepartmentService {
    @Resource
    private DepartmentMapper departmentMapper;
    @Resource
    private RegexUtil regexUtil;
    @Resource
    private SysUserMapper sysUserMapper;
    @Resource
    private AgencyMapper agencyMapper;
    @Resource
    private SysDictDataMapper sysDictDataMapper;

    /**
     * 查询科室信息
     *
     * @param id 科室信息主键
     * @return 科室信息
     */
    @Override
    public DepartmentListVO selectDepartmentById(Long id) {
        return departmentMapper.selectDepartment(id);
    }

    /**
     * 查询科室信息列表
     *
     * @param department 科室信息
     * @return 科室信息
     */
    @Override
    public List<Department> selectDepartmentList(Department department) {
        List<Department> departmentList = departmentMapper.selectDepartmentList(department);
        List<String> strings = new ArrayList<>();
        strings.add("provide_service_category");
        strings.add("department_type");
        List<SysDictData> sysDictDataList = sysDictDataMapper.selectDictDataByTypeList(strings);
        for (Department dataDepartment : departmentList) {
            SysDictData departmentType = sysDictDataList.stream().filter(Objects::nonNull).filter(item -> item.getDictValue().equals(dataDepartment.getDepartmentType())).findFirst().orElse(new SysDictData());
            if (org.apache.commons.lang3.StringUtils.isNotBlank(departmentType.getDictLabel())){
                dataDepartment.setDepartmentType(departmentType.getDictLabel());
            }
            SysDictData provideServiceCategory = sysDictDataList.stream().filter(Objects::nonNull).filter(item -> item.getDictValue().equals(dataDepartment.getProvideServiceCategory())).findFirst().orElse(new SysDictData());
            if (org.apache.commons.lang3.StringUtils.isNotBlank(provideServiceCategory.getDictLabel())){
                dataDepartment.setProvideServiceCategory(provideServiceCategory.getDictLabel());
            }
        }
        return departmentList;
    }

    /**
     * 查询科室信息列表 问卷使用
     *
     * @return 科室信息集合
     */
    @Override
    public AjaxResult selectUserDepartment() {
        SysUser sysUser = sysUserMapper.selectUserById(SecurityUtils.getUserId());
        List<Department> departments = new ArrayList<>();
        if (Objects.nonNull(sysUser) && Objects.nonNull(sysUser.getHospitalAgencyId())) {
            Department department = new Department();
            department.setHospitalAgencyId(sysUser.getHospitalAgencyId());
            departments = departmentMapper.selectDepartmentList(department);
        }
        return AjaxResult.success(departments);
    }

    /**
     * 查询科室或病区信息列表 不分页
     *
     * @param department 科室信息
     * @return 科室信息
     */
    @Override
    public AjaxResult selectDepartmentByAgencyIdList(Department department) {
        if (Objects.isNull(department) || (Objects.isNull(department.getHospitalAgencyId()) && Objects.isNull(department.getParentDepartmentId()))) {
            return AjaxResult.success();
        }
        return AjaxResult.success(departmentMapper.selectDepartmentList(department));
    }

    /**
     * 新增科室信息
     *
     * @param department 科室信息
     * @return 结果
     */
    @Override
    public AjaxResult insertDepartment(Department department) {
        if (Objects.isNull(department.getParentDepartmentId())) {
            department.setParentDepartmentId(0L);
        }
        department.setCreateTime(LocalDateTime.now());
        department.setCreateBy(SecurityUtils.getUsername());
        //根据上级机构id查询
        List<Department> departmentList = departmentMapper.selectDepartmentNameCount(department);
        if (CollectionUtils.isNotEmpty(departmentList)) {
            //重名
            List<Department> departmentName = departmentList.stream().filter(Objects::nonNull).filter(item -> Objects.nonNull(item.getDepartmentName()) && department.getDepartmentName().equals(item.getDepartmentName())).collect(Collectors.toList());
            if (CollectionUtils.isNotEmpty(departmentName)) {
                return AjaxResult.error("该" + department.getHospitalAgencyName() + "下，已存在名称为" + department.getDepartmentName() + "的科室！");
            }
            //重编号
            List<Department> departmentCode = departmentList.stream().filter(Objects::nonNull).filter(item -> Objects.nonNull(item.getDepartmentCode()) && department.getDepartmentCode().equals(item.getDepartmentName())).collect(Collectors.toList());
            if (CollectionUtils.isNotEmpty(departmentCode)) {
                return AjaxResult.error("该" + department.getHospitalAgencyName() + "下，已存在科室编号为" + department.getDepartmentName() + "的科室！");
            }
        }
        //department.setDepartmentCode(Constants.DEPARTMENT_CODE + generateSystemCodeUtil.generateSystemCode(Constants.DEPARTMENT_CODE));
        return AjaxResult.success(departmentMapper.insertDepartment(department));
    }

    /**
     * 修改科室信息
     *
     * @param department 科室信息
     * @return 结果
     */
    @Override
    public AjaxResult updateDepartment(Department department) {
        //上级科室是自己本身，取消上级科室
        if (Objects.nonNull(department) && Objects.nonNull(department.getId()) && Objects.nonNull(department.getParentDepartmentId()) && department.getId().equals(department.getParentDepartmentId())) {
            department.setParentDepartmentId(null);
        }
        //根据上级机构id查询
        List<Department> departmentList = departmentMapper.selectDepartmentNameCount(department);
        if (CollectionUtils.isNotEmpty(departmentList)) {
            //重名
            List<Department> departmentName = departmentList.stream().filter(Objects::nonNull).filter(item -> Objects.nonNull(item.getDepartmentName()) && department.getDepartmentName().equals(item.getDepartmentName()) && !department.getId().equals(item.getId())).collect(Collectors.toList());
            if (CollectionUtils.isNotEmpty(departmentName)) {
                return AjaxResult.error("该" + department.getHospitalAgencyName() + "下，已存在名称为" + department.getDepartmentName() + "的科室！");
            }
            //重编号
            List<Department> departmentCode = departmentList.stream().filter(Objects::nonNull).filter(item -> Objects.nonNull(item.getDepartmentCode()) && department.getDepartmentCode().equals(item.getDepartmentName()) && !department.getId().equals(item.getId())).collect(Collectors.toList());
            if (CollectionUtils.isNotEmpty(departmentCode)) {
                return AjaxResult.error("该" + department.getHospitalAgencyName() + "下，已存在科室编号为" + department.getDepartmentName() + "的科室！");
            }
        }
        department.setUpdateBy(SecurityUtils.getUsername());
        department.setUpdateTime(LocalDateTime.now());
        return AjaxResult.success(departmentMapper.updateDepartmentById(department));
    }

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

    /**
     * 删除科室信息信息
     *
     * @param id 科室信息主键
     * @return 结果
     */
    @Override
    public int deleteDepartmentById(Long id) {
        return departmentMapper.deleteDepartmentById(id);
    }

    /**
     * 查询科室信息列表及包含话术数量
     *
     * @param departmentDto 科室信息
     * @return 结果
     */
    @DataScope(agencyAlias = "d", deptAlias = "si")
    @Override
    public DepartmentBaseVo selectDepartmentListScriptNum(DepartmentDTO departmentDto) {
	    Agency agency = agencyMapper.selectAgencyById(departmentDto.getHospitalAgencyId());
	    List<DepartmentVO> departmentVOList = departmentMapper.selectDepartmentListScriptNum(departmentDto);
	    return DepartmentBaseVo.builder().hospitalAgencyName(ObjectUtils.isEmpty(agency) ? "" : agency.getAgencyName())
		    .deptNumList(departmentVOList).build();
    }

    /**
     * 查询科室信息列表及包含手术数量
     *
     * @param departmentDto 科室信息
     * @return 结果
     */
    @DataScope(agencyAlias = "d", deptAlias = "oi")
    @Override
    public DepartmentBaseVo selectDepartmentListOperationNum(DepartmentDTO departmentDto) {
	    Agency agency = agencyMapper.selectAgencyById(departmentDto.getHospitalAgencyId());
		List<DepartmentVO> departmentVOList = departmentMapper.selectDepartmentListOperationNum(departmentDto);
	    return DepartmentBaseVo.builder().hospitalAgencyName(ObjectUtils.isEmpty(agency) ? "" : agency.getAgencyName())
		    .deptNumList(departmentVOList).build();
    }

    /**
     * 查询科室信息列表及包含微信库数量
     *
     * @param departmentDto 科室信息
     * @return 结果
     */
    @DataScope(agencyAlias = "d", deptAlias = "wt")
    @Override
    public DepartmentBaseVo selectDepartmentListWechatTemplateNum(DepartmentDTO departmentDto) {
	    Agency agency = agencyMapper.selectAgencyById(departmentDto.getHospitalAgencyId());
	    List<DepartmentVO> departmentVOList = departmentMapper.selectDepartmentListWechatTemplateNum(departmentDto);
	    return DepartmentBaseVo.builder().hospitalAgencyName(ObjectUtils.isEmpty(agency) ? "" : agency.getAgencyName())
		    .deptNumList(departmentVOList).build();
    }

    /**
     * 查询科室信息列表及包含短信库数量
     *
     * @param departmentDto 科室信息
     * @return 结果
     */
    @DataScope(agencyAlias = "d", deptAlias = "tm")
    @Override
    public DepartmentBaseVo selectDepartmentListMessageNum(DepartmentDTO departmentDto) {
	    Agency agency = agencyMapper.selectAgencyById(departmentDto.getHospitalAgencyId());
	    List<DepartmentVO> departmentVOList = departmentMapper.selectDepartmentListMessageNum(departmentDto);
	    return DepartmentBaseVo.builder().hospitalAgencyName(ObjectUtils.isEmpty(agency) ? "" : agency.getAgencyName())
		    .deptNumList(departmentVOList).build();
    }

    /**
     * 科室信息导入
     *
     * @param departmentList 科室信息
     * @return 结果
     */

    @Transactional(rollbackFor = Exception.class)
    @Override
    public AjaxResult insertDepartmentList(List<Department> departmentList) {
        //判断添加的数据是否为空
        if (CollectionUtils.isEmpty(departmentList)) {
            return AjaxResult.error("请添加科室导入信息！");
        }
        //根据护理站名称做去除处理
        List<Department> importDataList = departmentList.stream().filter(item -> StringUtils.isNotBlank(item.getDepartmentName())).distinct().collect(Collectors.toList());
        //校验联系电话格式是否正确
        Department department = importDataList.stream().filter(item -> StringUtils.isNotBlank(item.getDepartmentPhone())).filter(item -> BooleanUtils.isFalse(regexUtil.regexPhone(item.getDepartmentPhone()))).findFirst().orElse(new Department());
        if (StringUtils.isNotBlank(department.getDepartmentPhone())) {
            return AjaxResult.error("当前科室电话：" + department.getDepartmentPhone() + " 格式不正确，请重新录入！");
        }
        List<String> departmentName = importDataList.stream().filter(item -> StringUtils.isNotBlank(item.getDepartmentName())).map(Department::getDepartmentName).distinct().collect(Collectors.toList());
        //根据名称查询科室基本信息
        List<Department> allDepartment = departmentMapper.getAllDepartmentInfo(departmentName);
        //做差集，去除数据库中已经存在的科室信息
        List<Department> subtractList = new ArrayList<>(CollectionUtils.subtract(importDataList, allDepartment));
        if (CollectionUtils.isEmpty(subtractList)) {
            return AjaxResult.success();
        }
        List<Department> saveDepartmentList = new ArrayList<>();
        for (Department item : subtractList) {
            if (Objects.isNull(item.getParentDepartmentId())) {
                item.setParentDepartmentId(0L);
            }
            item.setCreateBy(SecurityUtils.getUsername());
            item.setCreateTime(LocalDateTime.now());
            Department newDepartment = new Department();
            BeanUtils.copyProperties(item, newDepartment);
            saveDepartmentList.add(newDepartment);
        }
        int insertCount = departmentMapper.insertDepartmentList(saveDepartmentList);
        if (insertCount <= 0) {
            throw new ServiceException("导入科室信息失败，请联系管理员！");
        }
        return AjaxResult.success();
    }

    /**
     * 查询科室信息列表及包含服务包数量
     *
     * @param departmentDto 科室
     * @return 结果
     */
    @DataScope(agencyAlias = "d", deptAlias = "sp")
    @Override
    public DepartmentBaseVo selectListServicePackageNum(DepartmentDTO departmentDto) {
        Agency agency = agencyMapper.selectAgencyById(departmentDto.getHospitalAgencyId());
        List<DepartmentVO> departmentVOList = departmentMapper.selectListServicePackageNum(departmentDto);
        return DepartmentBaseVo.builder().hospitalAgencyName(ObjectUtils.isEmpty(agency) ? "" : agency.getAgencyName())
                .deptNumList(departmentVOList).build();
    }
}
