package cn.iocoder.yudao.module.system.service.tenant;

import cn.hutool.core.collection.CollectionUtil;
import cn.iocoder.yudao.framework.common.enums.UserTypeEnum;
import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
import cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils;
import cn.iocoder.yudao.framework.tenant.core.context.TenantContextHolder;
import cn.iocoder.yudao.module.system.controller.admin.auth.vo.AuthLoginRespVO;
import cn.iocoder.yudao.module.system.controller.admin.tenant.vo.tenant.GroupTenantInfoVO;
import cn.iocoder.yudao.module.system.controller.admin.tenant.vo.tenant.GroupTenantListVO;
import cn.iocoder.yudao.module.system.controller.admin.tenant.vo.tenant.GroupTenantSaveReqVO;
import cn.iocoder.yudao.module.system.controller.admin.tenant.vo.tenant.TenantTreeResVO;
import cn.iocoder.yudao.module.system.convert.auth.AuthConvert;
import cn.iocoder.yudao.module.system.dal.dataobject.dept.DeptDO;
import cn.iocoder.yudao.module.system.dal.dataobject.oauth2.OAuth2AccessTokenDO;
import cn.iocoder.yudao.module.system.dal.dataobject.permission.RoleDO;
import cn.iocoder.yudao.module.system.dal.dataobject.permission.UserRoleDO;
import cn.iocoder.yudao.module.system.dal.dataobject.tenant.*;
import cn.iocoder.yudao.module.system.dal.dataobject.user.AdminUserDO;
import cn.iocoder.yudao.module.system.dal.mysql.permission.RoleMapper;
import cn.iocoder.yudao.module.system.dal.mysql.permission.UserRoleMapper;
import cn.iocoder.yudao.module.system.dal.mysql.tenant.*;
import cn.iocoder.yudao.module.system.dal.mysql.user.AdminUserMapper;
import cn.iocoder.yudao.module.system.enums.oauth2.OAuth2ClientConstants;
import cn.iocoder.yudao.module.system.enums.permission.RoleCodeEnum;
import cn.iocoder.yudao.module.system.service.dept.DeptService;
import cn.iocoder.yudao.module.system.service.oauth2.OAuth2TokenService;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;

import org.springframework.validation.annotation.Validated;

import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;

import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
import static cn.iocoder.yudao.module.system.enums.ErrorCodeConstants.AUTH_LOGIN_USER_ROLE_NOT_PERMISSION;
import static cn.iocoder.yudao.module.system.enums.ErrorCodeConstants.AUTH_LOGIN_USER_TENANT_IS_EXPIRE;

/**
 * 集团租户关联 Service 实现类
 *
 * @author 系统管理员
 */
@Service
@Validated
public class GroupTenantServiceImpl implements GroupTenantService {

    @Resource
    private GroupTenantMapper groupTenantMapper;
    @Resource
    private TenantMapper tenantMapper;
    @Resource
    private EnterpriseInfoMapper enterpriseInfoMapper;
    @Resource
    private RoleMapper roleMapper;
    @Resource
    private UserRoleMapper userRoleMapper;
    @Resource
    private AdminUserMapper adminUserMapper;
    @Resource
    private DeptService deptService;
    @Resource
    private OAuth2TokenService oauth2TokenService;
    @Resource
    private TenantService tenantService;

    @Resource
    private TenantPackageMapper tenantPackageMapper;
    @Resource
    private UserGroupTenantMapper userGroupTenantMapper;

    @Override
    public void createGroupTenant(GroupTenantSaveReqVO createReqVO) {
        groupTenantMapper.delete(new LambdaQueryWrapperX<GroupTenantDO>()
                .eq(GroupTenantDO::getGroupTenantId, createReqVO.getGroupTenantId()));

        List<Long> tenantIds = createReqVO.getTenantIds();
        tenantIds.forEach(tenantId -> {
            GroupTenantDO groupTenant = new GroupTenantDO();
            groupTenant.setGroupTenantId(createReqVO.getGroupTenantId());
            groupTenant.setOrgTenantId(tenantId);
            groupTenantMapper.insert(groupTenant);

            //创建用户与集团的关系
            UserGroupTenantDO userGroupTenant = new UserGroupTenantDO();
            userGroupTenant.setUserId(SecurityFrameworkUtils.getLoginUserId());
            userGroupTenant.setOrgTenantId(tenantId);
            userGroupTenantMapper.insert(userGroupTenant);
        });


    }

    @Override
    public List<GroupTenantInfoVO> getGroupTenant(Long groupTenantId, String province) {
//        List<GroupTenantDO> groupTenantList = groupTenantMapper.selectList(new LambdaQueryWrapperX<GroupTenantDO>()
//                .eq(GroupTenantDO::getGroupTenantId, groupTenantId));
        List<GroupTenantDO> groupTenantList = groupTenantMapper.selectListByGroupTenantIdAndProvince(groupTenantId, province);

        List<GroupTenantInfoVO> collect = groupTenantList.stream().map(item -> {
            GroupTenantInfoVO groupTenantInfoVO = new GroupTenantInfoVO();
            BeanUtils.copyProperties(item, groupTenantInfoVO);
            TenantDO tenantDO = tenantMapper.selectById(item.getOrgTenantId());
            groupTenantInfoVO.setTenantName(tenantDO.getName());

            EnterpriseInfoDO enterpriseInfo = enterpriseInfoMapper.selectOne(new LambdaQueryWrapperX<EnterpriseInfoDO>()
                    .eq(EnterpriseInfoDO::getTenantId, item.getOrgTenantId()));

            List<TenantPackageDO> packages = tenantService.getTenantPackagesByTenantId(item.getOrgTenantId());
            groupTenantInfoVO.setPackages(packages);
            groupTenantInfoVO.setEnterprise(enterpriseInfo);
            return groupTenantInfoVO;
        }).collect(Collectors.toList());

        return collect;
    }

    @Override
    public void updateGroupTenant(GroupTenantSaveReqVO updateReqVO) {
        List<Long> tenantIds = updateReqVO.getTenantIds();
        //先删除旧数据在生成新数据
        groupTenantMapper.delete(new LambdaQueryWrapperX<GroupTenantDO>()
                .eq(GroupTenantDO::getGroupTenantId, updateReqVO.getGroupTenantId()));

        tenantIds.forEach(tenantId -> {
            GroupTenantDO groupTenant = new GroupTenantDO();
            groupTenant.setGroupTenantId(updateReqVO.getGroupTenantId());
            groupTenant.setOrgTenantId(tenantId);
            groupTenantMapper.insert(groupTenant);
        });

        //todo 增加操作日志记录
    }

    @Override
    public AuthLoginRespVO changeTenantLogin(Long tenantId) {
        TenantDO tenant = tenantService.getTenant(tenantId);
        if (LocalDateTime.now().isAfter(tenant.getExpireTime())) {
            throw exception(AUTH_LOGIN_USER_TENANT_IS_EXPIRE);
        }

        Optional<RoleDO> optional = roleMapper.selectList(new LambdaQueryWrapperX<RoleDO>()
                .eq(RoleDO::getTenantId, tenantId)
                .eq(RoleDO::getCode, RoleCodeEnum.TENANT_ADMIN.getCode())).stream().findFirst();

        if (!optional.isPresent()) {
            throw exception(AUTH_LOGIN_USER_ROLE_NOT_PERMISSION);
        }
        RoleDO roleDO = optional.get();
        UserRoleDO userRoleDO = userRoleMapper.selectOne(new LambdaQueryWrapperX<UserRoleDO>().eq(UserRoleDO::getRoleId, roleDO.getId()));
        //拿到该机构最高权限的账号进行登录
        AdminUserDO adminUserDO = adminUserMapper.selectById(userRoleDO.getUserId());

        OAuth2AccessTokenDO accessTokenDO = oauth2TokenService.createAccessToken(adminUserDO.getId(), UserTypeEnum.ADMIN.getValue(),
                OAuth2ClientConstants.CLIENT_ID_DEFAULT, null);


        // 构建返回结果
        return AuthConvert.INSTANCE.convert(accessTokenDO);
    }

    @Override
    public List<TenantTreeResVO> getGroupTenantTree(Long groupTenantId) {
        List<GroupTenantDO> groupTenantList = groupTenantMapper.selectList(new LambdaQueryWrapperX<GroupTenantDO>()
                .eq(GroupTenantDO::getGroupTenantId, groupTenantId)
                .orderByDesc(GroupTenantDO::getCreateTime));

        return groupTenantList.stream().map(item -> {
            TenantTreeResVO resVO = new TenantTreeResVO();
            List<DeptDO> deptList = deptService.getTreeByTenantId(item.getOrgTenantId());
            TenantDO tenantDO = tenantMapper.selectById(item.getOrgTenantId());
            BeanUtils.copyProperties(tenantDO, resVO);
            resVO.setDeptList(deptList);
            return resVO;
        }).collect(Collectors.toList());
    }

    @Override
    public List<GroupTenantListVO> findAllGroupList() {
        List<GroupTenantDO> groupTenantList = groupTenantMapper.selectList(new LambdaQueryWrapperX<GroupTenantDO>().eq(GroupTenantDO::getDeleted,0));
        Map<Long, List<GroupTenantDO>> map = groupTenantList.stream().collect(Collectors.groupingBy(GroupTenantDO::getGroupTenantId));
        List<GroupTenantListVO> dataList = new ArrayList<>();
        map.forEach((groupTenantId, items) -> {
            TenantDO groupTenantDO = tenantMapper.selectById(groupTenantId);

            GroupTenantListVO listVO = new GroupTenantListVO();
            listVO.setGroupTenantId(groupTenantDO.getId());
            listVO.setGroupTenantName(groupTenantDO.getName());

            List<GroupTenantInfoVO> tenantList = cn.iocoder.yudao.framework.common.util.object.BeanUtils.toBean(items, GroupTenantInfoVO.class);
            for (GroupTenantInfoVO groupTenantInfoVO : tenantList) {
                TenantDO tenantDO = tenantMapper.selectById(groupTenantInfoVO.getOrgTenantId());
                groupTenantInfoVO.setTenantName(tenantDO.getName());
            }
            listVO.setTenantList(tenantList);
            dataList.add(listVO);
        });
        return dataList;
    }
}