<?php
/*
 * @author: CloudZA(云之安) <2922619853@qq.com>
 * @hitokoto: 一场秋雨一场凉，秋心酌满泪为霜。
 * Copyright (c) 2022 by CloudZA, All Rights Reserved.
 */

/**
 * 验证码生成类(需安装Redis)
 * 作者：云之安
 * 时间：2023年3月7日
 * 网站：http://osuu.cc
 */

class RandomCode
{
    private static $redis = null;

    private static $codePrefix = 'AU-'; // 验证码前缀
    private static $codeLength = 6; // 验证码长度
    private static $codeExpiration = 300; // 验证码有效时间，单位为秒

    // 设置 Redis 连接信息
    public static function setRedisConfig($host, $port, $password = '')
    {
        if (self::$redis === null) {
            self::$redis = new Redis();
            self::$redis->connect($host, $port);
            if ($password !== '') {
                self::$redis->auth($password);
            }
        }
    }

    // 设置验证码前缀
    public static function setCodePrefix($prefix)
    {
        self::$codePrefix = $prefix;
    }

    // 设置验证码长度
    public static function setCodeLength($length)
    {
        self::$codeLength = $length;
    }

    // 设置验证码有效时间
    public static function setCodeExpiration($expiration)
    {
        self::$codeExpiration = $expiration;
    }

    // 生成随机验证码和唯一标识符
    public static function generate()
    {
        self::initRedis();
        $code = self::$codePrefix . self::generateDigits(self::$codeLength);
        $uuid = sha1(uniqid($code, true));

        // 将验证码和唯一标识符存储到 Redis，并设置过期时间
        self::$redis->setex($uuid, self::$codeExpiration, $code);

        return array('code' => $code, 'uuid' => $uuid);
    }

    // 生成指定位数的数字
    private static function generateDigits($digits)
    {
        $min = pow(10, $digits - 1);
        $max = pow(10, $digits) - 1;
        return strval(mt_rand($min, $max));
    }

    // 验证验证码是否正确
    public static function validate($uuid, $inputCode)
    {
        self::initRedis();
        if (self::$redis->exists($uuid)) {
            $code = self::$redis->get($uuid);
            return ($code === $inputCode);
        }

        return false;
    }

    // 判断验证码是否失效
    public static function isExpired($uuid)
    {
        self::initRedis();
        if (self::$redis->exists($uuid)) {
            $timestamp = intval(self::$redis->get($uuid));
            return ((time() - $timestamp) > self::$codeExpiration);
        }

        return true;
    }

    // 初始化 Redis 连接
    private static function initRedis()
    {
        if (self::$redis === null) {
            throw new Exception('Redis connection has not been initialized.');
        }
    }

}
