<?php
// +----------------------------------------------------------------------
// | 麦沃德科技赋能开发者，助力中小企业发展 
// +----------------------------------------------------------------------
// | Copyright (c) 2017～2024  www.wdadmin.cn    All rights reserved.
// +----------------------------------------------------------------------
// | Wdadmin系统产品软件并不是自由软件，不加密，并不代表开源，未经许可不可自由转售和商用
// +----------------------------------------------------------------------
// | Author: MY WORLD Team <bd@maiwd.cn>   www.wdadmin.cn
// +----------------------------------------------------------------------
namespace app\adminapi\service\login;

use Gregwar\Captcha\CaptchaBuilder;
use Gregwar\Captcha\PhraseBuilder;
use app\adminapi\service\setting\WebsiteSettingsService;
use core\base\BaseService;
use think\facade\Cache;

/**
 * 验证码服务类
 * Class CaptchaService
 * @package app\adminapi\service\login
 */
class CaptchaService extends BaseService
{
    /**
     * 验证码缓存键前缀
     */
    const CACHE_KEY_PREFIX = 'admin_login_captcha:';

    /**
     * 验证码有效期（秒）
     */
    const CACHE_EXPIRE_TIME = 300;

    /**
     * 生成验证码
     * @return array 包含 key（唯一标识）和 img（验证码图片 base64 数据）
     */
    public function generate(): array
    {
        // 生成唯一标识
        $key = md5(uniqid(mt_rand(), true) . microtime(true));

        // 创建验证码，4 位数字和字母组合（排除易混淆字符）
        $phraseBuilder = new PhraseBuilder(4, 'abcdefghjkmnpqrstuvwxyz23456789');
        $builder = new CaptchaBuilder(null, $phraseBuilder);

        // 生成验证码图片
        $builder->build(130, 48);

        // 获取验证码内容（转小写存储，方便校验时忽略大小写）
        $phrase = strtolower($builder->getPhrase());

        // 将验证码存入缓存，以 key 为唯一标识
        $cacheKey = self::CACHE_KEY_PREFIX . $key;
        Cache::set($cacheKey, $phrase, self::CACHE_EXPIRE_TIME);

        // 获取 base64 图片数据
        $base64 = $builder->inline();

        return [
            'key' => $key,
            'img' => $base64,
        ];
    }

    /**
     * 校验验证码
     * @param string $code 用户输入的验证码
     * @param string $key  验证码唯一标识
     * @return bool
     */
    public function verify(string $code, string $key): bool
    {
        if (empty($key)) {
            self::setError('验证码标识不能为空');
            return false;
        }

        if (empty($code)) {
            self::setError('请输入验证码');
            return false;
        }

        // 从缓存获取验证码
        $cacheKey = self::CACHE_KEY_PREFIX . $key;
        $cachedCode = Cache::get($cacheKey);

        if (empty($cachedCode)) {
            self::setError('验证码已过期，请刷新');
            return false;
        }

        // 校验验证码（不区分大小写）
        if (strtolower($code) !== $cachedCode) {
            // 验证失败后清除验证码，防止暴力破解
            $this->clearByKey($key);
            self::setError('验证码错误');
            return false;
        }

        // 验证成功后清除验证码（一次性使用）
        $this->clearByKey($key);

        return true;
    }

    /**
     * 根据 key 清除验证码缓存
     * @param string $key 验证码唯一标识
     */
    public function clearByKey(string $key): void
    {
        $cacheKey = self::CACHE_KEY_PREFIX . $key;
        Cache::delete($cacheKey);
    }

    /**
     * 判断是否需要验证码
     * @return bool
     */
    public static function isEnabled(): bool
    {
        $settings = (new WebsiteSettingsService())->detail();
        // enable_captcha：1 = 开启，2 = 关闭
        return isset($settings['enable_captcha']) && $settings['enable_captcha'] == 1;
    }
}
