package com.crm.manager.service.impl;

import com.crm.rely.backend.core.dto.base.BaseResultDto;
import com.crm.rely.backend.core.exception.DataNotFoundException;
import com.crm.rely.backend.core.exception.ServiceException;
import com.crm.rely.backend.core.constant.Constants;
import com.crm.rely.backend.core.dto.base.BaseResultWithPagerDto;
import com.crm.rely.backend.core.dto.base.PageDto;
import com.crm.rely.backend.core.constant.ManagerConstant;
import com.crm.rely.backend.core.dto.user.department.UserDepartmentSearchDto;
import com.crm.rely.backend.model.entity.user.department.UserDepartmentAddEntity;
import com.crm.rely.backend.model.entity.user.department.UserDepartmentDeleteEntity;
import com.crm.rely.backend.model.entity.user.department.UserDepartmentSearchEntity;
import com.crm.rely.backend.model.entity.user.department.UserDepartmentUpdateEntity;
import com.crm.rely.backend.util.FormatPage;
import com.crm.manager.dao.repository.UserDepartmentRepository;
import com.crm.manager.dao.repository.UserRoleRepository;
import com.crm.rely.backend.core.pojo.table.UserDepartmentTable;
import com.crm.manager.service.UserDepartmentService;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.persistence.criteria.Predicate;
import java.util.*;

/**
 * @program: crm-backend
 * @description:
 * @author: houn
 * @create: 2019-07-25 13:56
 */
@Service
public class UserDepartmentServiceImpl implements UserDepartmentService {

    @Autowired
    private UserDepartmentRepository userDepartmentRepository;

    @Autowired
    private UserRoleRepository userRoleRepository;

    /**
     * 添加部门
     *
     * @param entity
     * @throws ServiceException
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void add(UserDepartmentAddEntity entity) throws ServiceException {

        existByName(entity.getName());

        UserDepartmentTable userDepartmentTable = new UserDepartmentTable();

        BeanUtils.copyProperties(entity, userDepartmentTable);

        userDepartmentTable.setRoleNumber(0);

        userDepartmentRepository.save(userDepartmentTable);
    }

    /**
     * 更新部门信息
     *
     * @param entity
     * @throws ServiceException
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void update(UserDepartmentUpdateEntity entity) throws ServiceException {

        UserDepartmentTable userDepartmentTable = userDepartmentRepository.findFirstById(entity.getId());
        if (userDepartmentTable == null) {
            throw new DataNotFoundException(Constants.INFO_NOT_FOUND);
        }
        if (userDepartmentTable.getName() == null || !userDepartmentTable.getName().equals(entity.getName())) {
            existByName(entity.getName());
        }

        BeanUtils.copyProperties(entity, userDepartmentTable);

        userDepartmentRepository.save(userDepartmentTable);
    }

    /**
     * 删除部门(批量)
     *
     * @param entity
     * @throws ServiceException
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void delete(UserDepartmentDeleteEntity entity) throws ServiceException {

        boolean existDepartmentId = userRoleRepository.existsByDepartmentIdIn(entity.getIds());

        if (existDepartmentId) {
            //todo 部门下存在角色 不能删除
            throw new ServiceException("");
        }

        List<UserDepartmentTable> userDepartmentTables = userDepartmentRepository.findByIdIn(entity.getIds());

        if (userDepartmentTables == null || userDepartmentTables.size() <= 0) {
            return;
        }

        userDepartmentRepository.delete(userDepartmentTables);
    }

    /**
     * 根据条件搜索列表
     *
     * @param entity
     * @return
     * @throws ServiceException
     */
    @Override
    public BaseResultWithPagerDto searchPage(UserDepartmentSearchEntity entity) throws ServiceException {

        //创建有序map map为排序字段
        Map<String, String> map = new LinkedHashMap<>(1);
        map.put("subIndex", "asc");
        Pageable pageable = FormatPage.formatPageable(entity.getPage(), map);

        Specification specification = getSpecification(entity);

        Page<UserDepartmentTable> userDepartmentTablePage = userDepartmentRepository.findAll(specification, pageable);

        long count = userDepartmentTablePage.getTotalElements();
        PageDto pageDto = FormatPage.format(entity.getPage(), count);

        if (count <= 0) {
            return new BaseResultWithPagerDto(Constants.SUCCESS_CODE, Constants.SEARCH_SUCCESS, pageDto);
        }

        List<UserDepartmentSearchDto> userDepartmentSearchDtos = transform(userDepartmentTablePage.getContent());

        return new BaseResultWithPagerDto(Constants.SUCCESS_CODE, Constants.SEARCH_SUCCESS, pageDto, userDepartmentSearchDtos);
    }
    @Override
    public BaseResultDto searchList() throws ServiceException {


        List<UserDepartmentTable> userDepartmentTables = userDepartmentRepository.getAllByOrderBySubIndex();


        List<UserDepartmentSearchDto> userDepartmentSearchDtos = transform(userDepartmentTables);

        return BaseResultDto.success(userDepartmentSearchDtos);
    }

    /**
     * 根据id查询
     *
     * @param id
     * @return
     * @throws ServiceException
     */
    @Override
    public UserDepartmentSearchDto searchSingle(Long id) throws ServiceException {

        UserDepartmentTable userDepartmentTable = userDepartmentRepository.findOne(id);
        if (userDepartmentTable == null) {
            throw new DataNotFoundException(Constants.INFO_NOT_FOUND);
        }

        UserDepartmentSearchDto userDepartmentSearchDto = transform(userDepartmentTable);

        return userDepartmentSearchDto;
    }

    /**
     * 验证当前部门用户名是否存在 存在则抛出serviceException异常 内容为部门名称已存在
     *
     * @param name
     * @throws ServiceException
     */
    private void existByName(String name) throws ServiceException {
        boolean existName = userDepartmentRepository.existsByName(name);

        if (existName) {
            throw new ServiceException(ManagerConstant.DEPARTMENT_NAME_IS_EXIST_ERROR);
        }
    }

    /**
     * 拼接动态sql
     *
     * @param entity
     * @return
     */
    private Specification getSpecification(UserDepartmentSearchEntity entity) {

        Specification<UserDepartmentTable> specification = (root, query, cb) -> {

            List<Predicate> predicates = new ArrayList<>(1);
            if (entity.getName() != null) {
                predicates.add(cb.like(root.get("name").as(String.class), "%" + entity.getName() + "%"));
            }
            Predicate[] pre = new Predicate[predicates.size()];

            return query.where(predicates.toArray(pre)).getRestriction();
        };

        return specification;
    }

    /**
     * 转化(list转化为dtos)
     *
     * @param userDepartmentTables
     * @return
     */
    private List<UserDepartmentSearchDto> transform(List<UserDepartmentTable> userDepartmentTables) {

        if (userDepartmentTables == null || userDepartmentTables.size() <= 0) {
            return null;
        }

        List<UserDepartmentSearchDto> transform = new ArrayList<>(userDepartmentTables.size());
        userDepartmentTables.forEach(value -> transform.add(transform(value)));

        return transform;
    }

    /**
     * 转化为dto
     *
     * @param userDepartmentTable
     * @return
     */
    private UserDepartmentSearchDto transform(UserDepartmentTable userDepartmentTable) {

        UserDepartmentSearchDto userDepartmentSearchDto = new UserDepartmentSearchDto();

        BeanUtils.copyProperties(userDepartmentTable, userDepartmentSearchDto);

        return userDepartmentSearchDto;
    }
}
