<?php
namespace Misuzu\Users;

use Index\XString;
use Misuzu\DateCheck;
use Misuzu\DB;
use Misuzu\Parsers\Parser;

class User {
    public const NAME_MIN_LENGTH =  3;               // Minimum username length
    public const NAME_MAX_LENGTH = 16;               // Maximum username length, unless your name is Flappyzor(WorldwideOnline2018through2019through2020)
    public const NAME_REGEX      = '[A-Za-z0-9-_]+'; // Username character constraint

    // Minimum amount of unique characters for passwords
    public const PASSWORD_UNIQUE = 6;

    // Maximum length of profile about section
    public const PROFILE_ABOUT_MAX_LENGTH = 50000;

    // Maximum length of forum signature
    public const FORUM_SIGNATURE_MAX_LENGTH = 2000;

    public static function validateUsername(string $name): string {
        if($name !== trim($name))
            return 'trim';

        if(str_starts_with(mb_strtolower($name), 'flappyzor'))
            return 'flapp';

        $length = mb_strlen($name);
        if($length < self::NAME_MIN_LENGTH)
            return 'short';
        if($length > self::NAME_MAX_LENGTH)
            return 'long';

        if(!preg_match('#^' . self::NAME_REGEX . '$#u', $name))
            return 'invalid';

        $userId = (int)DB::prepare('SELECT user_id FROM msz_users WHERE username = :username')
            ->bind('username', $name)->fetchColumn();
        if($userId > 0)
            return 'in-use';

        return '';
    }

    public static function usernameValidationErrorString(string $error): string {
        switch($error) {
            case 'trim':
                return 'Your username may not start or end with spaces!';
            case 'short':
                return sprintf('Your username is too short, it has to be at least %d characters!', self::NAME_MIN_LENGTH);
            case 'long':
                return sprintf("Your username is too long, it can't be longer than %d characters!", self::NAME_MAX_LENGTH);
            case 'invalid':
                return 'Your username contains invalid characters.';
            case 'in-use':
                return 'This username is already taken!';
            case 'flapp':
                return 'Your username may not start with Flappyzor!';
            case '':
                return 'This username is correctly formatted!';
            default:
                return 'This username is incorrectly formatted.';
        }
    }

    public static function validateEMailAddress(string $address): string {
        if(filter_var($address, FILTER_VALIDATE_EMAIL) === false)
            return 'format';
        if(!checkdnsrr(mb_substr(mb_strstr($address, '@'), 1), 'MX'))
            return 'dns';

        $userId = (int)DB::prepare('SELECT user_id FROM msz_users WHERE email = :email')
            ->bind('email', $address)->fetchColumn();
        if($userId > 0)
            return 'in-use';

        return '';
    }

    public static function validatePassword(string $password): string {
        if(XString::countUnique($password) < self::PASSWORD_UNIQUE)
            return 'weak';

        return '';
    }

    public static function validateBirthdate(int $year, int $month, int $day, int $yearRange = 100): string {
        if($day !== 0 && $month !== 0) {
            if($year > 0 && ($year < date('Y') - $yearRange || $year > date('Y')))
                return 'year';

            if(!DateCheck::isValidDate($year, $month, $day))
                return 'date';
        }

        return '';
    }

    public static function validateProfileAbout(int $parser, string $text): string {
        if(!Parser::isValid($parser))
            return 'parser';

        $length = strlen($text);
        if($length > self::PROFILE_ABOUT_MAX_LENGTH)
            return 'long';

        return '';
    }

    public static function validateForumSignature(int $parser, string $text): string {
        if(!Parser::isValid($parser))
            return 'parser';

        $length = strlen($text);
        if($length > self::FORUM_SIGNATURE_MAX_LENGTH)
            return 'long';

        return '';
    }
}
