package com.kym.service.admin.impl;

import cn.dev33.satoken.stp.StpUtil;
import cn.hutool.crypto.asymmetric.KeyType;
import cn.hutool.crypto.asymmetric.RSA;
import cn.hutool.crypto.digest.DigestAlgorithm;
import cn.hutool.crypto.digest.Digester;
import com.baomidou.dynamic.datasource.annotation.DS;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.github.pagehelper.PageHelper;
import com.kym.common.R;
import com.kym.common.constant.ResponseEnum;
import com.kym.common.utils.IDGenerator;
import com.kym.entity.admin.AdminUser;
import com.kym.entity.admin.AdminUserRole;
import com.kym.entity.admin.queryParams.CommonQueryParam;
import com.kym.entity.admin.vo.AdminUserVo;
import com.kym.entity.common.PageBean;
import com.kym.mapper.admin.AdminUserMapper;
import com.kym.service.admin.AdminUserRoleService;
import com.kym.service.admin.AdminUserService;
import jakarta.annotation.Resource;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import java.nio.charset.StandardCharsets;
import java.time.LocalDateTime;
import java.util.List;
import java.util.Map;


/**
 * <p>
 * 用户表 服务实现类
 * </p>
 *
 * @author skyline
 * @since 2023-07-11
 */
@Service
@DS("db-admin")
public class AdminUserServiceImpl extends ServiceImpl<AdminUserMapper, AdminUser> implements AdminUserService {
    final static Digester MD5 = new Digester(DigestAlgorithm.MD5);
    private static final Logger LOGGER = LoggerFactory.getLogger(AdminUserServiceImpl.class);

    @Value("${password.privateKey}")
    private String privateKey;


    @Value("${password.publicKey}")
    private String publicKey;


    @Resource
    private AdminUserRoleService adminUserRoleService;

    @Override
    public R<?> login(String mobilePhone, String password) {
        var user = lambdaQuery().eq(AdminUser::getMobilePhone, mobilePhone).one();
        RSA rsa = new RSA(privateKey, publicKey);
        password = rsa.decryptStr(password, KeyType.PrivateKey, StandardCharsets.UTF_8);
        var pwd = MD5.digestHex(password.concat(MD5.digestHex(mobilePhone).substring(0, 5)));
        if (pwd.equals(user.getPassword())) {
            StpUtil.login(user.getId());
            // 用户名存入session，统一日志读取使用
            StpUtil.getSession().set("userId", user.getId());
            StpUtil.getSession().set("companyId", user.getCompanyId());
            StpUtil.getSession().set("mobilePhone", user.getMobilePhone());
            user.setLastLoginTime(LocalDateTime.now());
            this.updateById(user);
            LOGGER.info("用户：" + mobilePhone + "/id:" + user.getId() + "登录");
            // token在cookie中有隐式返回，这里多做显式返回
            return R.success(Map.of("id", user.getId(), "satoken", StpUtil.getTokenValue()));
        }
        return R.failed(ResponseEnum.LOGIN_FAILED);
    }

    @Override
    public void logout(Long id) {
        StpUtil.logout(id);
    }

    /**
     * 用户信息、权限、角色
     *
     * @return
     */
    @Override
    public Object profile() {
        long userId = StpUtil.getLoginIdAsLong();
        return listUserPermissions(userId);
    }

    @Override
    public List<AdminUserVo> listUserPermissions(Long loginId) {
        return baseMapper.listUserPermissions(loginId);
    }

    @Override
    public PageBean<AdminUserVo> listAdminUser(CommonQueryParam params) {
        PageHelper.startPage(params.getPageNum(), params.getPageSize());
        var list = baseMapper.listAdminUser(params);
        return new PageBean<>(list);
    }

    @Override
    public void createAdminUser(AdminUserVo adminUserVo) {
        var password = MD5.digestHex(adminUserVo.getPassword().concat(MD5.digestHex(adminUserVo.getMobilePhone()).substring(0, 5)));
        // 用户
        var adminUser = new AdminUser();
        adminUser.setId(IDGenerator.INS().nextId());
        adminUser.setPassword(password);
        BeanUtils.copyProperties(adminUserVo, adminUser);
        save(adminUser);
        // 角色和权限
        var adminUserRole = new AdminUserRole()
                .setAdminUserId(adminUser.getId())
                .setRoleId(adminUserVo.getRoleId());
        adminUserRoleService.save(adminUserRole);
    }
}
