package com.cpop.core.service.impl;

import com.cpop.common.utils.StringUtils;
import com.cpop.core.base.entity.LoginUser;
import com.cpop.core.base.enums.OperationLogEnum;
import com.cpop.core.base.enums.UserType;
import com.cpop.core.base.exception.ServiceException;
import com.cpop.core.base.table.SysConfig;
import com.cpop.core.base.table.SysOperationLog;
import com.cpop.core.base.table.SysUser;
import com.cpop.core.mapper.CoreMapper;
import com.cpop.core.service.CoreService;
import com.cpop.core.utils.MessageUtils;
import com.cpop.core.utils.SecurityUtils;
import com.cpop.core.utils.uuid.IdUtils;
import com.mybatisflex.core.query.QueryWrapper;
import com.mybatisflex.core.row.Db;
import com.mybatisflex.core.row.DbChain;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

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

import static com.cpop.core.base.table.table.SysUserTableDef.SYS_USER;

/**
 * @author DB
 * @Description:
 * @create: 2023-08-27 11:04
 */
@Service("coreService")
public class CoreServiceImpl implements CoreService {

    @Autowired
    private CoreMapper coreMapper;

    /**
     * @Description: 添加操作日志
     * @param status 状态
     * @param operationLogEnum 日志枚举
     * @param loginUser 登陆用户
     * @param failReason 失败原因
     * @return String
     * @Author: DB
     * @Date: 2023/8/27 11:08
     */
    @Override
    public String insertOperationLog(Integer status, OperationLogEnum operationLogEnum, LoginUser loginUser, String failReason) {
        SysOperationLog operationLog = new SysOperationLog();
        operationLog.setId(IdUtils.fastSimpleUUID())
                .setCode(operationLogEnum.getCode())
                .setInfo(MessageUtils.message(operationLogEnum.getInfo()))
                .setDevIp(loginUser.getIpAddr())
                .setOperationUserType(loginUser.getUserType())
                .setOperationUserName(loginUser.getUsername());
        if (200 == status) {
            operationLog.setOperationUserId(loginUser.getUserId())
                    .setLevel(operationLogEnum.getSuccessLevel())
                    .setDescription(MessageUtils.message(operationLogEnum.getInfo()) + MessageUtils.message("i18n_baseInfo_success"))
                    .setResult(true)
                    .setActionType(1);
        } else {
            operationLog.setLevel(operationLogEnum.getExceptionLevel())
                    .setDescription(MessageUtils.message(operationLogEnum.getInfo()) + MessageUtils.message("i18n_baseInfo_failed"))
                    .setFailReason(failReason)
                    .setResult(false)
                    .setActionType(2);
        }
        operationLog.setCreateUserId(loginUser.getUserId());
        operationLog.setUpdateUserId(loginUser.getUserId());
        if (coreMapper.insertOperationLog(operationLog)) {
        }
        return operationLog.getId();
    }

    /**
     * @Description: 添加操作日志
     * @param operationLog 操作日志
     * @return boolean
     * @Author DB
     * @Date: 2023/8/29 23:46
     */
    @Override
    public boolean saveOperationLog(SysOperationLog operationLog) {
        return coreMapper.insertOperationLog(operationLog);
    }

    /**
     * @Description: 根据用户名获取用户信息
     * @param username  用户名
     * @return SysUser
     * @Author DB
     * @Date: 2023/8/27 23:37
     */
    @Override
    public SysUser getSysUserByUsername(String username, UserType userType) {
        return coreMapper.getSysUserByUsername(username, userType.toString());
    }

    /**
     * @Description: 更新登录地址
     * @param ipAddr 地址
     * @param username 用户名
     * @author DB
     * @Date: 2023/8/28 0028 13:48
     */
    @Override
    public void updateSysUserLoginIp(String ipAddr, String username, UserType userType) {
        coreMapper.updateSysUserLoginIp(ipAddr, username, userType.toString());
    }

    /**
     * @Description: 根据键名查询参数配置信息
     * @param configKey 键
     * @return String
     * @author DB
     * @Date: 2023/6/7 0007 15:59
     */
    @Override
    public SysConfig selectConfigByKey(String configKey) {
        return coreMapper.selectConfigByKey(configKey);
    }

    /**
     * 新增参数配置
     *
     * @param config 参数配置信息
     */
    @Override
    public void insertConfig(SysConfig config) {
        LoginUser loginUser = SecurityUtils.getInstance().getLoginUser();
        config.setCreateUserId(null == loginUser ? "1" : loginUser.getUserId());
        config.setUpdateUserId(null == loginUser ? "1" : loginUser.getUserId());
        coreMapper.insertConfig(config);
    }

    /**
     * 修改参数配置
     *
     * @param config 参数配置信息
     */
    @Override
    public void updateConfig(SysConfig config) {
        LoginUser loginUser = SecurityUtils.getInstance().getLoginUser();
        config.setUpdateUserId(null == loginUser ? "1" : loginUser.getUserId());
        coreMapper.updateConfig(config);
    }

    /**
     * 批量删除参数信息
     *
     * @param keys 需要删除的参数ID
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void deleteConfigByKeys(String[] keys) {
        List<String> keyList = Arrays.asList(keys);
        List<SysConfig> sysConfigList = coreMapper.selectConfigByKeys(keyList);
        sysConfigList.forEach(item -> {
            if (item.getConfigType()) {
                throw new ServiceException(String.format("内置参数【%1$s】不能删除 ", item.getConfigKey()));
            }
        });
        coreMapper.deleteConfigByKeys(keyList);
    }

    /**
     * @descriptions 新增系统用户
     * @author DB
     * @date 2023/09/08 15:04
     * @param sysUser 系统用户参数
     */
    @Override
    public void insertSysUser(SysUser sysUser) {
        coreMapper.insertSysUser(sysUser);
    }

    /**
     * @descriptions 修改系统用户
     * @author DB
     * @date 2023/09/08 17:20
     * @param sysUser 系统用户参数
     */
    @Override
    public void updateSysUser(SysUser sysUser) {
        coreMapper.updateSysUser(sysUser);
    }

    /**
     * @descriptions 根据主键删除用户
     * @author DB
     * @date 2023/09/08 17:50
     * @param id 主键
     */
    @Override
    public void removeSysUserById(String id) {
        coreMapper.removeSysUserById(id);
    }

    /**
     * @descriptions 根据用户名与用户类型获取用户信息
     * @author DB
     * @date 2023/10/19 9:57
     * @param username 用户名
     * @param userType 用户类型
     * @return 登陆用户
     */
    @Override
    public LoginUser loadUserByUsername(String username, UserType userType) {
        //统一获取系统用户信息
        SysUser sysUser = this.getSysUserByUsername(username, userType);
        if (sysUser == null) {
            throw new UsernameNotFoundException(MessageUtils.message("i18n_alert_accountOrPwdError"));
        }
        return userType.getStrategy().getLoginUserInfo(sysUser, null);
    }

    /**
     * @descriptions 可能存在用户手机号登陆的情况
     * @author DB
     * @date 2023/11/21 10:05
     * @param phoneNumber 手机号
     * @param userType  用户类型
     * @return: com.cpop.core.base.entity.LoginUser
     */
    @Override
    public LoginUser loadUserByPhone(String phoneNumber, UserType userType) {
        //统一获取系统用户信息
        SysUser sysUser = this.getSysUserByPhone(phoneNumber, userType);
        return userType.getStrategy().getLoginUserInfo(sysUser, null);
    }

    /**
     * @descriptions 根据手机号与用户类型获取用户信息
     * @author DB
     * @date 2023/10/19 9:57
     * @param phoneNumber 手机号
     * @param userType 用户类型
     * @return 登陆用户
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public LoginUser loadUserByPhone(String phoneNumber, UserType userType, Map<String, Object> credentials) {
        //统一获取系统用户信息
        SysUser sysUser = this.getSysUserByPhone(phoneNumber, userType);
        if (sysUser == null) {
            //如果是小程序自动注册用户信息
            if (userType == UserType.MINI_USER) {
                sysUser = new SysUser();
                sysUser.setId(IdUtils.fastSimpleUUID())
                        .setUserName(phoneNumber)
                        .setPhoneNumber(phoneNumber)
                        .setStatus(true)
                        .setUserType(userType.toString())
                        .setCreateUserId("1");
                sysUser.setUpdateUserId("1");
                this.coreMapper.insertSysUser(sysUser);
            } else {
                throw new UsernameNotFoundException("获取用户信息失败");
            }
        }
        //构建登陆用户信息
        return userType.getStrategy().getLoginUserInfo(sysUser, credentials);
    }

    /**
     * @Description: 根据用户名获取用户信息
     * @param phoneNumber 手机号
     * @return SysUser
     * @Author: DB
     * @Date: 2023/8/27 23:37
     */
    @Override
    public SysUser getSysUserByPhone(String phoneNumber, UserType userType) {
        return coreMapper.getSysUserByPhone(phoneNumber, userType.toString());
    }

    /**
     * @descriptions 检查用户是否存在
     * @author DB
     * @date 2023/11/10 11:57
     * @param username 用户名
     * @param id 主键
     * @param userType 用户类型
     * @return: void
     */
    @Override
    public void isAccountExist(String username, String id, String userType) {
        if (StringUtils.isBlank(username)) {
            return;
        }
        if (DbChain.table(SYS_USER).where(SYS_USER.USER_NAME.eq(username))
                .and(SYS_USER.USER_TYPE.eq(userType))
                .and(SYS_USER.ID.ne(id)).count() > 0) {
            throw new ServiceException(MessageUtils.message("i18n_alert_userIsExist"));
        }
    }
}
