package com.backendsys.modules.material.service.impl;

import cn.hutool.core.convert.Convert;
import cn.hutool.core.util.RandomUtil;
import cn.hutool.core.bean.BeanUtil;
import com.backendsys.exception.CustException;
import com.backendsys.modules.common.config.redis.utils.RedisUtil;
import com.backendsys.modules.common.config.security.utils.CaptchaUtil;
import com.backendsys.modules.common.config.security.utils.LockStatusUtil;
import com.backendsys.modules.common.config.security.utils.SecurityUtil;
import com.backendsys.modules.material.entity.MaterialAudit;
import com.backendsys.modules.material.entity.MaterialUser;
import com.backendsys.modules.material.service.MaterialUserService;
import com.backendsys.modules.system.dao.SysUserDao;
import com.backendsys.modules.system.dao.SysUserInfoDao;
import com.backendsys.modules.system.dao.SysUserRoleDao;
import com.backendsys.modules.system.dao.SysUserRoleRelationDao;
import com.backendsys.modules.system.entity.*;
import com.backendsys.modules.system.service.SysAuthService;
import com.backendsys.modules.system.service.SysCommonService;
import com.backendsys.modules.system.service.SysUserIntegralService;
import com.backendsys.modules.system.service.SysUserService;
import com.backendsys.utils.response.PageEntity;
import com.backendsys.utils.response.PageInfoResult;
import com.backendsys.utils.v2.PageUtils;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.env.Environment;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.Arrays;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

@Service
public class MaterialUserServiceImpl implements MaterialUserService {

    @Value("${spring.application.name}")
    private String APPLICATION_NAME;
    @Value("${tencent.sms.debug}")
    private String SMS_DEBUG;

    @Autowired
    private Environment env;
    @Autowired
    private LockStatusUtil lockStatusUtil;
    @Autowired
    private CaptchaUtil captchaUtil;
    @Autowired
    private RedisUtil redisUtil;

    @Autowired
    private SysUserDao sysUserDao;
    @Autowired
    private SysUserInfoDao sysUserInfoDao;
    @Autowired
    private SysUserRoleDao sysUserRoleDao;
    @Autowired
    private SysUserRoleRelationDao sysUserRoleRelationDao;

    @Autowired
    private SysAuthService sysAuthService;
    @Autowired
    private SysUserService sysUserService;
    @Autowired
    private SysCommonService sysCommonService;
    @Autowired
    private SysUserIntegralService sysUserIntegralService;

    /**
     * 获取素材用户列表 ({ invite_code = Material })
     */
    @Override
    public PageEntity selectMaterialUserList(String phone, Long role_id) {
        PageUtils.startPage();  // 分页
        SysUserDTO sysUserDTO = new SysUserDTO();
        sysUserDTO.setPhone(phone);
        sysUserDTO.setInvite_code("Material");
        if (role_id != null) {
            sysUserDTO.setRole_id(Arrays.asList(role_id));
        }
        List<SysUserInfo> user_info_list = sysUserInfoDao.selectUserList(sysUserDTO);
        return new PageInfoResult(user_info_list).toEntity();
    }

    /**
     * 获取素材用户角色列表
     */
    @Override
    public List<SysUserRole> selectMaterialUserRoleList() {
        LambdaQueryWrapper<SysUserRole> wrapper = new LambdaQueryWrapper<>();
        wrapper.likeRight(SysUserRole::getRole_sign, "MATERIAL");
        wrapper.orderByAsc(SysUserRole::getSort);
        List<SysUserRole> list = sysUserRoleDao.selectList(wrapper);
        return list;
    }

    /**
     * 审核素材用户
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Map<String, Object> auditMaterialUser(MaterialAudit materialAudit) {

        // 判断是否为素材用户 / 用户是否存在
        LambdaQueryWrapper<SysUserInfo> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(SysUserInfo::getUser_id, materialAudit.getUser_id());
        wrapper.eq(SysUserInfo::getInvite_code, "Material");
        SysUserInfo user_info_detail = sysUserInfoDao.selectOne(wrapper);
        if (user_info_detail == null) throw new CustException("用户不存在");

        // 判断用户是否待审核状态 (-1审核拒绝, 1待审核, 2审核通过)
        if (materialAudit.getUser_id() == SecurityUtil.getUserId()) throw new CustException("不能审核自己");

        // [DB] 获取素材用户角色ID集合
        List<SysUserRole> role_list = selectMaterialUserRoleList();
        List<Long> role_ids = role_list.stream().map(SysUserRole::getRole_id).toList();
        if (!role_ids.contains(materialAudit.getRole_id())) throw new CustException("必须指定素材用户角色");

        // [DB] 更新用户信息-审核状态/用户状态
        SysUserInfo entity = new SysUserInfo();
        entity.setAudit_status(materialAudit.getAudit_status());
        entity.setStatus(materialAudit.getStatus());
        sysUserInfoDao.update(entity, wrapper);

        // 如果是禁用状态，则清除该用户的登录信息
        if (materialAudit.getStatus() == -1) {
            sysUserService.kickUser(materialAudit.getUser_id());
        }

        // [DB] 更新用户与角色关系 (先删，后增)
        LambdaQueryWrapper<SysUserRoleRelation> wrapperRoleRelation = new LambdaQueryWrapper<>();
        wrapperRoleRelation.eq(SysUserRoleRelation::getUser_id, materialAudit.getUser_id());
        sysUserRoleRelationDao.delete(wrapperRoleRelation);
        sysUserRoleRelationDao.insertBatch(materialAudit.getUser_id(), Arrays.asList(materialAudit.getRole_id()));

        return Map.of("user_id", materialAudit.getUser_id());
    }


    // 注册素材用户 (手机号注册)
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Map<String, Object> registerMaterialUser(MaterialUser materialUser) {

        // 判断是否允许注册
        // [系统配置] 是否允许系统用户注册
        Boolean SYSTEM_USER_ALLOW_REGISTER = Convert.toBool(sysCommonService.getCommonByTag("SYSTEM_USER_ALLOW_REGISTER"));
        if (!SYSTEM_USER_ALLOW_REGISTER) throw new CustException("系统已禁止注册");

        String phone = materialUser.getPhone();
        Integer phoneAreaCode = materialUser.getPhone_area_code();
        Integer phoneValidCode = materialUser.getPhone_valid_code();

        String activeProfile = env.getActiveProfiles()[0];

        //if (!"local".equals(activeProfile)) {
        //    // 判断是否处于登录错误的冻结状态 (2分钟内错误5次，则出现冻结提示)
        //    lockStatusUtil.checkLockStatus(APPLICATION_NAME + "-register-error", phone);
        //    // 判断图形验证码是否正确
        //    if (!captchaUtil.isCaptchaValid(captcha, httpRequestUtil.getKaptchaKey())) {
        //        loginFail("验证码错误", username, false);
        //        return null;
        //    }
        //}


        // 判断短信验证码是否正确
        if (!"local".equals(activeProfile)) {
            String redisKey = APPLICATION_NAME + "-sms-" + phone;
            Integer smsCode = redisUtil.getCacheObject(redisKey);
            // 判断是否发送验证码
            if ("false".equals(SMS_DEBUG) && smsCode == null) throw new CustException("请先发送短信验证码");
            // 判断短信验证码是否错误
            if ("false".equals(SMS_DEBUG) && !smsCode.equals(phoneValidCode)) sysAuthService.loginFail("短信验证码错误", phone, true);
        }


        // [查询] 判断手机号是否存在 (如果存在就直接登录，返回Token)
        LambdaQueryWrapper<SysUser> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(SysUser::getPhone, phone).eq(SysUser::getPhone_area_code, phoneAreaCode);
        SysUser sysUserDetail = sysUserDao.selectOne(queryWrapper);
        if (sysUserDetail != null) {
            // [已注册] 返回登录信息 (并且7天免登录)
            SysUserInfo sysUserInfo = sysAuthService.loginSuccess(sysUserDetail.getId(), 1);
            Map<String, Object> response = BeanUtil.beanToMap(sysUserInfo);
            response.put("is_register", false);
            return response;
            //
        } else {
            // [未注册] 通过校验并注册 (注册成功后，返回登录信息)

            // 注册
            SysUserDTO registerEntity = new SysUserDTO();
            registerEntity.setUsername(phone);
            registerEntity.setPhone(phone);
            registerEntity.setPhone_area_code(phoneAreaCode);
            registerEntity.setInvite_code("Material");

            // 注册时，使用 [素材游客] 权限 (MATERIAL_GUEST)
            String role_sign = "MATERIAL_GUEST";
            LambdaQueryWrapper<SysUserRole> wrapperRole = new LambdaQueryWrapper<>();
            wrapperRole.eq(SysUserRole::getRole_sign, role_sign);
            SysUserRole roleDetail = sysUserRoleDao.selectOne(wrapperRole);
            registerEntity.setRole_id(Arrays.asList(roleDetail.getRole_id()));

            // 注册时，审核状态为 待审核 (-1拒绝, 1待审核, 2审核通过)
            registerEntity.setAudit_status(2);
            // 随机昵称 (6位)
            registerEntity.setNickname("用户" + RandomUtil.randomStringUpper(6));

            // 创建用户
            sysUserDao.insertUser(registerEntity);

            // 初始化用户积分
            sysUserIntegralService.init(registerEntity.getId());

            // [DB] 查询用户信息
            SysUserInfo sysUserInfo = sysAuthService.loginSuccess(registerEntity.getId(), 1);
            Map<String, Object> response = BeanUtil.beanToMap(sysUserInfo);
            response.put("is_register", true);
            return response;

        }
    }
}
