<?php
/**
 *  ╔═══════════════════════════════════════════════════╗
 *  ║                                                   ║
 *  ║     ██╗  ██╗   █████╗    ██████╗                  ║
 *  ║     ██║  ██║  ██╔══██╗  ██╔═══██╗                 ║
 *  ║     ███████║  ███████║  ██║   ██║                 ║
 *  ║     ██╔══██║  ██╔══██║  ██║   ██║                 ║
 *  ║     ██║  ██║  ██║  ██║  ╚██████╔╝   SNS           ║
 *  ║                                                   ║    
 *  ║                                                   ║    
 *  ║     © 2023 HaoSNS™ All Rights Reserved            ║
 *  ║     官方网站: https://www.haosns.com                *
 *  ║     本代码由赣州乐易网络科技有限公司®提供             *
 *  ║                                                    *
 *  ║   未经授权禁止复制、传播或用于其他商业目的            *
 *  ║                                                   ║
 *  ╚═══════════════════════════════════════════════════╝
 */


namespace app\api\validate;

use app\common\model\User;
use app\common\validate\BaseValidate;

/**
 * 用户验证器
 * Class UserValidate
 * @package  app\api\validate
 */
class UserValidate extends BaseValidate
{
    protected $rule = [
        'pay_password' => 'require|checkPayPassword',
        'transfer_in' => 'require|checkTransferIn',
        'money' => 'require|gt:0|checkMoney',
        'code' => 'require',
        'encrypted_data' => 'require',
        'iv' => 'require',
        'mobile' => 'require|mobile',
        'password' => 'require|length:6,20|alphaDash',
        'old_password' => 'require',
        'real_name'    => 'require',
        'id_card'      => 'require|checkIdCard',
    ];

    protected $message = [
        'pay_password.require' => '请输入支付密码',
        'pay_password.length' => '支付密码须在4-8位之间',
        'pay_password.alphaDash' => '支付密码须为字母数字下划线或破折号',
        'transfer_in.require' => '请选择收款用户',
        'money.require' => '请输入转账金额',
        'money.gt' => '转账金额须大于0',
        'code.require' => '参数缺失',
        'encrypted_data.require' => '参数缺失',
        'iv.require' => '参数缺失',
        'mobile.require' => '请输入手机号码',
        'mobile.mobile' => '无效的手机号码',
        'old_password.require' => '请输入原密码',
        'password.require' => '请输入登录密码',
        'password.length' => '登录密码须在6-20位之间',
        'password.alphaDash' => '登录密码须为字母数字下划线或破折号',

        'real_name.require' => '请输入真实姓名',
        'id_card.require' => '请输入身份证号',
    ];

    /**
     * @notes 余额转账场景
     * @return UserValidate
     */
    public function sceneTransfer()
    {
        return $this->only(['pay_password', 'transfer_in', 'money']);
    }

    /**
     * @notes 收款用户信息场景
     * @return UserValidate
     */
    public function sceneTransferIn()
    {
        return $this->only(['transfer_in'])
            ->remove('transfer_in', 'checkTransferIn');
    }

    /**
     * @notes 设置/修改交易密码场景
     * @return UserValidate
     */
    public function sceneSetPayPassword()
    {
        return $this->only(['pay_password'])
            ->remove('pay_password', 'checkPayPassword')
            ->append('pay_password', 'length:4,8|alphaDash');
    }

    /**
     * @notes 获取微信手机号场景
     * @return UserValidate
     */
    public function sceneGetMobileByMnp()
    {
        return $this->only(['code']);
    }

    /**
     * @notes 发送验证码 -  重置支付密码
     * @return UserValidate
     */
    public function sceneResetPayPasswordCaptcha()
    {
        return $this->only(['mobile']);
    }

    /**
     * @notes 发送验证码 -  重置登录密码
     * @return UserValidate
     */
    public function sceneResetPasswordCaptcha()
    {
        return $this->only(['mobile']);
    }

    /**
     * @notes 发送验证码 -  绑定手机号
     * @return UserValidate
     */
    public function sceneBindMobileCaptcha()
    {
        return $this->only(['mobile']);
    }

    /**
     * @notes 发送验证码 -  变更手机号
     * @return UserValidate
     */
    public function sceneChangeMobileCaptcha()
    {
        return $this->only(['mobile']);
    }

    /**
     * @notes 绑定手机号场景
     * @return UserValidate
     */
    public function sceneBindMobile()
    {
        return $this->only(['mobile', 'code']);
    }

    /**
     * @notes 重置支付密码
     * @return UserValidate
     */
    public function sceneResetPayPassword()
    {
        return $this->only(['mobile', 'code', 'pay_password'])
            ->remove('pay_password', 'checkPayPassword')
            ->append('pay_password', 'length:4,8|alphaDash');
    }

    /**
     * @notes 重置登录密码
     * @return UserValidate
     */
    public function sceneResetPassword()
    {
        return $this->only(['mobile', 'code', 'password'])
            ->append('password', 'require|length:6,12|alphaDash|checkComplexity');
    }

    /**
     * @notes 修改密码
     * @return UserValidate
     * @author lgp
     * @date 2023/3/7 16:27
     */
    public function sceneChangePassword()
    {
        return $this->only(['old_password','password'])
            ->append('password','require|length:6,20|alphaDash|checkComplexity');
    }

    /**
     * @notes 设置登录密码
     * @return UserValidate
     */
    public function sceneSetPassword()
    {
        return $this->only(['password'])
            ->append('password','require|length:6,20|alphaDash|checkComplexity');
    }

    public function sceneUserCertification()
    {
        return $this->only(['real_name','id_card'])->append('id_card','require|checkIdCard');
    }

    /**
     * @notes 校验支付密码
     * @param $value
     * @param $rule
     * @param $data
     * @return bool|string
     */
    public function checkPayPassword($value, $rule, $data)
    {
        $user = User::findOrEmpty($data['user_id']);
        if(empty($user->mobile)) {
            return '请先绑定手机号';
        }
        if(empty($user->pay_password)) {
            return '请先设置支付密码';
        }
        if($user->pay_password == md5($value)) {
            return true;
        }
        return '支付密码错误';
    }

    /**
     * @notes 校验收款用户
     * @param $value
     * @param $rule
     * @param $data
     * @return bool|string
     */
    public function checktransferIn($value, $rule, $data)
    {
        $me = User::findOrEmpty($data['user_id']);
        if($me->sn == $data['transfer_in'] || $me->mobile == $data['transfer_in']) {
            return '不能自己转账给自己';
        }
        $transferIn = User::whereOr('sn', $data['transfer_in'])
            ->whereOr('mobile', $data['transfer_in'])
            ->findOrEmpty();
        if($transferIn->isEmpty()) {
            return '收款用户不存在';
        }
        return true;
    }

    /**
     * @notes 校验余额
     * @param $value
     * @param $rule
     * @param $data
     * @return bool|string
     */
    public function checkMoney($value, $rule, $data)
    {
        $user = User::findOrEmpty($data['user_id']);
        if($user->user_money < $data['money']) {
            return '余额不足';
        }
        return true;
    }

    /**
     * @notes 校验密码复杂度
     * @param $value
     * @param $rue
     * @param $data
     */
    public function checkComplexity($value, $rue, $data)
    {
        $lowerCase = range('a', 'z');
        $upperCase = range('A', 'Z');
        $numbers = range(0, 9);
        $cases = array_merge($lowerCase, $upperCase);
        $caseCount = 0;
        $numberCount = 0;
        $passwordArr = str_split(trim(($data['password'] . '')));
        foreach ($passwordArr as $value) {
            if (in_array($value, $numbers)) {
                $numberCount++;
            }
            if (in_array($value, $cases)) {
                $caseCount++;
            }
        }
        if ($numberCount >= 1 && $caseCount >= 1) {
            return true;
        }
        return '密码需包含数字和字母';
    }

    /**
     * @notes 校验身份证姓名与身份证号
     * @param $value
     * @param $rue
     * @param $data
     */
    public function checkIdCard($value, $rule, $data){
         // 正则表达式匹配身份证号码格式
        $regex = '/^[1-9]\d{5}(19|20)\d{2}((0[1-9])|(1[0-2]))(([0-2][1-9])|10|20|30|31)\d{3}[0-9Xx]$/';

        // 判断是否符合正则表达式规则
        if (!preg_match($regex, $data['id_card'])) {
            return '身份证号不正确';
        }

        // 校验身份证号码的最后一位
        $id_card_array = str_split( $data['id_card']);
        $weight_factor = array(7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2); // 加权因子
        $verify_code = array('1', '0', 'X', '9', '8', '7', '6', '5', '4', '3', '2'); // 校验码对应值

        $checksum = 0;
        for ($i = 0; $i < 17; ++$i) {
            $checksum += intval($id_card_array[$i]) * $weight_factor[$i];
        }

        $mod = $checksum % 11;
        $verify_number = $verify_code[$mod];

        if (strcasecmp($verify_number, $id_card_array[17]) != 0) {
            return '身份证号不正确,请输入正确的身份证号码';
        }

        return true;
    }
}