<?php
namespace PpPhp\Plugins;

use PpPhp\Core\ValidationPlugin;

class PasswordStrengthRule implements ValidationPlugin
{
    public static function id(): string { return 'password'; }
    public static function label(): string { return 'Password strength'; }
    public static function group(): string { return 'Security'; }

    public static function paramsSchema(): array
    {
        return [
            ['key' => 'minLength', 'type' => 'number', 'label' => 'Min length', 'default' => 8],
            ['key' => 'upper', 'type' => 'bool', 'label' => 'Uppercase letter', 'default' => true],
            ['key' => 'lower', 'type' => 'bool', 'label' => 'Lowercase letter', 'default' => true],
            ['key' => 'digit', 'type' => 'bool', 'label' => 'Number', 'default' => true],
            ['key' => 'symbol', 'type' => 'bool', 'label' => 'Symbol', 'default' => false],
        ];
    }

    public static function appliesTo(): array { return ['password']; }
    public static function defaultMessage(): string { return 'Password does not meet the strength requirements.'; }

    private static function flag(mixed $v): bool { return in_array(strtolower((string) $v), ['1', 'yes', 'true', 'on'], true); }

    public static function serverCheck(mixed $value, array $params, array $record = []): bool
    {
        $s = (string) $value;
        $min = (int) ($params['minLength'] ?? 8);
        if (mb_strlen($s) < $min) return false;
        if (self::flag($params['upper'] ?? true) && !preg_match('/\p{Lu}/u', $s)) return false;
        if (self::flag($params['lower'] ?? true) && !preg_match('/\p{Ll}/u', $s)) return false;
        if (self::flag($params['digit'] ?? true) && !preg_match('/\d/', $s)) return false;
        if (self::flag($params['symbol'] ?? false) && !preg_match('/[^\p{L}\p{N}]/u', $s)) return false;
        return true;
    }

    public static function clientRule(array $params): array
    {
        return ['password' => [
            'minLength' => (int) ($params['minLength'] ?? 8),
            'upper' => self::flag($params['upper'] ?? true),
            'lower' => self::flag($params['lower'] ?? true),
            'digit' => self::flag($params['digit'] ?? true),
            'symbol' => self::flag($params['symbol'] ?? false),
        ]];
    }
}
