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

import cn.hutool.crypto.SecureUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.lesingle.common.constants.BaseEntityConstants;
import com.lesingle.common.constants.TenantConstants;
import com.lesingle.common.enums.CommonStatus;
import com.lesingle.common.enums.ErrorCode;
import com.lesingle.common.enums.UserSource;
import com.lesingle.common.enums.UserType;
import com.lesingle.common.exception.BusinessException;
import com.lesingle.common.result.PageResult;
import com.lesingle.modules.sys.dto.CreateUserDto;
import com.lesingle.modules.sys.dto.UpdateUserDto;
import com.lesingle.modules.sys.entity.SysRole;
import com.lesingle.modules.sys.entity.SysTenant;
import com.lesingle.modules.sys.entity.SysUser;
import com.lesingle.modules.sys.entity.SysUserRole;
import com.lesingle.modules.sys.mapper.SysRoleMapper;
import com.lesingle.modules.sys.mapper.SysTenantMapper;
import com.lesingle.modules.sys.mapper.SysUserMapper;
import com.lesingle.modules.sys.mapper.SysUserRoleMapper;
import com.lesingle.modules.sys.service.ISysUserService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;

@Slf4j
@Service
@RequiredArgsConstructor
public class SysUserServiceImpl extends ServiceImpl<SysUserMapper, SysUser> implements ISysUserService {

    private final SysUserRoleMapper userRoleMapper;
    private final SysRoleMapper roleMapper;
    private final SysTenantMapper tenantMapper;
    private final PasswordEncoder passwordEncoder;

    @Override
    @Transactional
    public Map<String, Object> createUser(CreateUserDto dto, Long tenantId) {
        log.info("开始创建用户，用户名：{}，租户：{}", dto.getUsername(), tenantId);

        // 验证角色是否属于该租户
        if (dto.getRoleIds() != null && !dto.getRoleIds().isEmpty()) {
            List<SysRole> roles = roleMapper.selectList(
                    new LambdaQueryWrapper<SysRole>()
                            .in(SysRole::getId, dto.getRoleIds())
                            .eq(SysRole::getTenantId, tenantId)
            );
            if (roles.size() != dto.getRoleIds().size()) {
                throw BusinessException.of(ErrorCode.NOT_FOUND, "部分角色不存在或不属于该租户");
            }
        }

        SysUser user = new SysUser();
        user.setTenantId(tenantId);
        user.setUsername(dto.getUsername());
        user.setPassword(passwordEncoder.encode(dto.getPassword()));
        user.setNickname(dto.getNickname());
        user.setEmail(dto.getEmail());
        user.setPhone(dto.getPhone());
        user.setGender(dto.getGender());
        user.setAvatar(dto.getAvatar());
        user.setStatus(dto.getStatus() != null ? dto.getStatus() : CommonStatus.ENABLED.getValue());
        user.setUserSource(UserSource.ADMIN_CREATED.getValue());
        user.setUserType(UserType.ADULT.getValue());

        baseMapper.insert(user);

        // 创建角色关联
        if (dto.getRoleIds() != null) {
            for (Long roleId : dto.getRoleIds()) {
                SysUserRole ur = new SysUserRole();
                ur.setUserId(user.getId());
                ur.setRoleId(roleId);
                userRoleMapper.insert(ur);
            }
        }

        log.info("用户创建成功，ID：{}", user.getId());
        return findDetail(user.getId(), tenantId, false);
    }

    @Override
    public PageResult<Map<String, Object>> findAll(Long page, Long pageSize, Long tenantId,
                                                     String keyword, boolean isSuperTenant,
                                                     String userType, Long filterTenantId,
                                                     String userSource, String status) {
        Map<String, Object> params = new HashMap<>();

        if (isSuperTenant) {
            // 超管模式：按 userType 映射到租户类型过滤
            if (userType != null) {
                switch (userType) {
                    case "platform" -> params.put("isSuperTenantFilter", 1);
                    case "org" -> {
                        // 排除超管、公众、评委租户，使用 org 租户 ID 列表过滤
                        List<Long> orgTenantIds = getOrgTenantIds();
                        if (orgTenantIds.isEmpty()) {
                            // 如果没有机构租户，返回空结果
                            return new PageResult<>(List.of(), 0L, page, pageSize);
                        }
                        params.put("orgTenantIdsFilter", orgTenantIds);
                    }
                    case "judge" -> {
                        // 按租户 code='judge' 过滤（因为 judge 租户的 tenant_type 可能是 other）
                        params.put("tenantCodeFilter", TenantConstants.CODE_JUDGE);
                    }
                    case "public" -> {
                        // 按租户 code='public' 过滤（因为 public 租户的 tenant_type=platform，不是 public）
                        params.put("tenantCodeFilter", TenantConstants.CODE_PUBLIC);
                    }
                }
            }
            if (filterTenantId != null) {
                params.put("filterTenantId", filterTenantId);
            }
            if (userSource != null) params.put("userSource", userSource);
            if (status != null) params.put("status", status);
        } else {
            params.put("tenantId", tenantId);
        }

        if (keyword != null && !keyword.isBlank()) {
            params.put("keyword", keyword);
        }

        IPage<Map<String, Object>> result = baseMapper.selectUserPage(new Page<>(page, pageSize), params);

        // 为每个用户附加角色信息
        for (Map<String, Object> user : result.getRecords()) {
            Long userId = ((Number) user.get("id")).longValue();
            user.put("roles", getRolesWithInfo(userId));
        }

        return PageResult.from(result);
    }

    /**
     * 获取机构租户 ID 列表（排除超管、公众、评委）
     */
    private List<Long> getOrgTenantIds() {
        List<SysTenant> tenants = tenantMapper.selectList(
                new LambdaQueryWrapper<SysTenant>().eq(SysTenant::getValidState, BaseEntityConstants.VALID));
        return tenants.stream()
                .filter(t -> t.getIsSuper() == 0 && !TenantConstants.CODE_PUBLIC.equals(t.getCode()) && !TenantConstants.CODE_JUDGE.equals(t.getCode()))
                .map(SysTenant::getId)
                .toList();
    }

    @Override
    public Map<String, Object> getStats() {
        List<SysTenant> tenants = tenantMapper.selectList(
                new LambdaQueryWrapper<SysTenant>().eq(SysTenant::getValidState, BaseEntityConstants.VALID));

        List<Long> superIds = tenants.stream().filter(t -> t.getIsSuper() == 1).map(SysTenant::getId).toList();
        List<Long> publicIds = tenants.stream().filter(t -> TenantConstants.CODE_PUBLIC.equals(t.getCode())).map(SysTenant::getId).toList();
        List<Long> judgeIds = tenants.stream().filter(t -> TenantConstants.CODE_JUDGE.equals(t.getCode())).map(SysTenant::getId).toList();
        List<Long> orgIds = tenants.stream()
                .filter(t -> t.getIsSuper() == 0 && !TenantConstants.CODE_PUBLIC.equals(t.getCode()) && !TenantConstants.CODE_JUDGE.equals(t.getCode()))
                .map(SysTenant::getId).toList();

        LambdaQueryWrapper<SysUser> base = new LambdaQueryWrapper<SysUser>().eq(SysUser::getValidState, BaseEntityConstants.VALID);

        Map<String, Object> stats = new HashMap<>();
        stats.put("total", count(base));
        stats.put("platform", superIds.isEmpty() ? 0 : count(new LambdaQueryWrapper<SysUser>().eq(SysUser::getValidState, BaseEntityConstants.VALID).in(SysUser::getTenantId, superIds)));
        stats.put("org", orgIds.isEmpty() ? 0 : count(new LambdaQueryWrapper<SysUser>().eq(SysUser::getValidState, BaseEntityConstants.VALID).in(SysUser::getTenantId, orgIds)));
        stats.put("judge", judgeIds.isEmpty() ? 0 : count(new LambdaQueryWrapper<SysUser>().eq(SysUser::getValidState, BaseEntityConstants.VALID).in(SysUser::getTenantId, judgeIds)));
        stats.put("public", publicIds.isEmpty() ? 0 : count(new LambdaQueryWrapper<SysUser>().eq(SysUser::getValidState, BaseEntityConstants.VALID).in(SysUser::getTenantId, publicIds)));

        return stats;
    }

    @Override
    public Map<String, Object> findDetail(Long id, Long tenantId, boolean isSuperTenant) {
        Map<String, Object> user = baseMapper.selectUserDetail(id, tenantId, isSuperTenant);
        if (user == null) {
            throw BusinessException.of(ErrorCode.NOT_FOUND, "用户不存在");
        }
        // 附加角色和权限
        user.put("roles", getRolesWithInfo(id));
        return user;
    }

    @Override
    public SysUser findByUsername(String username, Long tenantId) {
        LambdaQueryWrapper<SysUser> wrapper = new LambdaQueryWrapper<SysUser>()
                .eq(SysUser::getUsername, username)
                .eq(SysUser::getValidState, BaseEntityConstants.VALID);
        if (tenantId != null) {
            wrapper.eq(SysUser::getTenantId, tenantId);
        }
        return getOne(wrapper, false);
    }

    @Override
    @Transactional
    public Map<String, Object> updateUser(Long id, UpdateUserDto dto, Long tenantId) {
        log.info("开始更新用户，ID：{}", id);
        SysUser existing = getById(id);
        if (existing == null) {
            throw BusinessException.of(ErrorCode.NOT_FOUND, "用户不存在");
        }

        SysUser user = new SysUser();
        user.setId(id);
        if (dto.getUsername() != null) user.setUsername(dto.getUsername());
        if (dto.getNickname() != null) user.setNickname(dto.getNickname());
        if (dto.getEmail() != null) user.setEmail(dto.getEmail());
        if (dto.getPhone() != null) user.setPhone(dto.getPhone());
        if (dto.getGender() != null) user.setGender(dto.getGender());
        if (dto.getAvatar() != null) user.setAvatar(dto.getAvatar());
        if (dto.getStatus() != null) user.setStatus(dto.getStatus());
        if (dto.getPassword() != null && !dto.getPassword().isBlank()) {
            user.setPassword(passwordEncoder.encode(dto.getPassword()));
        }
        baseMapper.updateById(user);

        // 更新角色关联
        if (dto.getRoleIds() != null) {
            userRoleMapper.delete(new LambdaQueryWrapper<SysUserRole>().eq(SysUserRole::getUserId, id));
            for (Long roleId : dto.getRoleIds()) {
                SysUserRole ur = new SysUserRole();
                ur.setUserId(id);
                ur.setRoleId(roleId);
                userRoleMapper.insert(ur);
            }
        }

        return findDetail(id, tenantId, tenantId == null);
    }

    @Override
    public void updateStatus(Long id, String status, Long operatorId) {
        log.info("更新用户状态，ID：{}，状态：{}", id, status);
        SysUser user = new SysUser();
        user.setId(id);
        user.setStatus(status);
        baseMapper.updateById(user);
    }

    @Override
    public void removeUser(Long id, Long tenantId) {
        log.info("删除用户，ID：{}", id);
        // 逻辑删除
        removeById(id);
    }

    @Override
    public List<String> getPermissions(Long userId) {
        return baseMapper.selectPermissionsByUserId(userId);
    }

    @Override
    public List<String> getRoles(Long userId) {
        return baseMapper.selectRolesByUserId(userId);
    }

    /** 获取用户角色（含角色对象信息） */
    private List<Map<String, Object>> getRolesWithInfo(Long userId) {
        List<SysUserRole> userRoles = userRoleMapper.selectList(
                new LambdaQueryWrapper<SysUserRole>().eq(SysUserRole::getUserId, userId));
        List<Map<String, Object>> result = new ArrayList<>();
        for (SysUserRole ur : userRoles) {
            SysRole role = roleMapper.selectById(ur.getRoleId());
            if (role != null) {
                Map<String, Object> roleMap = new HashMap<>();
                roleMap.put("roleId", ur.getRoleId());
                roleMap.put("role", role);
                result.add(roleMap);
            }
        }
        return result;
    }
}
