package com.competition.modules.pub.service;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.competition.common.exception.BusinessException;
import com.competition.modules.pub.dto.PublicLoginDto;
import com.competition.modules.pub.dto.PublicRegisterDto;
import com.competition.modules.sys.entity.SysRole;
import com.competition.modules.sys.entity.SysTenant;
import com.competition.modules.sys.entity.SysUser;
import com.competition.modules.sys.entity.SysUserRole;
import com.competition.modules.sys.mapper.SysRoleMapper;
import com.competition.modules.sys.mapper.SysTenantMapper;
import com.competition.modules.sys.mapper.SysUserMapper;
import com.competition.modules.sys.mapper.SysUserRoleMapper;
import com.competition.modules.user.entity.UserParentChild;
import com.competition.modules.user.mapper.UserParentChildMapper;
import com.competition.security.util.JwtUtil;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

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

@Slf4j
@Service
@RequiredArgsConstructor
public class PublicAuthService {

    private final SysUserMapper sysUserMapper;
    private final SysUserRoleMapper sysUserRoleMapper;
    private final SysRoleMapper sysRoleMapper;
    private final SysTenantMapper sysTenantMapper;
    private final UserParentChildMapper userParentChildMapper;
    private final PasswordEncoder passwordEncoder;
    private final JwtUtil jwtUtil;
    private final StringRedisTemplate stringRedisTemplate;

    /**
     * 公众端注册
     */
    @Transactional
    public Map<String, Object> register(PublicRegisterDto dto) {
        // 查找公众租户
        SysTenant publicTenant = sysTenantMapper.selectOne(
                new LambdaQueryWrapper<SysTenant>().eq(SysTenant::getCode, "public"));
        if (publicTenant == null) {
            throw new BusinessException(500, "公众租户未配置");
        }

        // 检查用户名是否已存在
        Long existCount = sysUserMapper.selectCount(
                new LambdaQueryWrapper<SysUser>()
                        .eq(SysUser::getUsername, dto.getUsername())
                        .eq(SysUser::getTenantId, publicTenant.getId()));
        if (existCount > 0) {
            throw new BusinessException(400, "用户名已存在");
        }

        // 创建用户
        SysUser user = new SysUser();
        user.setTenantId(publicTenant.getId());
        user.setUsername(dto.getUsername());
        user.setPassword(passwordEncoder.encode(dto.getPassword()));
        user.setNickname(dto.getNickname());
        user.setPhone(dto.getPhone());
        user.setCity(dto.getCity());
        user.setUserSource("self_registered");
        user.setUserType("adult");
        user.setStatus("enabled");
        sysUserMapper.insert(user);

        // 查找或创建 public_user 角色
        SysRole publicRole = sysRoleMapper.selectOne(
                new LambdaQueryWrapper<SysRole>()
                        .eq(SysRole::getCode, "public_user")
                        .eq(SysRole::getTenantId, publicTenant.getId()));
        if (publicRole == null) {
            publicRole = new SysRole();
            publicRole.setTenantId(publicTenant.getId());
            publicRole.setName("公众用户");
            publicRole.setCode("public_user");
            publicRole.setDescription("公众端注册用户默认角色");
            sysRoleMapper.insert(publicRole);
        }

        // 分配角色
        SysUserRole userRole = new SysUserRole();
        userRole.setUserId(user.getId());
        userRole.setRoleId(publicRole.getId());
        sysUserRoleMapper.insert(userRole);

        // 生成 JWT
        String token = jwtUtil.generateToken(user.getId(), user.getUsername(), publicTenant.getId());

        return buildAuthResult(token, user, List.of(publicRole.getCode()));
    }

    /**
     * 公众端登录
     */
    public Map<String, Object> login(PublicLoginDto dto) {
        // 先在公众租户下查找
        SysTenant publicTenant = sysTenantMapper.selectOne(
                new LambdaQueryWrapper<SysTenant>().eq(SysTenant::getCode, "public"));

        SysUser user = null;
        if (publicTenant != null) {
            user = sysUserMapper.selectOne(
                    new LambdaQueryWrapper<SysUser>()
                            .eq(SysUser::getUsername, dto.getUsername())
                            .eq(SysUser::getTenantId, publicTenant.getId()));
        }

        // 如未找到，在所有租户中搜索
        if (user == null) {
            user = sysUserMapper.selectOne(
                    new LambdaQueryWrapper<SysUser>()
                            .eq(SysUser::getUsername, dto.getUsername())
                            .last("LIMIT 1"));
        }

        if (user == null) {
            throw new BusinessException(401, "用户名或密码错误");
        }

        if (!"enabled".equals(user.getStatus())) {
            throw new BusinessException(403, "账号已被禁用");
        }

        if (!passwordEncoder.matches(dto.getPassword(), user.getPassword())) {
            throw new BusinessException(401, "用户名或密码错误");
        }

        // 获取角色
        List<String> roles = getUserRoleCodes(user.getId());

        String token = jwtUtil.generateToken(user.getId(), user.getUsername(), user.getTenantId());
        return buildAuthResult(token, user, roles);
    }

    /**
     * 切换到子女账号
     */
    public Map<String, Object> switchChild(Long parentUserId, Long childUserId) {
        // 验证亲子关系
        Long count = userParentChildMapper.selectCount(
                new LambdaQueryWrapper<UserParentChild>()
                        .eq(UserParentChild::getParentUserId, parentUserId)
                        .eq(UserParentChild::getChildUserId, childUserId));
        if (count == 0) {
            throw new BusinessException(403, "无权切换到该子女账号");
        }

        SysUser childUser = sysUserMapper.selectById(childUserId);
        if (childUser == null) {
            throw new BusinessException(404, "子女账号不存在");
        }

        List<String> roles = getUserRoleCodes(childUser.getId());
        String token = jwtUtil.generateToken(childUser.getId(), childUser.getUsername(), childUser.getTenantId());

        Map<String, Object> result = buildAuthResult(token, childUser, roles);
        // 在用户信息中附加 parentUserId
        @SuppressWarnings("unchecked")
        Map<String, Object> userInfo = (Map<String, Object>) result.get("user");
        userInfo.put("parentUserId", parentUserId);
        return result;
    }

    private List<String> getUserRoleCodes(Long userId) {
        List<SysUserRole> userRoles = sysUserRoleMapper.selectList(
                new LambdaQueryWrapper<SysUserRole>().eq(SysUserRole::getUserId, userId));
        if (userRoles.isEmpty()) {
            return Collections.emptyList();
        }
        List<Long> roleIds = userRoles.stream().map(SysUserRole::getRoleId).collect(Collectors.toList());
        List<SysRole> roles = sysRoleMapper.selectBatchIds(roleIds);
        return roles.stream().map(SysRole::getCode).collect(Collectors.toList());
    }

    private Map<String, Object> buildAuthResult(String token, SysUser user, List<String> roles) {
        Map<String, Object> userInfo = new LinkedHashMap<>();
        userInfo.put("id", user.getId());
        userInfo.put("username", user.getUsername());
        userInfo.put("nickname", user.getNickname());
        userInfo.put("avatar", user.getAvatar());
        userInfo.put("phone", user.getPhone());
        userInfo.put("city", user.getCity());
        userInfo.put("gender", user.getGender());
        userInfo.put("userType", user.getUserType());
        userInfo.put("roles", roles);
        userInfo.put("permissions", Collections.emptyList());

        Map<String, Object> result = new LinkedHashMap<>();
        result.put("token", token);
        result.put("user", userInfo);
        return result;
    }
}
