package com.yc.ship.module.ota.service.password;

import com.baomidou.mybatisplus.core.toolkit.IdWorker;
import com.yc.ship.framework.common.pojo.PageResult;
import com.yc.ship.framework.common.util.object.BeanUtils;
import com.yc.ship.module.ota.controller.admin.password.vo.OperatePasswordCheckAndResetReqVO;
import com.yc.ship.module.ota.controller.admin.password.vo.OperatePasswordPageReqVO;
import com.yc.ship.module.ota.controller.admin.password.vo.OperatePasswordSaveReqVO;
import com.yc.ship.module.ota.controller.admin.password.vo.OperatePasswordUpdateReqVO;
import com.yc.ship.module.ota.dal.dataobject.password.OperatePasswordDO;
import com.yc.ship.module.ota.dal.mysql.password.OperatePasswordMapper;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.validation.annotation.Validated;

import javax.annotation.Resource;

import static com.yc.ship.framework.common.exception.util.ServiceExceptionUtil.exception0;
import static com.yc.ship.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId;


/**
 * 操作密码 Service 实现类
 *
 * @author 管理员
 */
@Service
@Validated
public class OperatePasswordServiceImpl implements OperatePasswordService {

    @Resource
    private OperatePasswordMapper operatePasswordMapper;
    @Resource
    private PasswordEncoder passwordEncoder;

    @Override
    public Long createOperatePassword(OperatePasswordSaveReqVO createReqVO) {
        long loginUserId = getLoginUserId();
        // 插入
        OperatePasswordDO operatePassword = BeanUtils.toBean(createReqVO, OperatePasswordDO.class);
        Long id = IdWorker.getId(operatePassword);
        operatePassword.setId(id);
        operatePassword.setUserId(loginUserId);
        operatePassword.setDeleted(false);

        try {
            String password = RSAUtils.decryptByPrivateKey(operatePassword.getPassword(), RSAUtils.PRIVATE_KEY_LZ);
            operatePassword.setPassword(encodePassword(password));
        } catch (Exception e) {
            throw exception0(11_028, "密码不正确");
        }

        operatePasswordMapper.insert(operatePassword);
        // 返回
        return operatePassword.getId();
    }

    @Override
    public void updateOperatePassword(OperatePasswordSaveReqVO updateReqVO) {
        // 校验存在
        validateOperatePasswordExists(updateReqVO.getId());
        // 更新
        OperatePasswordDO updateObj = BeanUtils.toBean(updateReqVO, OperatePasswordDO.class);
        operatePasswordMapper.updateById(updateObj);
    }

    @Override
    public void deleteOperatePassword(Long id) {
        // 校验存在
        validateOperatePasswordExists(id);
        // 删除
        operatePasswordMapper.deleteById(id);
    }

    private void validateOperatePasswordExists(Long id) {
        if (operatePasswordMapper.selectById(id) == null) {
            throw exception0(11_028, "不存在");
        }
    }

    @Override
    public OperatePasswordDO getOperatePassword(Long id) {
        return operatePasswordMapper.selectById(id);
    }

    @Override
    public PageResult<OperatePasswordDO> getOperatePasswordPage(OperatePasswordPageReqVO pageReqVO) {
        return operatePasswordMapper.selectPage(pageReqVO);
    }

    @Override
    public void resetPassword(Integer type, String password) {
        // 校验用户存在
        long loginUserId = getLoginUserId();
        OperatePasswordDO passwordDO = validateUserAndTypeExists(loginUserId, type);
        if (passwordDO == null) {
            throw exception0(11_028, "不存在");
        }
        try {
            String passwordStr = RSAUtils.decryptByPrivateKey(password, RSAUtils.PRIVATE_KEY_LZ);
            // 执行更新
            passwordDO.setPassword(encodePassword(passwordStr)); // 加密密码
            operatePasswordMapper.updateById(passwordDO);
        } catch (Exception e) {
            throw exception0(11_028, "操作失败");
        }

    }

    @Override
    public boolean validateExists(Integer type) {
        Long userId = getLoginUserId();
        OperatePasswordDO passwordDO = validateUserAndTypeExists(userId, type);
        if (passwordDO == null) {
            return false;
        } else {
            return true;
        }
    }

    @Override
    public void updatePassword(OperatePasswordUpdateReqVO reqVO) {
        Long userId = getLoginUserId();
        String oldPwd = "";
        String newPwd = "";
        try {
            oldPwd = RSAUtils.decryptByPrivateKey(reqVO.getOldPassword(), RSAUtils.PRIVATE_KEY_LZ);
            newPwd = RSAUtils.decryptByPrivateKey(reqVO.getNewPassword(), RSAUtils.PRIVATE_KEY_LZ);
        } catch (Exception e) {
            throw exception0(500,"密码解密失败");
        }
        OperatePasswordDO passwordDO = validatePassword(userId, reqVO.getType(), oldPwd);
        // 执行更新
        passwordDO.setPassword(encodePassword(newPwd)); // 加密密码
        operatePasswordMapper.updateById(passwordDO);
    }

    @Override
    public boolean checkPwd( OperatePasswordCheckAndResetReqVO reqVO) {
        Long userId = getLoginUserId();
        boolean flag = true;
        try {
            String password = RSAUtils.decryptByPrivateKey(reqVO.getPassword(), RSAUtils.PRIVATE_KEY_LZ);
            this.validatePassword(userId, reqVO.getType(), password);
        } catch (Exception e) {
            flag = false;
        }

        return flag;
    }

    @Override
    public boolean isPasswordMatch(String rawPassword, String encodedPassword) {
        return passwordEncoder.matches(rawPassword, encodedPassword);
    }

    private OperatePasswordDO validatePassword(Long userId, Integer type, String oldPassword) {
        OperatePasswordDO passwordDO = validateUserAndTypeExists(userId, type);
        if (passwordDO == null) {
            throw exception0(11_028, "不存在");
        }
        if (!isPasswordMatch(oldPassword, passwordDO.getPassword())) {
            throw exception0(11_028, "操作失败");
        }
        return passwordDO;
    }

    private OperatePasswordDO validateUserAndTypeExists(Long userId, Integer type) {
        OperatePasswordDO passwordDO = operatePasswordMapper.selectOne(OperatePasswordDO::getUserId, userId, OperatePasswordDO::getType, type);
        return passwordDO;
    }

    /**
     * 对密码进行加密
     *
     * @param password 密码
     * @return 加密后的密码
     */
    private String encodePassword(String password) {
        return passwordEncoder.encode(password);
    }

}