package com.qqchen.deploy.backend.system.service.impl;

import com.qqchen.deploy.backend.system.converter.UserConverter;
import com.qqchen.deploy.backend.framework.annotation.ServiceType;
import com.qqchen.deploy.backend.framework.annotation.Audited;
import com.qqchen.deploy.backend.framework.enums.ResponseCode;
import com.qqchen.deploy.backend.framework.exception.BusinessException;
import com.qqchen.deploy.backend.framework.exception.UniqueConstraintException;
import com.qqchen.deploy.backend.framework.security.SecurityUtils;
import com.qqchen.deploy.backend.framework.security.util.JwtTokenUtil;
import com.qqchen.deploy.backend.framework.service.impl.BaseServiceImpl;
import com.qqchen.deploy.backend.framework.utils.PasswordGenerator;
import com.qqchen.deploy.backend.system.model.query.UserQuery;
import com.qqchen.deploy.backend.system.model.request.LoginRequest;
import com.qqchen.deploy.backend.system.model.request.UserRequest;
import com.qqchen.deploy.backend.system.model.response.LoginResponse;
import com.qqchen.deploy.backend.system.entity.User;
import com.qqchen.deploy.backend.system.repository.IUserRepository;
import com.qqchen.deploy.backend.system.service.IUserService;
import com.qqchen.deploy.backend.system.converter.RoleConverter;
import com.qqchen.deploy.backend.system.model.UserDTO;
import com.qqchen.deploy.backend.system.model.RoleDTO;
import com.qqchen.deploy.backend.system.repository.IDepartmentRepository;
import com.qqchen.deploy.backend.system.entity.Department;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.hibernate.Hibernate;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import java.util.ArrayList;
import java.util.List;

import static com.qqchen.deploy.backend.framework.annotation.ServiceType.Type.DATABASE;

@Service
@ServiceType(DATABASE)
@Slf4j
public class UserServiceImpl extends BaseServiceImpl<User, UserDTO, UserQuery, Long> implements IUserService {

    @Resource
    private RoleConverter roleConverter;

    @Resource
    private UserConverter userConverter;
    
    @Resource
    private AuthenticationManager authenticationManager;

    @Resource
    private IUserRepository userRepository;
    
    @Resource
    private JwtTokenUtil jwtTokenUtil;

    @Resource
    private IDepartmentRepository departmentRepository;

    @Override
    @Transactional(readOnly = false)
    @Audited(action = "REGISTER", detail = "用户注册")
    public UserDTO register(UserRequest request) {
        if (checkUsernameExists(request.getUsername())) {
            throw new BusinessException(ResponseCode.USERNAME_EXISTS);
        }
        if (checkEmailExists(request.getEmail())) {
            throw new BusinessException(ResponseCode.EMAIL_EXISTS);
        }
        
        UserDTO userDTO = new UserDTO();
        userDTO.setUsername(request.getUsername());
        userDTO.setEmail(request.getEmail());
        userDTO.setNickname(request.getNickname());
        userDTO.setPhone(request.getPhone());
        return create(userDTO);
    }

    @Override
    public boolean checkUsernameExists(String username) {
        return false;
    }

    @Override
    public boolean checkEmailExists(String email) {
        return false;
    }

    @Override
    @Transactional(readOnly = true)
    @Audited(action = "USER_LOGIN", detail = "登录")
    public LoginResponse login(LoginRequest request) {
        Authentication authentication = authenticationManager.authenticate(
            new UsernamePasswordAuthenticationToken(request.getUsername(), request.getPassword())
        );
        UserDetails userDetails = (UserDetails) authentication.getPrincipal();
        String token = jwtTokenUtil.generateToken(userDetails);
        User user = userRepository.findByUsernameAndDeletedFalse(userDetails.getUsername())
            .orElseThrow(() -> new BusinessException(ResponseCode.USER_NOT_FOUND));
        
        LoginResponse response = userConverter.toLoginResponse(user, token);
        log.info("用户 {} ({}) 登录成功", user.getUsername(), user.getNickname());
        return response;
    }

    @Override
    @Transactional(readOnly = true)
    public List<RoleDTO> getUserRoles(Long userId) {
        User user = findEntityById(userId);
        Hibernate.initialize(user.getRoles());
        return roleConverter.toDtoList(new ArrayList<>(user.getRoles()));
    }

    @Override
    @Transactional(readOnly = true)
    public List<RoleDTO> getCurrentUserRoles() {
//        String username = SecurityUtils.getCurrentUsername();
//        User user = repository.findByUsernameAndDeletedFalse(username)
//            .orElseThrow(() -> new BusinessException(ResponseCode.USER_NOT_FOUND));
//        Hibernate.initialize(user.getRoles());
//        return roleConverter.toDtoList(new ArrayList<>(user.getRoles()));
        return null;
    }

//    @Override
//    public List<UserDTO> findAll(BaseQuery query) {
//        return null;
//    }

    @Override
    @Transactional(readOnly = false)
    @Audited(action = "CHANGE_PASSWORD", detail = "修改密码")
    public void changePassword(Long userId, String oldPassword, String newPassword) {
        // ... 密码修改逻辑 ...
    }

    @Override
    @Transactional(readOnly = true)
    @Audited(action = "GET_CURRENT_USER", detail = "获取当前用户信息")
    public UserDTO getCurrentUser() {
        String username = SecurityUtils.getCurrentUsername();
        User user = userRepository.findByUsernameAndDeletedFalse(username)
            .orElseThrow(() -> new BusinessException(ResponseCode.USER_NOT_FOUND));
        
        log.debug("获取当前用户信息: {}", user.getUsername());
        return userConverter.toDto(user);
    }

    @Override
    @Transactional(readOnly = true)
    public LoginResponse getCurrentUserResponse() {
        // 复用getCurrentUser方法，直接转换DTO为LoginResponse
        UserDTO userDTO = getCurrentUser();
        return userConverter.toLoginResponse(userDTO);
    }

    @Override
    @Transactional(readOnly = false)
    @Audited(action = "RESET_PASSWORD", detail = "重置密码")
    public void resetPassword(Long userId, String newPassword) {
        User user = findEntityById(userId);
        String encodedPassword = PasswordGenerator.encode(newPassword);
        user.setPassword(encodedPassword);
        repository.save(user);
        log.info("用户 {} 密码已重置", user.getUsername());
    }

    @Override
    @Transactional
    @Audited(action = "ASSIGN_DEPARTMENT", detail = "分配部门")
    public void assignDepartment(Long userId, Long departmentId) {
        // 获取用户
        User user = findEntityById(userId);
        // 获取部门
        Department department = departmentRepository.findById(departmentId)
            .orElseThrow(() -> new BusinessException(ResponseCode.DEPARTMENT_NOT_FOUND));
        // 设置用户部门
        user.setDepartment(department);
        userRepository.save(user);

        log.info("用户 {} 已分配到部门 {}", user.getUsername(), department.getName());
    }

    @Override
    protected void validateUniqueConstraints(UserDTO dto) {
        // 检查用户名唯一性（包括已删除的记录）
        if (userRepository.existsByUsername(dto.getUsername())) {
            throw new UniqueConstraintException(ResponseCode.USERNAME_EXISTS, "username", dto.getUsername());
        }

        // 检查邮箱唯一性（包括已删除的记录）
        if (StringUtils.hasText(dto.getEmail()) && userRepository.existsByEmail(dto.getEmail())) {
            throw new UniqueConstraintException(ResponseCode.EMAIL_EXISTS, "email", dto.getEmail());
        }
    }

    @Override
    @Transactional
    public UserDTO update(Long id, UserDTO dto) {
        User user = findEntityById(id);
        
        // 更新基本信息
        userConverter.updateEntity(user, dto);
        
        // 如果指定了部门ID，更新用户部门
        if (dto.getDepartmentId() != null) {
            Department department = departmentRepository.findById(dto.getDepartmentId())
                .orElseThrow(() -> new BusinessException(ResponseCode.DEPARTMENT_NOT_FOUND));
            user.setDepartment(department);
            log.info("用户 {} 已分配到部门 {}", user.getUsername(), department.getName());
        }
        
        // 保存更新
        userRepository.save(user);
        
        // 转换为DTO并返回
        UserDTO result = userConverter.toDto(user);
        if (user.getDepartment() != null) {
            result.setDepartmentId(user.getDepartment().getId());
        }
        return result;
    }
}