package com.gitee.sop.admin.service.sys;

import com.gitee.fastmybatis.core.PageInfo;
import com.gitee.fastmybatis.core.query.LambdaQuery;
import com.gitee.sop.admin.common.dto.StatusUpdateBatchDTO;
import com.gitee.sop.admin.common.dto.StatusUpdateDTO;
import com.gitee.sop.admin.common.dto.UserDTO;
import com.gitee.sop.admin.common.support.ServiceSupport;
import com.gitee.sop.admin.common.util.CopyUtil;
import com.gitee.sop.admin.dao.entity.SysUser;
import com.gitee.sop.admin.dao.mapper.SysUserMapper;
import com.gitee.sop.admin.service.sys.dto.DeptUserResultDTO;
import com.gitee.sop.admin.service.sys.dto.SysDeptDTO;
import com.gitee.sop.admin.service.sys.dto.SysUserAddDTO;
import com.gitee.sop.admin.service.sys.dto.SysUserDTO;
import com.gitee.sop.admin.service.sys.dto.SysUserSearchDTO;
import com.gitee.sop.admin.service.sys.dto.SysUserUpdateDTO;
import com.gitee.sop.admin.service.sys.login.enums.RegTypeEnum;
import com.google.common.collect.Lists;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.crypto.bcrypt.BCrypt;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;


/**
 * @author 六如
 */
@Service
public class SysUserService implements ServiceSupport<SysUser, SysUserMapper> {

    @Autowired
    SysUserDeptService sysUserDeptService;

    public <T extends UserDTO> void fillShowName(Collection<T> userDTOS) {
        if (CollectionUtils.isEmpty(userDTOS)) {
            return;
        }
        Set<Long> userIds = userDTOS.stream().flatMap(docInfo -> Lists.newArrayList(docInfo.getAddBy(), docInfo.getUpdateBy()).stream())
                .filter(val -> val != null && val > 0)
                .collect(Collectors.toSet());
        Map<Long, SysUserDTO> userIdMap = this.getUserInfo(userIds);
        for (T userDTO : userDTOS) {
            SysUserDTO addUser = userIdMap.get(userDTO.getAddBy());
            if (addUser != null) {
                userDTO.setAddByName(addUser.getShowName());
            }
            SysUserDTO updateUser = userIdMap.get(userDTO.getUpdateBy());
            if (updateUser != null) {
                userDTO.setUpdateByName(updateUser.getShowName());
            }
        }
    }

    public Map<Long, SysUserDTO> getUserInfo(Collection<Long> userIds) {
        if (CollectionUtils.isEmpty(userIds)) {
            return Collections.emptyMap();
        }
        return this.query()
                .in(SysUser::getId, userIds)
                .map(SysUser::getId, sysUser -> CopyUtil.copyBean(sysUser, SysUserDTO::new));
    }

    public PageInfo<SysUserDTO> doPage(SysUserSearchDTO sysUserSearchDTO) {
        LambdaQuery<SysUser> query = sysUserSearchDTO.toLambdaQuery(SysUser.class);
        Long deptId = sysUserSearchDTO.getDeptId();
        DeptUserResultDTO deptUserResultDTO = sysUserDeptService.listDeptUserIdsDeep(deptId);
        if (deptUserResultDTO.getSelect()) {
            List<Long> userIds = deptUserResultDTO.getUserIds();
            // 查不到返回空
            if (CollectionUtils.isEmpty(userIds)) {
                return new PageInfo<>();
            }
            query.in(SysUser::getId, userIds);
        }

        query.orderByDesc(SysUser::getId);

        // 格式转换
        return this.pageAndConvert(query, records -> {
            if (records.isEmpty()) {
                return Collections.emptyList();
            }
            Set<Long> userIds = records.stream().map(SysUser::getId).collect(Collectors.toSet());
            Map<Long, SysDeptDTO> userIdDeptMap = sysUserDeptService.getUserDeptId(userIds);

            return CopyUtil.copyList(records, SysUserDTO::new, after -> {
                SysDeptDTO sysDeptDTO = userIdDeptMap.get(after.getId());
                after.setDept(sysDeptDTO);
            });
        });
    }

    public Long addUser(SysUserAddDTO sysUserAddDTO) {
        SysUser sysUser = CopyUtil.copyBean(sysUserAddDTO, SysUser::new);
        String encodedPassword = BCrypt.hashpw(sysUserAddDTO.getPassword(), BCrypt.gensalt());
        sysUser.setPassword(encodedPassword);
        sysUser.setRegType(RegTypeEnum.BACKEND.getValue());
        this.save(sysUser);

        // 添加部门
        Long deptId = sysUserAddDTO.getParentId();
        if (deptId != null && deptId > 0) {
            sysUserDeptService.saveUserDept(sysUser.getId(), Lists.newArrayList(deptId));
        }

        return sysUser.getId();
    }

    public int updateUser(SysUserUpdateDTO sysUserUpdateDTO) {
        SysUser sysUser = CopyUtil.copyBean(sysUserUpdateDTO, SysUser::new);
        int cnt = this.update(sysUser);

        // 添加部门
        Long deptId = sysUserUpdateDTO.getParentId();
        if (deptId != null && deptId > 0) {
            sysUserDeptService.saveUserDept(sysUser.getId(), Lists.newArrayList(deptId));
        }
        return cnt;
    }

    /**
     * 修改状态
     *
     * @param statusUpdateDTO 修改值
     * @return 返回影响行数
     */
    public int updateStatus(StatusUpdateDTO statusUpdateDTO) {
        return this.query()
                .eq(SysUser::getId, statusUpdateDTO.getId())
                .set(SysUser::getStatus, statusUpdateDTO.getStatus())
                .update();
    }

    public int updateStatus(StatusUpdateBatchDTO statusUpdateDTO) {
        return this.query()
                .in(SysUser::getId, statusUpdateDTO.getIds())
                .set(SysUser::getStatus, statusUpdateDTO.getStatus())
                .update();
    }

    public void resetUserPassword(Long userId, String passwordHash) {
        String encodedPassword = BCrypt.hashpw(passwordHash, BCrypt.gensalt());
        this.query()
                .eq(SysUser::getId, userId)
                .set(SysUser::getPassword, encodedPassword)
                .update();
    }

    public SysUser getByUsername(String username) {
        return this.get(SysUser::getUsername, username);
    }


}
