package com.platform.modules.sys.service.impl;

import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.baomidou.mybatisplus.plugins.Page;
import com.baomidou.mybatisplus.service.impl.ServiceImpl;
import com.platform.common.utils.*;
import com.platform.modules.live.entity.LiveSceneEntity;
import com.platform.modules.live.service.LiveSceneService;
import com.platform.modules.plm.util.MateriaFileProperties;
import com.platform.modules.plm.util.MaterialUtils;
import com.platform.modules.sys.dao.SysTenantDao;
import com.platform.modules.sys.dto.SaveTenantDTO;
import com.platform.modules.sys.entity.SysTenantEntity;
import com.platform.modules.sys.entity.SysUserEntity;
import com.platform.modules.sys.service.SysTenantService;
import com.platform.modules.sys.service.SysUserRoleService;
import com.platform.modules.sys.service.SysUserService;
import com.platform.modules.sys.service.SysUserTokenService;
import org.apache.commons.lang.RandomStringUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.shiro.crypto.hash.Sha256Hash;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.Arrays;
import java.util.Date;
import java.util.List;
import java.util.Map;

@Service("sysTenantService")
public class SysTenantServiceImpl extends ServiceImpl<SysTenantDao, SysTenantEntity> implements SysTenantService {

    @Autowired
    private SysUserService sysUserService;
    @Autowired
    private SysUserRoleService sysUserRoleService;
    @Autowired
    private SysUserTokenService sysUserTokenService;
    @Autowired
    private RedisUtils redisUtils;
    @Autowired
    private MateriaFileProperties materiaFileProperties;

    @Override
    public PageUtils queryPage(Map<String, Object> params) {

        String tenantName = (String) params.get("tenantName");
        String strTenantId = (String) params.get("tenantId");
        Long tenantId = null;

        if (StringUtils.isNotBlank(strTenantId)){
            tenantId = Long.valueOf(strTenantId);
        }

        Page<SysTenantEntity> page = this.selectPage(
                new Query<SysTenantEntity>(params).getPage(),
                new EntityWrapper<SysTenantEntity>()
                        .like(StringUtils.isNotBlank(tenantName), "tenant_name", tenantName)
                        .eq(null != tenantId, "tenant_id", tenantId)
        );

        return new PageUtils(page);
    }

    @Override
    public List<SysTenantEntity> saveBatch(List<SysTenantEntity> list) {
        if (list == null || list.size() == 0) {
            return null;
        }
        this.baseMapper.saveBatch(list);
        return list;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public R saveTenant(SaveTenantDTO tenantDTO) {

        // 1.保存企业信息
        SysTenantEntity tenantEntity = new SysTenantEntity();

        tenantEntity.setTenantName(tenantDTO.getTenantName());
        tenantEntity.setStatus(tenantDTO.getTenantStatus() == null ? 1 : tenantDTO.getTenantStatus());
        tenantEntity.setCreateTime(new Date());
        tenantEntity.setCreateUserId(ShiroUtils.getUserId());
        if (StringUtils.isBlank(tenantDTO.getLicense())){
            tenantEntity.setLicense(null);
        }else {
            tenantEntity.setLicense(tenantDTO.getLicense());
        }
        if (StringUtils.isBlank(tenantDTO.getLicenseUrl())){
            tenantEntity.setLicenseUrl(null);
        }else {
            tenantEntity.setLicenseUrl(handlerLicenseUrl(tenantDTO.getLicenseUrl(), materiaFileProperties.getBasePath()));
        }

        this.insert(tenantEntity);
        // 存入Redis
        redisUtils.hset(Constant.REDIS_SYS_TENANT_ENTITY, tenantEntity.getId().toString(), tenantEntity);
        // 2.保存用户信息
        return saveUser(tenantDTO, tenantEntity);
    }

    @Override
    public String tenantCheckExist(String tenantName, String license) {

        if (StringUtils.isBlank(tenantName) && StringUtils.isBlank(license)) {
            return null;
        }

        List<SysTenantEntity> list = baseMapper.checkExist(tenantName, license);

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

        for (SysTenantEntity entity : list) {
            if (tenantName.equals(entity.getTenantName())) {
                return "企业名称已存在";
            } else if (license.equals(entity.getLicense())) {
                return "营业执照注册号已存在";
            }
        }

        return null;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public R updateTenant(SysTenantEntity sysTenant) {

        if (null == sysTenant.getId()) {
            return R.error("id不能为空");
        }

        SysTenantEntity tenantEntity = selectById(sysTenant.getId());
        Integer statusFlag;
        if (null != tenantEntity.getStatus()){
            statusFlag = tenantEntity.getStatus();
        }else {
            statusFlag = 1;
        }

        if (StringUtils.isNotBlank(sysTenant.getTenantName()))
            tenantEntity.setTenantName(sysTenant.getTenantName());
        if (null != sysTenant.getStatus())
            tenantEntity.setStatus(sysTenant.getStatus());
        if (StringUtils.isNotBlank(sysTenant.getLicense())){
            tenantEntity.setLicense(sysTenant.getLicense());
        }else {
            tenantEntity.setLicense(null);
        }
        if (StringUtils.isNotBlank(sysTenant.getLicenseUrl())){
            tenantEntity.setLicenseUrl(handlerLicenseUrl(sysTenant.getLicenseUrl(), materiaFileProperties.getBasePath()));
        }else {
            tenantEntity.setLicenseUrl(null);
        }

        this.updateById(tenantEntity);

        // 存入Redis
        redisUtils.hset(Constant.REDIS_SYS_TENANT_ENTITY, tenantEntity.getId().toString(), tenantEntity);

        // 当机构状态为禁用时，机构下的所有账号都将被禁用
        if (null != sysTenant.getStatus() && !statusFlag.equals(sysTenant.getStatus())) {
            // 获取机构下的用户集合
            List<SysUserEntity> list = sysUserService.selectList(
                    new EntityWrapper<SysUserEntity>().eq("tenant_id", sysTenant.getId())
            );

            if (null == list || list.size() <= 0)
                return R.ok();

            // 机构状态为禁用时，踢出所有机构下已登录的用户
            if (statusFlag.equals(0)){
                for (SysUserEntity entity : list){
                    sysUserTokenService.logout(entity.getUserId());
                }
            }

            if (0 == sysTenant.getStatus()) {
                for (SysUserEntity entity : list) {
                    entity.setStatus(entity.getStatus() - 1);
                }
                sysUserService.updateBatchById(list);
            } else if (1 == sysTenant.getStatus()) {
                for (SysUserEntity entity : list) {
                    entity.setStatus(entity.getStatus() + 1);
                }
                sysUserService.updateBatchById(list);
            }
        }

        return R.ok();
    }

    @Override
    public R info(Long id) {

        SysTenantEntity sysTenantEntity = this.selectById(id);

        if (null == sysTenantEntity)
            return R.error("获取用户信息失败");

        // 地址拼接头
        if (StringUtils.isNotBlank(sysTenantEntity.getLicenseUrl())) {
            sysTenantEntity.setLicenseUrl(MaterialUtils.getMaterialUrl(sysTenantEntity.getLicenseUrl(), materiaFileProperties.getBasePath()));
        }

        return R.ok().put("sysTenant", sysTenantEntity);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public R delete(Long[] ids) {

        boolean delResult = this.deleteBatchIds(Arrays.asList(ids));

        if (!delResult)
            return R.error("删除失败");

        for (Long id : ids) {
            // 删除Redis中的数据
            redisUtils.hdel(Constant.REDIS_SYS_TENANT_ENTITY, id.toString());

            // 修改被删除的机构下的员工状态
            List<SysUserEntity> userEntityList = sysUserService.selectList(new EntityWrapper<SysUserEntity>().eq("tenant_id", id));
            // 机构下若无用户，则直接返回
            if (null == userEntityList || userEntityList.size() <= 0)
                return R.ok();

            for (SysUserEntity entity : userEntityList) {
                if (null != entity.getStatus()){
                    entity.setStatus(entity.getStatus() - 1);
                }
                // 踢出所有机构下已登录的用户
                sysUserTokenService.logout(entity.getUserId());
            }
            sysUserService.updateBatchById(userEntityList);
        }
        return R.ok();
    }

    /**
     * 保存员工信息
     *
     * @param tenantDTO 机构DTO
     */
    private R saveUser(SaveTenantDTO tenantDTO, SysTenantEntity tenantEntity) {

        SysUserEntity userEntity = new SysUserEntity();

        userEntity.setUsername(tenantDTO.getUsername());
        userEntity.setRealname(tenantDTO.getRealName());
        userEntity.setEmail(tenantDTO.getEmail() == null ? null : tenantDTO.getEmail());
        userEntity.setIdCard(tenantDTO.getIdCard());
        userEntity.setMobile(tenantDTO.getMobile());
        userEntity.setCreateTime(tenantEntity.getCreateTime());
        userEntity.setTenantId(tenantEntity.getId());
        userEntity.setCreateUserId(tenantDTO.getUserCreateUserId());
        userEntity.setStatus(tenantEntity.getStatus());
        // 密码加密并保存
        String salt = RandomStringUtils.randomAlphanumeric(20);
        userEntity.setPassword(new Sha256Hash(tenantDTO.getPassword(), salt).toHex());
        userEntity.setSalt(salt);

        sysUserService.insert(userEntity);

        // 保存用户与角色关系
        sysUserRoleService.saveOrUpdate(userEntity.getUserId(), tenantDTO.getRoleIdList());

        return R.ok();
    }

    /**
     * 处理营业执照影印件
     *
     * @param licenseUrl 路径
     */
    private String handlerLicenseUrl(String licenseUrl, String basePath) {

        if (StringUtils.isBlank(basePath))
            return licenseUrl;

        if (licenseUrl.startsWith(basePath)) {
            licenseUrl = licenseUrl.substring(basePath.length());
            if (licenseUrl.startsWith("/")) {
                return licenseUrl;
            } else {
                return "/" + licenseUrl;
            }
        }

        return licenseUrl;
    }

}
