package com.ruoyi.platform.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.date.DateUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ruoyi.common.constant.Constants;
import com.ruoyi.common.constant.UserConstants;
import com.ruoyi.common.core.domain.platform.PlatformTenant;
import com.ruoyi.common.core.domain.platform.dto.PlatformTenantDTO;
import com.ruoyi.common.core.domain.platform.vo.PlatformTenantVO;
import com.ruoyi.common.core.domain.saas.dto.SysUserDTO;
import com.ruoyi.common.core.domain.saas.entity.SysDept;
import com.ruoyi.common.core.domain.saas.entity.SysUser;
import com.ruoyi.common.core.domain.saas.vo.SysRoleVO;
import com.ruoyi.common.core.page.MpPageUtils;
import com.ruoyi.common.core.page.TableDataInfo;
import com.ruoyi.common.core.text.Convert;
import com.ruoyi.common.exception.BusinessException;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.utils.bean.DozerUtils;
import com.ruoyi.common.utils.uuid.IdUtils;
import com.ruoyi.platform.mapper.PlatformTenantMapper;
import com.ruoyi.platform.mapper.saas.SaaSDeptMapper;
import com.ruoyi.platform.mapper.saas.SaaSRoleMapper;
import com.ruoyi.platform.mapper.saas.SaaSUserMapper;
import com.ruoyi.platform.mapper.saas.SaaSUserRoleMapper;
import com.ruoyi.platform.service.IPlatformTenantService;
import com.ruoyi.system.domain.SysUserRole;
import com.ruoyi.system.service.ISysUserService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;

/**
 * 租户Service业务层处理
 * 
 * @author zhushuyong
 * @date 2021-07-02
 */
@Slf4j
@Service
public class PlatformTenantServiceImpl extends ServiceImpl<PlatformTenantMapper, PlatformTenant> implements IPlatformTenantService
{
    @Autowired
    private PlatformTenantMapper platformTenantMapper;

    @Autowired
    private ISysUserService userService;

    @Autowired
    private SaaSDeptMapper saaSDeptMapper;

    @Autowired
    private SaaSUserMapper saaSUserMapper;

    @Autowired
    private SaaSRoleMapper saaSRoleMapper;

    @Autowired
    private SaaSUserRoleMapper saaSUserRoleMapper;

    /**
     * 查询租户
     * 
     * @param id 租户ID
     * @return 租户
     */
    @Override
    public PlatformTenantVO selectPlatformTenantById(String id)
    {
        return platformTenantMapper.selectByTenantId(id);
    }

    /**
     * 查询租户列表
     * 
     * @param platformTenant 租户
     * @return 租户
     */
    @Override
    public TableDataInfo<PlatformTenantVO> selectPlatformTenantPage(PlatformTenantDTO platformTenant)
    {
        IPage<PlatformTenant> platformTenantIPage = this.page(MpPageUtils.intPage(), getWrapper(platformTenant));
        return MpPageUtils.copyPage(platformTenantIPage, PlatformTenantVO.class);
    }

    @Override
    public List<PlatformTenantVO> selectPlatformTenantList(PlatformTenantDTO platformTenant) {
        return BeanUtil.copyToList(this.list(getWrapper(platformTenant)), PlatformTenantVO.class);
    }

    private LambdaQueryWrapper<PlatformTenant> getWrapper(PlatformTenantDTO platformTenant) {
        return new LambdaQueryWrapper<PlatformTenant>()
                .like(StringUtils.isNotBlank(platformTenant.getTenantNo()), PlatformTenant::getTenantNo, platformTenant.getTenantNo())
                .like(StringUtils.isNotBlank(platformTenant.getTenantName()), PlatformTenant::getTenantName, platformTenant.getTenantName())
                .eq(StringUtils.isNotBlank(platformTenant.getStatus()), PlatformTenant::getStatus, platformTenant.getStatus())
                .ge(StringUtils.isNotNull(platformTenant.getStartDate()), PlatformTenant::getStartDate, platformTenant.getStartDate())
                .le(StringUtils.isNotNull(platformTenant.getEndDate()), PlatformTenant::getEndDate, platformTenant.getEndDate());
    }

    /**
     * 新增租户
     * 
     * @param platformTenantDTO 租户
     * @return 结果
     */
    @Override
    @Transactional
    public int insertPlatformTenant(PlatformTenantDTO platformTenantDTO)
    {
        if (StringUtils.isNotEmpty(platformTenantDTO.getTenantNo())
                && UserConstants.TENANT_NO_NOT_UNIQUE.equals(checkTenantNoUnique(platformTenantDTO))) {
            throw new BusinessException("新增租户'" + platformTenantDTO.getTenantName() + "'失败，租户编号已存在");
        }else if (StringUtils.isNotEmpty(platformTenantDTO.getPhonenumber())
                && UserConstants.USER_PHONE_NOT_UNIQUE.equals(userService.checkPhoneUnique(SysUserDTO.builder().phonenumber(platformTenantDTO.getPhonenumber()).build()))) {
            throw new BusinessException("新增租户超管用户'" + platformTenantDTO.getLoginName() + "'失败，手机号码已存在");
        }
        else if (StringUtils.isNotEmpty(platformTenantDTO.getEmail())
                && UserConstants.USER_EMAIL_NOT_UNIQUE.equals(userService.checkEmailUnique(SysUserDTO.builder().email(platformTenantDTO.getEmail()).build())))
        {
            throw new BusinessException("新增租户超管用户'" + platformTenantDTO.getLoginName() + "'失败，邮箱账号已存在");
        }
        PlatformTenant platformTenant = DozerUtils.copyProperties(platformTenantDTO, PlatformTenant.class);
        platformTenant.setStartDate(DateUtil.beginOfDay(platformTenant.getStartDate()));
        platformTenant.setEndDate(DateUtil.endOfDay(platformTenant.getEndDate()));
        //租户入口
        int resultTenant = platformTenantMapper.insert(platformTenant);
        if (resultTenant<=0) {
            throw new BusinessException("新增租户入库'" + platformTenantDTO.getTenantName() + "'失败，请联系管理员");
        }
        SysDept sysDept = SysDept.builder()
                .id(IdUtils.fastSimpleUUID())
                .parentId(Constants.TOP_PARENT_DEPT_ID)
                .ancestors(Constants.TOP_PARENT_DEPT_ID)
                .deptType(Constants.YB)
                .deptName(platformTenantDTO.getDeptName())
                .leader(platformTenantDTO.getLoginName())
                .phone(platformTenantDTO.getPhonenumber())
                .email(platformTenantDTO.getEmail())
                .createBy(platformTenant.getCreateBy())
                .tenantId(platformTenant.getId())
                .build();
        int resultDept = saaSDeptMapper.insert(sysDept);
        if (resultDept<=0) {
            throw new BusinessException("租户部门入库'" + platformTenantDTO.getDeptName() + "'失败，请联系管理员");
        }
        //用户入库
        SysUser user = SysUser.builder()
                .id(IdUtils.fastSimpleUUID())
                .deptId(sysDept.getId())
                .loginName(platformTenantDTO.getLoginName())
                .userName(platformTenantDTO.getUserName())
                .userType(Constants.YB)
                .email(platformTenantDTO.getEmail())
                .phonenumber(platformTenantDTO.getPhonenumber())
                .sex(platformTenantDTO.getSex())
                .password(platformTenantDTO.getPassword())
                .salt(platformTenantDTO.getSalt())
                .status(platformTenantDTO.getUserStatus())
                .createBy(platformTenant.getCreateBy())
                .tenantId(platformTenant.getId()).build();
        int resultUser = saaSUserMapper.insert(user);
        if (resultUser<=0) {
            throw new BusinessException("租户超管入库'" + platformTenantDTO.getLoginName() + "'失败，请联系管理员");
        }
        SysRoleVO roleVO = saaSRoleMapper.selectRoleByTenantId();
        if (Objects.isNull(roleVO)) {
            throw new BusinessException("租户超管角色未提前初始化，请联系管理员");
        }
        int resultUserRole = saaSUserRoleMapper.insert(SysUserRole.builder()
                .userId(user.getId())
                .roleId(roleVO.getId())
                .tenantId(platformTenant.getId())
                .build());
        if (resultUserRole<=0) {
            throw new BusinessException("租户超管'" + platformTenantDTO.getLoginName() + "'角色初始化失败，请联系管理员");
        }
        return resultTenant;
    }

    /**
     * 修改租户
     * 
     * @param platformTenantDTO 租户
     * @return 结果
     */
    @Override
    @Transactional
    public int updatePlatformTenant(PlatformTenantDTO platformTenantDTO)
    {
        if (StringUtils.isNotEmpty(platformTenantDTO.getTenantNo())
                && UserConstants.TENANT_NO_NOT_UNIQUE.equals(checkTenantNoUnique(platformTenantDTO))) {
            throw new BusinessException("修改租户'" + platformTenantDTO.getTenantName() + "'失败，租户编号已存在");
        }else if (StringUtils.isNotEmpty(platformTenantDTO.getPhonenumber())
                && UserConstants.USER_PHONE_NOT_UNIQUE.equals(userService.checkPhoneUnique(SysUserDTO.builder()
                .id(platformTenantDTO.getUserId()).phonenumber(platformTenantDTO.getPhonenumber()).build()))) {
            throw new BusinessException("修改租户超管用户'" + platformTenantDTO.getLoginName() + "'失败，手机号码已存在");
        }
        else if (StringUtils.isNotEmpty(platformTenantDTO.getEmail())
                && UserConstants.USER_EMAIL_NOT_UNIQUE.equals(userService.checkEmailUnique(SysUserDTO.builder()
                .id(platformTenantDTO.getUserId()).email(platformTenantDTO.getEmail()).build())))
        {
            throw new BusinessException("修改租户超管用户'" + platformTenantDTO.getLoginName() + "'失败，邮箱账号已存在");
        }
        PlatformTenant platformTenant = DozerUtils.copyProperties(platformTenantDTO, PlatformTenant.class);
        platformTenant.setStartDate(DateUtil.beginOfDay(platformTenant.getStartDate()));
        platformTenant.setEndDate(DateUtil.endOfDay(platformTenant.getEndDate()));
        //租户入口
        int resultTenant = platformTenantMapper.updateById(platformTenant);
        if (resultTenant<=0) {
            throw new BusinessException("修改租户入库'" + platformTenantDTO.getTenantName() + "'失败，请联系管理员");
        }
        //部门入库
        SysDept sysDept = SysDept.builder()
                .id(platformTenantDTO.getDeptId())
                .deptName(platformTenantDTO.getDeptName())
                .leader(platformTenantDTO.getLoginName())
                .phone(platformTenantDTO.getPhonenumber())
                .email(platformTenantDTO.getEmail())
                .updateBy(platformTenant.getUpdateBy())
                .updateTime(new Date())
                .build();
        int resultDept = saaSDeptMapper.updateById(sysDept);
        if (resultDept<=0) {
            throw new BusinessException("租户部门入库'" + platformTenantDTO.getDeptName() + "'失败，请联系管理员");
        }
        //用户入库
        SysUser user = SysUser.builder()
                .id(platformTenantDTO.getUserId())
                .userName(platformTenantDTO.getUserName())
                .email(platformTenantDTO.getEmail())
                .phonenumber(platformTenantDTO.getPhonenumber())
                .sex(platformTenantDTO.getSex())
                .status(platformTenantDTO.getUserStatus())
                .updateBy(platformTenant.getUpdateBy())
                .updateTime(new Date())
                .build();
        int resultUser = saaSUserMapper.updateById(user);
        if (resultUser<=0) {
            throw new BusinessException("租户超管入库'" + platformTenantDTO.getLoginName() + "'失败，请联系管理员");
        }
        return resultTenant;
    }

    /**
     * 删除租户对象
     * 
     * @param ids 需要删除的数据ID
     * @return 结果
     */
    @Override
    public int deletePlatformTenantByIds(String ids)
    {
        return platformTenantMapper.deleteBatchIds(Arrays.asList(Convert.toStrArray(ids)));
    }

    /**
     * 删除租户信息
     * 
     * @param id 租户ID
     * @return 结果
     */
    @Override
    public int deletePlatformTenantById(String id)
    {
        return platformTenantMapper.deleteById(id);
    }

    @Override
    public String checkTenantNoUnique(PlatformTenantDTO platformTenantDTO) {
        String tenantId = StringUtils.isIdNull(platformTenantDTO.getId());
        Optional<PlatformTenant> info = platformTenantMapper.selectList(Wrappers.query(PlatformTenant
                .builder().tenantNo(platformTenantDTO.getTenantNo()).build())).stream().findFirst();
        if (info.isPresent() && !tenantId.equals(info.get().getId()))
        {
            return UserConstants.TENANT_NO_NOT_UNIQUE;
        }
        return UserConstants.TENANT_NO_UNIQUE;
    }

    @Override
    public int changeStatus(PlatformTenantDTO platformTenantDTO) {
        return platformTenantMapper.updateById(DozerUtils.copyProperties(platformTenantDTO, PlatformTenant.class));
    }

}
