package com.lesingle.creation.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.lesingle.creation.common.enums.UserStatusEnum;
import com.lesingle.creation.common.exception.BusinessException;
import com.lesingle.creation.common.util.JwtTokenUtil;
import com.lesingle.creation.dto.auth.LoginDTO;
import com.lesingle.creation.entity.*;
import com.lesingle.creation.mapper.*;
import com.lesingle.creation.service.AuthService;
import com.lesingle.creation.vo.auth.LoginResponseVO;
import com.lesingle.creation.vo.auth.UserInfoVO;
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.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

/**
 * 认证服务实现类
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class AuthServiceImpl implements AuthService {

    private final UserMapper userMapper;
    private final TenantMapper tenantMapper;
    private final UserRoleMapper userRoleMapper;
    private final RoleMapper roleMapper;
    private final PermissionMapper permissionMapper;
    private final RolePermissionMapper rolePermissionMapper;
    private final JwtTokenUtil jwtTokenUtil;
    private final PasswordEncoder passwordEncoder;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public LoginResponseVO login(LoginDTO loginDTO) {
        String username = loginDTO.getUsername();
        String password = loginDTO.getPassword();
        String tenantCode = loginDTO.getTenantCode();

        log.info("登录请求：username={}, tenantCode={}", username, tenantCode);

        // 1. 根据用户名查询用户
        User user = userMapper.selectOne(new LambdaQueryWrapper<User>()
                .eq(User::getUsername, username)
                .eq(User::getDeleted, 0));

        if (user == null) {
            log.warn("用户不存在：{}", username);
            throw new BusinessException("用户名或密码错误");
        }

        log.info("用户查询成功，ID={}, tenantId={}", user.getId(), user.getTenantId());
        log.info("数据库密码哈希：{}", user.getPassword());
        log.info("输入密码：{}", password);

        // 2. 验证密码
        boolean passwordMatches = passwordEncoder.matches(password, user.getPassword());
        log.info("密码验证结果：{}", passwordMatches);
        if (!passwordMatches) {
            log.warn("密码不匹配，用户名：{}", username);
            throw new BusinessException("用户名或密码错误");
        }

        // 3. 验证租户
        Long tenantId;
        if (tenantCode != null && !tenantCode.isEmpty()) {
            // 根据租户编码查询租户
            Tenant tenant = tenantMapper.selectOne(new LambdaQueryWrapper<Tenant>()
                    .eq(Tenant::getCode, tenantCode));
            if (tenant == null) {
                throw new BusinessException("租户不存在");
            }
            if (tenant.getValidState() != 1) {
                throw new BusinessException("租户已失效");
            }
            tenantId = tenant.getId();
        } else {
            tenantId = user.getTenantId();
        }
        if (tenantId == null) {
            throw new BusinessException("请指定租户编码");
        }

        // 4. 验证租户是否有效
        Tenant tenant = tenantMapper.selectById(tenantId);
        if (tenant == null) {
            throw new BusinessException("租户不存在");
        }
        if (tenant.getValidState() != 1) {
            throw new BusinessException("租户已失效");
        }

        // 5. 验证用户是否属于该租户
        if (!user.getTenantId().equals(tenantId)) {
            throw new BusinessException("用户不属于该租户");
        }

        // 6. 验证用户状态
        if (!UserStatusEnum.ENABLED.getCode().equals(user.getStatus())) {
            throw new BusinessException("用户账号已停用");
        }

        // 7. 生成 JWT Token
        String token = jwtTokenUtil.generateToken(user.getId(), tenantId, tenant.getCode());

        // 8. 构建用户信息
        UserInfoVO userInfo = buildUserInfo(user, tenantId);

        LoginResponseVO response = new LoginResponseVO();
        response.setToken(token);
        response.setUser(userInfo);

        log.info("用户登录成功，用户名={}, 租户编码={}", username, tenantCode);

        return response;
    }

    @Override
    public UserInfoVO getUserInfo(Long userId) {
        User user = userMapper.selectById(userId);
        if (user == null) {
            throw new BusinessException("用户不存在");
        }

        return buildUserInfo(user, user.getTenantId());
    }

    @Override
    public void logout(Long userId) {
        // TODO: 可以将 token 加入黑名单（使用 Redis）
        log.info("用户登出成功，用户 ID={}", userId);
    }

    @Override
    public LoginResponseVO refreshToken(String token) {
        try {
            // 1. 解析 token 获取用户 ID
            Long userId = jwtTokenUtil.getUserIdFromToken(token.replace("Bearer ", ""));
            if (userId == null) {
                throw new BusinessException("Token 无效");
            }

            // 2. 查询用户信息
            User user = userMapper.selectById(userId);
            if (user == null) {
                throw new BusinessException("用户不存在");
            }

            // 3. 生成新的 token
            String newToken = jwtTokenUtil.generateToken(
                    user.getId(),
                    user.getTenantId(),
                    tenantMapper.selectById(user.getTenantId()).getCode()
            );

            // 4. 构建响应
            UserInfoVO userInfo = buildUserInfo(user, user.getTenantId());
            LoginResponseVO response = new LoginResponseVO();
            response.setToken(newToken);
            response.setUser(userInfo);

            log.info("刷新 Token 成功，用户 ID={}", userId);
            return response;

        } catch (Exception e) {
            log.error("刷新 Token 失败", e);
            throw new BusinessException("刷新 Token 失败");
        }
    }

    /**
     * 构建用户信息 VO
     */
    private UserInfoVO buildUserInfo(User user, Long tenantId) {
        UserInfoVO vo = new UserInfoVO();
        vo.setId(user.getId());
        vo.setUsername(user.getUsername());
        vo.setNickname(user.getNickname());
        vo.setEmail(user.getEmail());
        vo.setAvatar(user.getAvatar());
        vo.setTenantId(user.getTenantId());

        // 获取租户编码
        Tenant tenant = tenantMapper.selectById(tenantId);
        if (tenant != null) {
            vo.setTenantCode(tenant.getCode());
        }

        // 获取用户角色列表
        List<String> roles = getUserRoles(user.getId());
        vo.setRoles(roles);

        // 获取用户权限列表
        List<String> permissions = getUserPermissions(user.getId());
        vo.setPermissions(permissions);

        return vo;
    }

    /**
     * 获取用户角色列表
     */
    private List<String> getUserRoles(Long userId) {
        // 查询用户关联的角色
        List<UserRole> userRoles = userRoleMapper.selectList(
                new LambdaQueryWrapper<UserRole>()
                        .eq(UserRole::getUserId, userId)
        );

        if (userRoles.isEmpty()) {
            return new ArrayList<>();
        }

        // 获取角色 ID 列表
        List<Long> roleIds = userRoles.stream()
                .map(UserRole::getRoleId)
                .collect(Collectors.toList());

        // 查询角色详情
        List<Role> roles = roleMapper.selectBatchIds(roleIds);

        // 返回角色编码列表（只返回有效的角色）
        return roles.stream()
                .filter(role -> role.getValidState() == 1)
                .map(Role::getCode)
                .collect(Collectors.toList());
    }

    /**
     * 获取用户权限列表
     */
    private List<String> getUserPermissions(Long userId) {
        // 查询用户关联的角色
        List<UserRole> userRoles = userRoleMapper.selectList(
                new LambdaQueryWrapper<UserRole>()
                        .eq(UserRole::getUserId, userId)
        );

        if (userRoles.isEmpty()) {
            return new ArrayList<>();
        }

        // 获取角色 ID 列表
        List<Long> roleIds = userRoles.stream()
                .map(UserRole::getRoleId)
                .collect(Collectors.toList());

        // 查询角色关联的权限
        List<RolePermission> rolePermissions = rolePermissionMapper.selectList(
                new LambdaQueryWrapper<RolePermission>()
                        .in(RolePermission::getRoleId, roleIds)
        );

        if (rolePermissions.isEmpty()) {
            return new ArrayList<>();
        }

        // 获取权限 ID 列表
        List<Long> permissionIds = rolePermissions.stream()
                .map(RolePermission::getPermissionId)
                .distinct()
                .collect(Collectors.toList());

        // 查询权限详情
        List<Permission> permissions = permissionMapper.selectBatchIds(permissionIds);

        // 返回权限编码列表（只返回有效的权限）
        return permissions.stream()
                .filter(permission -> permission.getValidState() == 1)
                .map(Permission::getCode)
                .collect(Collectors.toList());
    }
}
