package shop.alien.store.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;
import shop.alien.entity.result.R;
import shop.alien.entity.store.LifeSys;
import shop.alien.entity.store.UserLoginInfo;
import shop.alien.entity.store.dto.SystemUserAddDto;
import shop.alien.entity.store.dto.SystemUserStatusDto;
import shop.alien.entity.store.dto.SystemUserUpdateDto;
import shop.alien.entity.store.vo.LifeSysVo;
import shop.alien.entity.store.vo.SystemLoginVo;
import shop.alien.mapper.LifeSysMapper;
import shop.alien.store.config.BaseRedisService;
import shop.alien.store.service.LifeSysUserRoleService;
import shop.alien.store.service.SystemService;
import shop.alien.util.common.JwtUtil;

import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.*;
import java.util.stream.Collectors;

/**
 * <p>
 * 商家会员记录 服务实现类
 * </p>
 *
 * @author ssk
 * @since 2025-02-20
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class SystemServiceImpl extends ServiceImpl<LifeSysMapper, LifeSys> implements SystemService {

    private final LifeSysMapper lifeSysMapper;

    private final BaseRedisService baseRedisService;

    private final LifeSysUserRoleService lifeSysUserRoleService;

    @Value("${jwt.expiration-time}")
    private String effectiveTime;

    private final String defaultPassword = "123456";

    @Override
    public SystemLoginVo login(String username, String password) {
        int effectiveTimeInt = Integer.parseInt(effectiveTime.substring(0, effectiveTime.length() - 1));
        String effectiveTimeUnit = effectiveTime.substring(effectiveTime.length() - 1);
        long effectiveTimeIntLong = 0L;
        switch (effectiveTimeUnit) {
            case "s": {
                effectiveTimeIntLong = effectiveTimeInt * 1000L;
                break;
            }
            case "m": {
                effectiveTimeIntLong = effectiveTimeInt * 60L * 1000L;
                break;
            }
            case "h": {
                effectiveTimeIntLong = effectiveTimeInt * 60L * 60L * 1000L;
                break;
            }
            case "d": {
                effectiveTimeIntLong = effectiveTimeInt * 24L * 60L * 60L * 1000L;
                break;
            }
        }
        SystemLoginVo result = new SystemLoginVo();
        //给密码加密MD5，查询用户是否存在
        QueryWrapper<LifeSys> loginQueryWrapper = new QueryWrapper<>();
        loginQueryWrapper.eq("user_name", username);
        LifeSys lifeSys = lifeSysMapper.selectOne(loginQueryWrapper);
        if (lifeSys != null && lifeSys.getUserPassword().equals(encryptToMD5(password))) {
            Map<String, String> tokenMap = new HashMap<>();
            tokenMap.put("phone", lifeSys.getPhone());
            tokenMap.put("userName", lifeSys.getUserName());
            tokenMap.put("userId", String.valueOf(lifeSys.getId()));
            tokenMap.put("userType", "web");
            //存入token
            result.setToken(JwtUtil.createJWT("web_" + lifeSys.getId(), lifeSys.getUserName(), JSONObject.toJSONString(tokenMap), effectiveTimeIntLong));
            baseRedisService.setString("web_" + lifeSys.getUserName(), result.getToken());
            //登录结果
            result.setResult(true);
            //登录结果
            result.setMessage("登录成功！！");
        } else {
            result.setResult(false);
            result.setMessage("用户名或者密码错误，请确认！！");
        }
        return result;
    }

    @Override
    public SystemLoginVo logout(UserLoginInfo userLoginInfo) {
        //JWT移除token
        return null;
    }

    @Override
    public R<LifeSys> register(String userName, String password, String roleId) {
        // 校验必填字段
        if (!StringUtils.hasText(userName)) {
            return R.fail("用户名不能为空");
        }
        if (!StringUtils.hasText(password)) {
            return R.fail("密码不能为空");
        }

        // 校验用户名是否已存在
        QueryWrapper<LifeSys> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("user_name", userName);
        LifeSys existingUser = lifeSysMapper.selectOne(queryWrapper);
        if (existingUser != null) {
            return R.fail("该用户名已存在，请更换其他用户名");
        }

        // 创建新用户
        LifeSys lifeSys = new LifeSys();
        lifeSys.setUserName(userName);
        // 密码使用MD5加密后存储
        lifeSys.setUserPassword(encryptToMD5(password));
//        if (StringUtils.hasText(roleId)) {
//            lifeSys.setRoleId(roleId);
//        }
        lifeSys.setDeleteFlag(0); // 未删除

        // 保存用户
        int result = lifeSysMapper.insert(lifeSys);
        if (result > 0) {
            return R.data(lifeSys, "注册成功");
        }
        return R.fail("注册失败，请稍后重试");
    }

    @Override
    public R<LifeSys> addUser(SystemUserAddDto addDto) {
        // 校验用户名是否已存在
        QueryWrapper<LifeSys> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("user_name", addDto.getUserName());
        LifeSys existingUser = lifeSysMapper.selectOne(queryWrapper);
        if (existingUser != null) {
            return R.fail("该用户名已存在，请更换其他用户名");
        }

        // 校验邮箱是否已存在
/*        LambdaQueryWrapper<LifeSys> emailQueryWrapper = new LambdaQueryWrapper<>();
        emailQueryWrapper.eq(LifeSys::getEmail, addDto.getEmail());
        LifeSys existingEmail = lifeSysMapper.selectOne(emailQueryWrapper);
        if (existingEmail != null) {
            return R.fail("该邮箱已被使用，请更换其他邮箱");
        }*/

/*        // 校验手机号是否已存在
        LambdaQueryWrapper<LifeSys> phoneQueryWrapper = new LambdaQueryWrapper<>();
        phoneQueryWrapper.eq(LifeSys::getPhone, addDto.getPhone());
        LifeSys existingPhone = lifeSysMapper.selectOne(phoneQueryWrapper);
        if (existingPhone != null) {
            return R.fail("该手机号已被使用，请更换其他手机号");
        }*/

        // 创建新用户
        LifeSys lifeSys = new LifeSys();
        lifeSys.setUserName(addDto.getUserName());
        lifeSys.setRealName(addDto.getRealName());
        lifeSys.setPhone(addDto.getPhone());
        lifeSys.setEmail(addDto.getEmail());
        // 密码使用MD5加密后存储
//        lifeSys.setUserPassword(encryptToMD5(addDto.getPassword()));
        lifeSys.setUserPassword(defaultPassword);

        // 不再将角色ID保存到life_sys表的role_id字段，而是保存到中间关系表
        // lifeSys.setRoleId(addDto.getRoleIds());
        
        lifeSys.setDepartmentId(addDto.getDepartmentId());
        lifeSys.setRemark(addDto.getRemark());
        lifeSys.setStatus(addDto.getStatus() != null ? addDto.getStatus() : 1);
        lifeSys.setDeleteFlag(0); // 未删除

        // 保存用户
        int result = lifeSysMapper.insert(lifeSys);
        if (result > 0) {
            // 保存用户与角色的关系到中间表
            if (StringUtils.hasText(addDto.getRoleIds())) {
                try {
                    // 解析角色ID字符串（支持逗号分隔）
                    List<Long> roleIdList = Arrays.stream(addDto.getRoleIds().split(","))
                            .map(String::trim)
                            .filter(id -> !id.isEmpty())
                            .map(Long::parseLong)
                            .collect(Collectors.toList());
                    
                    // 批量保存到中间关系表
                    if (!roleIdList.isEmpty()) {
                        lifeSysUserRoleService.assignRoles(lifeSys.getId(), roleIdList);
                    }
                } catch (NumberFormatException e) {
                    log.error("角色ID格式错误: {}", addDto.getRoleIds(), e);
                    // 角色ID解析失败不影响用户创建，只记录日志
                }
            }
            
            // 清除密码信息，避免返回到前端
            lifeSys.setUserPassword(null);
            return R.data(lifeSys, "新增账号成功");
        }
        return R.fail("新增账号失败，请稍后重试");
    }

    @Override
    public R<LifeSys> updateUser(SystemUserUpdateDto updateDto) {
        // 校验用户ID
        if (updateDto.getUserId() == null) {
            return R.fail("用户ID不能为空");
        }

        // 查询用户是否存在
        LifeSys lifeSys = lifeSysMapper.selectById(updateDto.getUserId());
        if (lifeSys == null) {
            return R.fail("用户不存在");
        }

        // 如果提供了用户名，校验用户名是否与其他用户重复
        if (StringUtils.hasText(updateDto.getUserName()) && !updateDto.getUserName().equals(lifeSys.getUserName())) {
            QueryWrapper<LifeSys> queryWrapper = new QueryWrapper<>();
            queryWrapper.eq("user_name", updateDto.getUserName());
            LifeSys existingUser = lifeSysMapper.selectOne(queryWrapper);
            if (existingUser != null) {
                return R.fail("该用户名已存在，请更换其他用户名");
            }
            lifeSys.setUserName(updateDto.getUserName());
        }

        // 如果提供了邮箱，校验邮箱是否与其他用户重复
/*        if (StringUtils.hasText(updateDto.getEmail()) && !updateDto.getEmail().equals(lifeSys.getEmail())) {
            LambdaQueryWrapper<LifeSys> emailQueryWrapper = new LambdaQueryWrapper<>();
            emailQueryWrapper.eq(LifeSys::getEmail, updateDto.getEmail());
            LifeSys existingEmail = lifeSysMapper.selectOne(emailQueryWrapper);
            if (existingEmail != null) {
                return R.fail("该邮箱已被使用，请更换其他邮箱");
            }
            lifeSys.setEmail(updateDto.getEmail());
        }*/

        // 更新其他字段（如果提供了）
        if (StringUtils.hasText(updateDto.getRealName())) {
            lifeSys.setRealName(updateDto.getRealName());
        }
        if (StringUtils.hasText(updateDto.getPhone())) {
            lifeSys.setPhone(updateDto.getPhone());
        }
        if (StringUtils.hasText(updateDto.getPassword())) {
            // 如果提供了密码，则更新密码
            // lifeSys.setUserPassword(encryptToMD5(updateDto.getPassword()));
            lifeSys.setUserPassword(updateDto.getPassword());
        }
        if (StringUtils.hasText(updateDto.getDepartmentId())) {
            lifeSys.setDepartmentId(updateDto.getDepartmentId());
        }
        if (StringUtils.hasText(updateDto.getRemark())) {
            lifeSys.setRemark(updateDto.getRemark());
        }
        if (updateDto.getStatus() != null) {
            if (updateDto.getStatus() != 0 && updateDto.getStatus() != 1) {
                return R.fail("状态值只能是0（禁用）或1（启用）");
            }
            lifeSys.setStatus(updateDto.getStatus());
        }

        // 保存用户信息
        int result = lifeSysMapper.updateById(lifeSys);
        if (result > 0) {
            // 如果提供了角色ID列表，更新用户与角色的关系到中间表
            if (StringUtils.hasText(updateDto.getRoleIds())) {
                try {
                    // 解析新的角色ID字符串（支持逗号分隔）
                    Set<Long> newRoleIdSet = Arrays.stream(updateDto.getRoleIds().split(","))
                            .map(String::trim)
                            .filter(id -> !id.isEmpty())
                            .map(Long::parseLong)
                            .collect(Collectors.toSet());
                    
                    // 获取用户当前的角色ID列表
                    List<Long> currentRoleIdList = lifeSysUserRoleService.getRoleIdsByUserId(lifeSys.getId());
                    Set<Long> currentRoleIdSet = currentRoleIdList.stream().collect(Collectors.toSet());
                    
                    // 如果新角色列表为空，则删除所有角色关系
                    if (newRoleIdSet.isEmpty()) {
                        if (!currentRoleIdSet.isEmpty()) {
                            lifeSysUserRoleService.removeAllRoles(lifeSys.getId());
                        }
                    } else {
                        // 比较新旧角色列表，进行增量更新
                        // 找出需要新增的角色（新列表中有，旧列表中没有）
                        Set<Long> rolesToAdd = newRoleIdSet.stream()
                                .filter(roleId -> !currentRoleIdSet.contains(roleId))
                                .collect(Collectors.toSet());
                        
                        // 找出需要删除的角色（旧列表中有，新列表中没有）
                        Set<Long> rolesToRemove = currentRoleIdSet.stream()
                                .filter(roleId -> !newRoleIdSet.contains(roleId))
                                .collect(Collectors.toSet());
                        
                        // 执行新增操作
                        for (Long roleId : rolesToAdd) {
                            lifeSysUserRoleService.addRole(lifeSys.getId(), roleId);
                        }
                        
                        // 执行删除操作
                        for (Long roleId : rolesToRemove) {
                            lifeSysUserRoleService.removeRole(lifeSys.getId(), roleId);
                        }
                        
                        // 如果没有任何变化，记录日志
                        if (rolesToAdd.isEmpty() && rolesToRemove.isEmpty()) {
                            log.info("用户ID={}的角色关系未发生变化，无需更新", lifeSys.getId());
                        } else {
                            log.info("用户ID={}的角色关系已更新：新增{}个角色，删除{}个角色", 
                                    lifeSys.getId(), rolesToAdd.size(), rolesToRemove.size());
                        }
                    }
                } catch (NumberFormatException e) {
                    log.error("角色ID格式错误: {}", updateDto.getRoleIds(), e);
                    return R.fail("角色ID格式错误，请检查后重试");
                }
            }
            
            // 清除密码信息，避免返回到前端
            lifeSys.setUserPassword(null);
            return R.data(lifeSys, "修改账号成功");
        }
        return R.fail("修改账号失败，请稍后重试");
    }

    @Override
    public R<LifeSys> updateUserStatus(SystemUserStatusDto statusDto) {
        // 校验用户ID
        if (statusDto.getUserId() == null) {
            return R.fail("用户ID不能为空");
        }

        // 校验状态值
        if (statusDto.getStatus() == null) {
            return R.fail("状态值不能为空");
        }

        if (statusDto.getStatus() != 0 && statusDto.getStatus() != 1) {
            return R.fail("状态值只能是0（禁用）或1（启用）");
        }

        // 查询用户是否存在
        LifeSys lifeSys = lifeSysMapper.selectById(statusDto.getUserId());
        if (lifeSys == null) {
            return R.fail("用户不存在");
        }

        // 更新用户状态
        lifeSys.setStatus(statusDto.getStatus());
        
        // 如果提供了备注，也更新备注
        if (StringUtils.hasText(statusDto.getRemark())) {
            String currentRemark = lifeSys.getRemark();
            String newRemark = statusDto.getRemark();
            // 如果已有备注，追加新备注
            if (StringUtils.hasText(currentRemark)) {
                lifeSys.setRemark(currentRemark + " | " + newRemark);
            } else {
                lifeSys.setRemark(newRemark);
            }
        }

        // 执行更新
        int result = lifeSysMapper.updateById(lifeSys);
        if (result > 0) {
            // 清除密码信息，避免返回到前端
            lifeSys.setUserPassword(null);
            String statusText = statusDto.getStatus() == 1 ? "启用" : "禁用";
            return R.data(lifeSys, "账号" + statusText + "成功");
        }
        return R.fail("修改状态失败，请稍后重试");
    }

    @Override
    public R<LifeSys> resetPassword(Integer userId) {
        // 校验用户ID
        if (userId == null) {
            return R.fail("用户ID不能为空");
        }

        // 查询用户是否存在
        LifeSys lifeSys = lifeSysMapper.selectById(userId);
        if (lifeSys == null) {
            return R.fail("用户不存在");
        }

        // 重置密码为默认值（例如 "123456"）
        lifeSys.setUserPassword(defaultPassword);

        // 执行更新
        int result = lifeSysMapper.updateById(lifeSys);
        if (result > 0) {
            // 清除密码信息，避免返回到前端
            lifeSys.setUserPassword(null);
            return R.data(lifeSys, "密码重置成功，新密码为：" + defaultPassword);
        }
        return R.fail("密码重置失败，请稍后重试");
    }

    @Override
    public IPage<LifeSysVo> getUserPage(int page, int size, String userName, String realName, String phone, String departmentId, Long roleId) {
        // 创建分页对象
        IPage<LifeSysVo> pageObj = new Page<>(page, size);
        
        // 构建查询条件
        QueryWrapper<LifeSys> queryWrapper = new QueryWrapper<>();
        
        // 用户名模糊查询
        if (StringUtils.hasText(userName)) {
            queryWrapper.like("ls.user_name", userName);
        }
        
        // 真实姓名模糊查询
        if (StringUtils.hasText(realName)) {
            queryWrapper.like("ls.real_name", realName);
        }
        
        // 联系电话模糊查询
        if (StringUtils.hasText(phone)) {
            queryWrapper.like("ls.phone", phone);
        }
        
        // 部门ID精确查询
        if (StringUtils.hasText(departmentId)) {
            queryWrapper.eq("ls.department_id", departmentId);
        }

//        queryWrapper.eq("ls.status", 1);

        // 如果指定了角色ID，需要先查询角色关联表获取用户ID列表
        if (roleId != null) {
            queryWrapper.eq("lsur.role_id", roleId);
        }
        
        // 未删除的用户
        queryWrapper.eq("ls.delete_flag", 0);
        queryWrapper.groupBy("ls.id");
        // 按创建时间倒序
        queryWrapper.orderByDesc("ls.created_time");
        
        // 执行分页查询
        return lifeSysMapper.selectPageAndRoleName(pageObj, queryWrapper);
    }

    @Override
    public R clearUserDepartment(String userId) {
        // 校验用户ID
        if (userId == null || userId.isEmpty()) {
            return R.fail("用户ID不能为空");
        }

        // 清除用户的部门
        UpdateWrapper<LifeSys> updateWrapper = new UpdateWrapper<>();
        updateWrapper.set("department_id", null)
                     .in("id", userId.split(","));
        // 执行更新
        int result = lifeSysMapper.update(null, updateWrapper);
        if (result > 0) {
            return R.success( "用户部门清除成功");
        }
        return R.fail("用户部门清除失败，请稍后重试");
    }

    public static String encryptToMD5(String input) {
        try {
            // 获取 MD5 算法的 MessageDigest 实例
            MessageDigest md = MessageDigest.getInstance("MD5");
            // 将输入的字符串转换为字节数组，并进行 MD5 计算
            byte[] messageDigest = md.digest(input.getBytes());

            // 创建一个 StringBuilder 用于存储十六进制字符串
            StringBuilder hexString = new StringBuilder();
            for (byte b : messageDigest) {
                // 将字节转换为十六进制字符串
                String hex = Integer.toHexString(0xFF & b);
                if (hex.length() == 1) {
                    // 如果十六进制字符串长度为 1，则在前面补 0
                    hexString.append('0');
                }
                hexString.append(hex);
            }
            // 返回最终的 MD5 加密后的十六进制字符串
            return hexString.toString();
        } catch (NoSuchAlgorithmException e) {
            // 若指定的算法（MD5）不可用，抛出运行时异常
            throw new RuntimeException(e);
        }
    }

}
