package com.snack.server.module.user.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.snack.server.common.ResultCode;
import com.snack.server.exception.BusinessException;
import com.snack.server.module.user.dto.req.UserPageReq;
import com.snack.server.module.user.dto.req.UserSaveReq;
import com.snack.server.module.user.entity.User;
import com.snack.server.module.user.mapper.UserMapper;
import com.snack.server.module.user.service.UserService;
import com.snack.server.module.user.vo.UserVO;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;

/**
 * 用户管理业务实现
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class UserServiceImpl implements UserService {

    private final UserMapper userMapper;
    private final BCryptPasswordEncoder passwordEncoder = new BCryptPasswordEncoder();

    @Override
    public Page<UserVO> pageUsers(UserPageReq req) {
        Page<User> page = new Page<>(req.getCurrent(), req.getSize());
        LambdaQueryWrapper<User> wrapper = new LambdaQueryWrapper<User>()
                .and(StrUtil.isNotBlank(req.getKeyword()), w -> w
                        .like(User::getUsername, req.getKeyword())
                        .or().like(User::getNickname, req.getKeyword())
                        .or().like(User::getPhone, req.getKeyword())
                )
                .eq(req.getStatus() != null, User::getStatus, req.getStatus())
                .orderByDesc(User::getId);

        Page<User> result = userMapper.selectPage(page, wrapper);
        Page<UserVO> voPage = new Page<>(result.getCurrent(), result.getSize(), result.getTotal());
        voPage.setRecords(result.getRecords().stream().map(this::toVO).toList());
        return voPage;
    }

    @Override
    public UserVO getUserById(Long id) {
        User u = userMapper.selectById(id);
        if (u == null) {
            throw new BusinessException(ResultCode.USER_NOT_EXIST);
        }
        return toVO(u);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Long createUser(UserSaveReq req) {
        // 1. 用户名唯一性
        Long count = userMapper.selectCount(
                new LambdaQueryWrapper<User>().eq(User::getUsername, req.getUsername())
        );
        if (count > 0) {
            throw new BusinessException(1003, "用户名已存在");
        }
        // 2. 密码必填
        if (StrUtil.isBlank(req.getPassword())) {
            throw new BusinessException(1000, "密码不能为空");
        }
        // 3. 入库
        User user = new User();
        BeanUtil.copyProperties(req, user, "id");
        user.setPassword(passwordEncoder.encode(req.getPassword()));
        if (user.getStatus() == null) user.setStatus(1);
        if (user.getGender() == null) user.setGender(0);
        userMapper.insert(user);
        log.info("创建用户 id={} username={}", user.getId(), user.getUsername());
        return user.getId();
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updateUser(UserSaveReq req) {
        if (req.getId() == null) {
            throw new BusinessException(1000, "ID 不能为空");
        }
        User existing = userMapper.selectById(req.getId());
        if (existing == null) {
            throw new BusinessException(ResultCode.USER_NOT_EXIST);
        }
        // 用户名查重（排除自己）
        if (StrUtil.isNotBlank(req.getUsername()) && !req.getUsername().equals(existing.getUsername())) {
            Long count = userMapper.selectCount(
                    new LambdaQueryWrapper<User>()
                            .eq(User::getUsername, req.getUsername())
                            .ne(User::getId, req.getId())
            );
            if (count > 0) {
                throw new BusinessException(1003, "用户名已存在");
            }
        }
        // 不修改密码（密码留空）
        User user = new User();
        BeanUtil.copyProperties(req, user, "password");
        userMapper.updateById(user);
        log.info("更新用户 id={}", req.getId());
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void deleteUser(Long id) {
        User existing = userMapper.selectById(id);
        if (existing == null) {
            throw new BusinessException(ResultCode.USER_NOT_EXIST);
        }
        // 安全：删除前检查是否有未完成订单（这里简化为允许直接删除，业务上应校验）
        userMapper.deleteById(id);
        log.info("删除用户 id={}", id);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void resetPassword(Long id, String newPassword) {
        if (StrUtil.isBlank(newPassword) || newPassword.length() < 6) {
            throw new BusinessException(1000, "新密码至少 6 位");
        }
        User existing = userMapper.selectById(id);
        if (existing == null) {
            throw new BusinessException(ResultCode.USER_NOT_EXIST);
        }
        User update = new User();
        update.setId(id);
        update.setPassword(passwordEncoder.encode(newPassword));
        userMapper.updateById(update);
        log.info("重置用户 id={} 密码", id);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updateStatus(Long id, Integer status) {
        if (id == null || status == null) {
            throw new BusinessException(1000, "参数错误");
        }
        User existing = userMapper.selectById(id);
        if (existing == null) {
            throw new BusinessException(ResultCode.USER_NOT_EXIST);
        }
        User update = new User();
        update.setId(id);
        update.setStatus(status);
        userMapper.updateById(update);
        log.info("用户 id={} 状态更新为 {}", id, status);
    }

    private UserVO toVO(User u) {
        UserVO vo = new UserVO();
        BeanUtil.copyProperties(u, vo, "password");
        return vo;
    }
}
