package com.dji.sample.manage.service.impl;

import com.auth0.jwt.JWT;
import com.auth0.jwt.exceptions.TokenExpiredException;
import com.auth0.jwt.interfaces.DecodedJWT;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.dji.sample.common.model.CustomClaim;
import com.dji.sample.common.util.JwtUtil;
import com.dji.sample.common.util.SecurityUtils;
import com.dji.sample.component.mqtt.config.MqttPropertyConfiguration;
import com.dji.sample.manage.dao.IUserMapper;
import com.dji.sample.manage.model.dto.OrgDTO;
import com.dji.sample.manage.model.dto.UserDTO;
import com.dji.sample.manage.model.dto.UserListDTO;
import com.dji.sample.manage.model.dto.UserOrgDTO;
import com.dji.sample.manage.model.dto.WorkspaceDTO;
import com.dji.sample.manage.model.entity.OrgEntity;
import com.dji.sample.manage.model.entity.UserEntity;
import com.dji.sample.manage.model.entity.UserOrgEntity;
import com.dji.sample.manage.model.entity.WorkspaceEntity;
import com.dji.sample.manage.model.enums.RoleTypeEnum;
import com.dji.sample.manage.model.enums.UserTypeEnum;
import com.dji.sample.manage.service.IOrgService;
import com.dji.sample.manage.service.IUserOrgService;
import com.dji.sample.manage.service.IUserService;
import com.dji.sample.manage.service.IWorkspaceService;
import com.dji.sdk.common.HttpResultResponse;
import com.dji.sdk.common.Pagination;
import com.dji.sdk.common.PaginationData;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import java.time.Instant;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.UUID;
import java.util.stream.Collectors;

import static com.dji.sample.common.util.SecurityUtils.*;

@Service
@Transactional
public class UserServiceImpl extends ServiceImpl<IUserMapper, UserEntity> implements IUserService {

    @Autowired
    private IUserMapper mapper;

    @Autowired
    private MqttPropertyConfiguration mqttPropertyConfiguration;

    @Autowired
    private IWorkspaceService workspaceService;
    
    @Autowired
    private IOrgService orgService;
    
    @Autowired
    private IUserOrgService userOrgService;

    @Override
    public HttpResultResponse getUserByUsername(String username, String orgId) {
        UserEntity userEntity = this.getUserByUsername(username);
        if (userEntity == null) {
            return new HttpResultResponse()
                    .setCode(HttpStatus.UNAUTHORIZED.value())
                    .setMessage("invalid username");
        }
        // 检查用户是否有权限访问该组织
        if (StringUtils.hasText(orgId) && (userEntity.getIsSuperAdmin() == null || userEntity.getIsSuperAdmin() != 1)) {
            Optional<UserOrgEntity> userOrg = userOrgService.getUserOrg(userEntity.getUserId(), orgId);
            if (userOrg.isEmpty()) {
                return new HttpResultResponse()
                        .setCode(HttpStatus.FORBIDDEN.value())
                        .setMessage("User does not have access to this organization");
            }
        }

        UserDTO user = this.entityConvertToDTO(userEntity);
        
        // 获取组织对应的workspaceId
        if (StringUtils.hasText(orgId)) {
            String workspaceId = orgService.getWorkspaceIdByOrgId(orgId);
            user.setWorkspaceId(workspaceId);
            user.setCurrentOrgId(orgId);
        }

        return HttpResultResponse.success(user);
    }

    @Override
    public HttpResultResponse userLogin(String username, String password, Integer flag) {
        // check user
        UserEntity userEntity = this.getUserByUsername(username);
        if (userEntity == null) {
            return new HttpResultResponse()
                    .setCode(HttpStatus.UNAUTHORIZED.value())
                    .setMessage("invalid username");
        }
        // 修改逻辑 跳过web判定
        if (flag != UserTypeEnum.WEB.getVal()) {
            if (flag.intValue() != userEntity.getUserType().intValue()) {
                return HttpResultResponse.error("The account type does not match.");
            }
        }
        // 密码加密验证
        if (!SecurityUtils.matchesPassword(password, userEntity.getPassword())) {
            return new HttpResultResponse()
                    .setCode(HttpStatus.UNAUTHORIZED.value())
                    .setMessage("invalid password");
        }

        // 获取用户所有的组织信息
        List<UserOrgDTO> userOrgs = userOrgService.getUserOrgs(userEntity.getUserId());
        
        // 如果没有组织关系且不是超级管理员，返回错误
        if (CollectionUtils.isEmpty(userOrgs) && userEntity.getIsSuperAdmin() != 1) {
            return new HttpResultResponse()
                    .setCode(HttpStatus.UNAUTHORIZED.value())
                    .setMessage("User does not belong to any organization");
        }
        
        // 选择第一个组织作为当前组织
        String selectedOrgId = "";
        String selectedWorkspaceId = "";
        Integer selectedRoleType = userEntity.getRoleType();
        
        if (!CollectionUtils.isEmpty(userOrgs)) {
            // 如果用户有关联的组织，使用第一个作为默认
            UserOrgDTO firstOrg = userOrgs.get(0);
            selectedOrgId = firstOrg.getOrgId();
            selectedRoleType = firstOrg.getRoleType();
            
            // 获取组织对应的workspaceId
            selectedWorkspaceId = orgService.getWorkspaceIdByOrgId(selectedOrgId);
        } else if (userEntity.getIsSuperAdmin() == 1) {
            // 超级管理员可访问所有组织
            // 获取第一个可用的组织作为默认组织
            List<OrgDTO> allOrgs = orgService.getAllOrgs();
            if (!CollectionUtils.isEmpty(allOrgs)) {
                OrgDTO firstOrg = allOrgs.get(0);
                selectedOrgId = firstOrg.getOrgId();
                selectedWorkspaceId = firstOrg.getWorkspaceId();
                selectedRoleType = RoleTypeEnum.SYS_ADMIN.getVal(); // 超级管理员在所有组织中都是最高权限
                
                // 同时将所有组织信息添加到UserDTO中，使前端可以切换
                userOrgs = allOrgs.stream()
                    .map(org -> UserOrgDTO.builder()
                        .orgId(org.getOrgId())
                        .orgName(org.getOrgName())
                        .roleType(RoleTypeEnum.SYS_ADMIN.getVal())
                        .build())
                    .collect(Collectors.toList());
            } else {
                // // 如果没有任何组织，则获取默认工作空间
                // List<WorkspaceDTO> workspaces = workspaceService.getAllWorkspaces();
                // if (!CollectionUtils.isEmpty(workspaces)) {
                //     selectedWorkspaceId = workspaces.get(0).getWorkspaceId();
                // }
                
                // 没有组织则为空
                userOrgs = List.of();
            }
        }
        
        // 验证工作空间
        if (!StringUtils.hasText(selectedWorkspaceId)) {
            return new HttpResultResponse()
                    .setCode(HttpStatus.UNAUTHORIZED.value())
                    .setMessage("No valid workspace available");
        }

        // 创建token - 使用当前选定的组织、工作空间和角色
        CustomClaim customClaim = new CustomClaim(userEntity.getUserId(),
                userEntity.getUsername(), userEntity.getUserType(),
                selectedRoleType,
                selectedWorkspaceId, selectedOrgId);

        // 添加orgId到claim
        customClaim.setOrgId(selectedOrgId);

        // create token
        String token = JwtUtil.createToken(customClaim.convertToMap());

        UserDTO userDTO = entityConvertToDTO(userEntity);
        userDTO.setMqttAddr(MqttPropertyConfiguration.getBasicMqttAddress());
        userDTO.setAccessToken(token);
        userDTO.setWorkspaceId(selectedWorkspaceId);
        userDTO.setRoleType(selectedRoleType);
        userDTO.setCurrentOrgId(selectedOrgId);
        
        // 添加用户所有组织信息
        userDTO.setOrgs(userOrgs);
        
        return HttpResultResponse.success(userDTO);
    }

    @Override
    public Optional<UserDTO> refreshToken(String token) {
        if (!StringUtils.hasText(token)) {
            return Optional.empty();
        }
        CustomClaim customClaim;
        try {
            DecodedJWT jwt = JwtUtil.verifyToken(token);
            customClaim = new CustomClaim(jwt.getClaims());
        } catch (TokenExpiredException e) {
            customClaim = new CustomClaim(JWT.decode(token).getClaims());
        } catch (Exception e) {
            e.printStackTrace();
            return Optional.empty();
        }
        String refreshToken = JwtUtil.createToken(customClaim.convertToMap());

        UserDTO user = entityConvertToDTO(this.getUserByUsername(customClaim.getUsername()));
        if (Objects.isNull(user)) {
            return Optional.empty();
        }
        user.setWorkspaceId(customClaim.getWorkspaceId());
        user.setAccessToken(refreshToken);
        
        // 获取orgId
        String orgId = (String)customClaim.getOrgId();
        if (StringUtils.hasText(orgId)) {
            user.setCurrentOrgId(orgId);
        }
        
        return Optional.of(user);
    }

    @Override
    public PaginationData<UserListDTO> getUsersByOrgId(long page, long pageSize, String orgId) {
        // 使用新的关联查询方式，基于用户-组织关联表查询
        List<String> userIds = userOrgService.getUserIdsByOrgId(orgId);
        
        if (CollectionUtils.isEmpty(userIds)) {
            return new PaginationData<>(
                    List.of(), 
                    new Pagination(page, pageSize, 0L)
            );
        }
        
        // 分页查询符合条件的用户
        Page<UserEntity> userEntityPage = mapper.selectPage(
                new Page<>(page, pageSize),
                new LambdaQueryWrapper<UserEntity>().in(UserEntity::getUserId, userIds)
        );
        
        // 查询用户在此组织中的角色
        Map<String, Integer> userRoleMap = userOrgService.getUserRoleMapByOrgId(orgId);
        
        // 获取组织对应的workspaceId
        String workspaceId = orgService.getWorkspaceIdByOrgId(orgId);

        List<UserListDTO> usersList = userEntityPage.getRecords()
                .stream()
                .map(entity -> {
                    // 使用组织中的角色覆盖用户默认角色
                    Integer roleInOrg = userRoleMap.getOrDefault(entity.getUserId(), entity.getRoleType());
                    return entity2UserListDTO(entity, workspaceId, roleInOrg, orgId);
                })
                .collect(Collectors.toList());
                
        return new PaginationData<>(
                usersList, 
                new Pagination(userEntityPage.getCurrent(), userEntityPage.getSize(), userEntityPage.getTotal())
        );
    }

    @Override
    public Boolean updateUser(String orgId, String userId, UserListDTO user) {
        UserEntity userEntity = mapper.selectOne(
                new LambdaQueryWrapper<UserEntity>()
                        .eq(UserEntity::getUserId, userId));
        if (userEntity == null) {
            return false;
        }
        
        // 检查用户是否在该组织中
        Optional<UserOrgEntity> userOrgOpt = userOrgService.getUserOrg(userId, orgId);
        if (userOrgOpt.isEmpty()) {
            return false;
        }
        
        userEntity.setMqttUsername(user.getMqttUsername());
        userEntity.setMqttPassword(user.getMqttPassword());
        userEntity.setEmail(user.getEmail());
        userEntity.setPhone(user.getPhone());
        userEntity.setUpdateTime(System.currentTimeMillis());
        
        // 设置更新者信息
        userEntity.setUpdaterId(SecurityUtils.getUserId());
        userEntity.setUpdaterName(SecurityUtils.getUsername());
        
        int id = mapper.update(userEntity, new LambdaUpdateWrapper<UserEntity>()
                .eq(UserEntity::getUserId, userId));
        
        // 更新用户在组织中的角色
        if (user.getRoleType() != null) {
            userOrgService.updateUserOrgRole(userId, orgId, user.getRoleType());
        }

        return id > 0;
    }

    @Override
    public Boolean deleteUser(String orgId, String userId) {
        // 管理员以上才能删除
        aboveAdminRoleAndThrowError();
        
        // 不能删除自身
        if (userId.equals(getUserId())) {
            throw new RuntimeException("can't delete self");
        }
        
        UserEntity userEntity = this.mapper.selectOne(
                new LambdaQueryWrapper<UserEntity>()
                        .eq(UserEntity::getUserId, userId));
        
        if (userEntity == null) {
            return false;
        }
        
        // 不能删除高级用户
        if (userEntity.getRoleType() == RoleTypeEnum.SYS_ADMIN.getVal()) {
            aboveSysAdminRoleAndThrowError();
        }

        // 如果用户是超级管理员，不允许删除
        if (userEntity.getIsSuperAdmin() == 1) {
            throw new RuntimeException("Cannot delete super admin user");
        }
        
        // 检查用户在组织中的角色
        Optional<UserOrgEntity> userOrgOpt = userOrgService.getUserOrg(userId, orgId);
        if (userOrgOpt.isPresent()) {
            UserOrgEntity userOrg = userOrgOpt.get();
            
            // 如果用户是组织管理员，检查是否是唯一的组织管理员
            if (userOrg.getRoleType() == RoleTypeEnum.ADMIN.getVal() || 
                userOrg.getRoleType() == RoleTypeEnum.ORG_ADMIN.getVal()) {
                
                // 检查是否还有其他管理员
                List<String> adminUserIds = userOrgService.list(
                        new LambdaQueryWrapper<UserOrgEntity>()
                                .eq(UserOrgEntity::getOrgId, orgId)
                                .eq(UserOrgEntity::getRoleType, RoleTypeEnum.ADMIN.getVal())
                                .or()
                                .eq(UserOrgEntity::getRoleType, RoleTypeEnum.ORG_ADMIN.getVal())
                ).stream().map(UserOrgEntity::getUserId).collect(Collectors.toList());
                
                if (adminUserIds.size() <= 1) {
                    throw new RuntimeException("Cannot delete the last administrator of the organization");
                }
            }
            
            // 从组织中移除用户
            userOrgService.removeUserFromOrg(userId, orgId);
        }
        
        // 检查用户是否还属于任何组织
        List<UserOrgDTO> remainingOrgs = userOrgService.getUserOrgs(userId);
        
        // 如果用户不再属于任何组织，删除用户
        if (CollectionUtils.isEmpty(remainingOrgs)) {
            int delete = mapper.delete(
                    new LambdaQueryWrapper<UserEntity>()
                            .eq(UserEntity::getUserId, userId));
            return delete > 0;
        }
        
        return true;
    }

    @Override
    public Boolean addUser(String orgId, UserEntity user) {
        // 管理员才能创建用户
        aboveAdminRoleAndThrowError();

        // 用户名不能重复
        String username = user.getUsername();
        LambdaQueryWrapper<UserEntity> userQueryWrapper = new LambdaQueryWrapper<>();
        userQueryWrapper.eq(UserEntity::getUsername, username);
        List<UserEntity> nameUserList = this.mapper.selectList(userQueryWrapper);
        
        // 检查用户是否已存在
        UserEntity userEntity;
        if (!CollectionUtils.isEmpty(nameUserList)) {
            // 如果用户已存在，检查是否已在该组织中
            userEntity = nameUserList.get(0);
            Optional<UserOrgEntity> userOrgOpt = userOrgService.getUserOrg(userEntity.getUserId(), orgId);
            if (userOrgOpt.isPresent()) {
                throw new RuntimeException("User already exists in this organization");
            }
        } else {
            // 创建新用户
            userEntity = new UserEntity();
            userEntity.setUserType(user.getUserType() != null ? user.getUserType() : UserTypeEnum.PILOT.getVal());
            userEntity.setRoleType(user.getRoleType() != null ? user.getRoleType() : RoleTypeEnum.MEMBER.getVal());
            userEntity.setUserId(UUID.randomUUID().toString());
            userEntity.setPassword(SecurityUtils.encryptPassword(user.getPassword()));
            userEntity.setUsername(user.getUsername());
            userEntity.setEmail(user.getEmail());
            userEntity.setPhone(user.getPhone());
            userEntity.setIsSuperAdmin(user.getIsSuperAdmin() != null ? user.getIsSuperAdmin() : 0);
            userEntity.setCreateTime(System.currentTimeMillis());
            userEntity.setUpdateTime(System.currentTimeMillis());
            
            // 设置创建者和更新者信息
            String currentUserId = SecurityUtils.getUserId();
            String currentUserName = SecurityUtils.getUsername();
            
            userEntity.setCreatorId(currentUserId);
            userEntity.setCreatorName(currentUserName);
            userEntity.setUpdaterId(currentUserId);
            userEntity.setUpdaterName(currentUserName);
            
            // 保存用户信息
            this.mapper.insert(userEntity);
        }
        
        // 不能创建高级用户
        if (user.getRoleType() == RoleTypeEnum.SYS_ADMIN.getVal()) {
            aboveSysAdminRoleAndThrowError();
        }
        
        // 保存用户与组织的关联信息
        if (StringUtils.hasText(orgId)) {
            return userOrgService.addUserToOrg(
                    userEntity.getUserId(), 
                    orgId, 
                    user.getRoleType() != null ? user.getRoleType() : RoleTypeEnum.MEMBER.getVal()
            );
        }
        
        return true;
    }

    /**
     * Convert database entity objects into user data transfer object.
     * @param entity 用户实体
     * @param workspaceId 工作空间ID
     * @param roleTypeInOrg 用户在指定组织中的角色
     * @param orgId 组织ID
     * @return 用户列表展示对象
     */
    private UserListDTO entity2UserListDTO(UserEntity entity, String workspaceId, Integer roleTypeInOrg, String orgId) {
        UserListDTO.UserListDTOBuilder builder = UserListDTO.builder();
        if (entity != null) {
            builder.userId(entity.getUserId())
                    .id(entity.getId())
                    .username(entity.getUsername())
                    .mqttUsername(entity.getMqttUsername())
                    .mqttPassword(entity.getMqttPassword())
                    .userType(UserTypeEnum.find(entity.getUserType()).getDesc())
                    .roleTypeName(RoleTypeEnum.find(roleTypeInOrg).getDesc())  // 使用组织内的角色
                    .roleType(roleTypeInOrg)  // 使用组织内的角色
                    .email(entity.getEmail())
                    .phone(entity.getPhone())
                    .isSuperAdmin(entity.getIsSuperAdmin())
                    .createTime(LocalDateTime.ofInstant(
                            Instant.ofEpochMilli(entity.getCreateTime()), ZoneId.systemDefault()));
                    
            // 获取组织名称
            Optional<OrgDTO> orgOpt = orgService.getOrgByOrgId(orgId);
            orgOpt.ifPresent(org -> builder.workspaceName(org.getOrgName())); // 用组织名称代替工作空间名称
        }

        return builder.build();
    }

    /**
     * Convert database entity objects into user data transfer object.
     * 为了保持兼容性保留原方法
     */
    private UserListDTO entity2UserListDTO(UserEntity entity) {
        UserListDTO.UserListDTOBuilder builder = UserListDTO.builder();
        if (entity != null) {
            builder.userId(entity.getUserId())
                    .id(entity.getId())
                    .username(entity.getUsername())
                    .mqttUsername(entity.getMqttUsername())
                    .mqttPassword(entity.getMqttPassword())
                    .userType(UserTypeEnum.find(entity.getUserType()).getDesc())
                    .roleTypeName(RoleTypeEnum.find(entity.getRoleType()).getDesc())
                    .roleType(entity.getRoleType())
                    .email(entity.getEmail())
                    .phone(entity.getPhone())
                    .isSuperAdmin(entity.getIsSuperAdmin())
                    .createTime(LocalDateTime.ofInstant(
                            Instant.ofEpochMilli(entity.getCreateTime()), ZoneId.systemDefault()));
        }

        return builder.build();
    }

    /**
     * Query a user by username.
     * @param username
     * @return
     */
    private UserEntity getUserByUsername(String username) {
        return mapper.selectOne(new QueryWrapper<UserEntity>()
                .eq("username", username));
    }

    /**
     * Query a user by username.
     * @param userId
     * @return
     */
    private UserEntity getUserByUserId(String userId) {
        return mapper.selectOne(new QueryWrapper<UserEntity>()
                .eq("user_id", userId));
    }

    /**
     * Convert database entity objects into user data transfer object.
     * @param entity
     * @return
     */
    private UserDTO entityConvertToDTO(UserEntity entity) {
        if (entity == null) {
            return null;
        }
        return UserDTO.builder()
                .userId(entity.getUserId())
                .username(entity.getUsername())
                .userType(entity.getUserType())
                .roleType(entity.getRoleType())
                .mqttUsername(entity.getMqttUsername())
                .mqttPassword(entity.getMqttPassword())
                .mqttAddr(MqttPropertyConfiguration.getBasicMqttAddress())
                .email(entity.getEmail())
                .phone(entity.getPhone())
                .isSuperAdmin(entity.getIsSuperAdmin())
                .build();
    }

    /**
     * Query user's details based on userId
     * @param userId
     * @param workspaceId
     * @return
     */
    @Override
    public HttpResultResponse getUserByUserId(String userId, String workspaceId) {

        UserEntity userEntity = this.getUserByUserId(userId);
        if (userEntity == null) {
            return new HttpResultResponse()
                    .setCode(HttpStatus.UNAUTHORIZED.value())
                    .setMessage("invalid userId");
        }

        UserDTO user = this.entityConvertToDTO(userEntity);
        user.setWorkspaceId(workspaceId);

        return HttpResultResponse.success(user);
    }

    // 更新方法签名以适应组织架构
    @Override
    public PaginationData<UserListDTO> getUsersByWorkspaceId(long page, long pageSize, String workspaceId) {
        // 查找使用该workspaceId的所有组织
        List<OrgDTO> orgs = orgService.list(
                new LambdaQueryWrapper<OrgEntity>()
                        .eq(OrgEntity::getWorkspaceId, workspaceId)
        ).stream().map(org -> OrgDTO.builder()
                .orgId(org.getOrgId())
                .orgName(org.getOrgName())
                .workspaceId(org.getWorkspaceId())
                .build()).collect(Collectors.toList());
        
        if (CollectionUtils.isEmpty(orgs)) {
            return new PaginationData<>(
                    List.of(),
                    new Pagination(page, pageSize, 0L)
            );
        }
        
        // 使用第一个组织的用户列表
        return getUsersByOrgId(page, pageSize, orgs.get(0).getOrgId());
    }

    // addWorkspaceAdminUser
    @Override
    public UserEntity addWorkspaceAdminUser(UserEntity user) {
        return user;
    }
}
